# Conflicts:
#	app/src/main/AndroidManifest.xml
#	app/src/main/java/com/xinyingpower/microphoto/MainActivity.java
#	app/src/main/res/layout/activity_main.xml
serial
liuguijing 2 years ago
commit 17cf85489b

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

@ -31,9 +31,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-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera" />

@ -34,6 +34,8 @@ set(OPENCV_EXTRA_MODULES_PATH D:/Workspace/Github/opencv_contrib/modules)
project("microphoto") project("microphoto")
# message(FATAL_ERROR "OpenCV ${OpenCV_DIR}")
find_package(OpenCV REQUIRED core imgproc highgui) find_package(OpenCV REQUIRED core imgproc highgui)
if(OpenCV_FOUND) if(OpenCV_FOUND)
include_directories(${OpenCV_INCLUDE_DIRS}) include_directories(${OpenCV_INCLUDE_DIRS})
@ -281,12 +283,13 @@ add_library( # Sets the name of the library.
${TERM_CORE_ROOT}/SpecData_I1_SHX.cpp ${TERM_CORE_ROOT}/SpecData_I1_SHX.cpp
${TERM_CORE_ROOT}/SpecData_XY.cpp ${TERM_CORE_ROOT}/SpecData_XY.cpp
${TERM_CORE_ROOT}/SpecData_ZJ.cpp ${TERM_CORE_ROOT}/SpecData_ZJ.cpp
${TERM_CORE_ROOT}/TermClient.cpp
${TERM_CORE_ROOT}/Timer.cpp ${TERM_CORE_ROOT}/Timer.cpp
${TERM_CORE_ROOT}/TimerThread.cpp ${TERM_CORE_ROOT}/TimerThread.cpp
${TERM_CORE_ROOT}/Utils.cpp ${TERM_CORE_ROOT}/Utils.cpp
${TERM_CORE_ROOT}/Client/TerminalService.cpp
${TERM_CORE_ROOT}/Client/Terminal.cpp ${TERM_CORE_ROOT}/Client/Terminal.cpp
${TERM_CORE_ROOT}/Client/Terminal_HN.cpp ${TERM_CORE_ROOT}/Client/Terminal_HN.cpp
${TERM_CORE_ROOT}/Client/Terminal_AH.cpp
${TERM_CORE_ROOT}/Client/Terminal_HEN_ZZ.cpp ${TERM_CORE_ROOT}/Client/Terminal_HEN_ZZ.cpp
${TERM_CORE_ROOT}/Client/Terminal_HEN.cpp ${TERM_CORE_ROOT}/Client/Terminal_HEN.cpp
${TERM_CORE_ROOT}/Client/Terminal_SHX.cpp ${TERM_CORE_ROOT}/Client/Terminal_SHX.cpp

@ -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()
{ {

@ -1,6 +1,7 @@
#include <jni.h> #include <jni.h>
#include <string> #include <string>
#include <TermClient.h> #include <Factory.h>
#include <Client/Terminal.h>
#include "TerminalDevice.h" #include "TerminalDevice.h"
#include "PhoneDevice.h" #include "PhoneDevice.h"
#include "PhoneDevice2.h" #include "PhoneDevice2.h"
@ -15,17 +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.
} }
@ -34,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"
@ -74,7 +74,6 @@ Java_com_xinyingpower_microphoto_MainActivity_takePhoto(
unsigned char id = (unsigned char)channel - 1; unsigned char id = (unsigned char)channel - 1;
Camera2Reader *camera = new Camera2Reader(id); Camera2Reader *camera = new Camera2Reader(id);
const char *pathStr = env->GetStringUTFChars(path, 0); const char *pathStr = env->GetStringUTFChars(path, 0);
const char *fileNameStr = env->GetStringUTFChars(fileName, 0); const char *fileNameStr = env->GetStringUTFChars(fileName, 0);
@ -88,10 +87,10 @@ Java_com_xinyingpower_microphoto_MainActivity_takePhoto(
return JNI_TRUE; return JNI_TRUE;
} }
extern "C" JNIEXPORT jboolean 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(".");
@ -107,35 +106,48 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_init(
JavaVM* vm = NULL; JavaVM* vm = NULL;
jint ret = env->GetJavaVM(&vm); jint ret = env->GetJavaVM(&vm);
// const string& appPath, const string& termId, const string& server, unsigned short port, const string& bindIp // const string& appPath, const string& termId, const string& server, unsigned short port, const string& bindIp
CTermClient& service = CTermClient::GetService(); // CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
// CTerminalDevice* device = new CTerminalDevice(vm, pThis); // CTerminalDevice* device = new CTerminalDevice(vm, pThis);
// CPhoneDevice2* device = new CPhoneDevice2(vm, pThis); // CPhoneDevice2* device = new CPhoneDevice2(vm, pThis);
CTerminal* pTerminal = NewTerminal(GetCurrentProtocol());
CPhoneDevice* device = new CPhoneDevice(vm, pThis); CPhoneDevice* device = new CPhoneDevice(vm, pThis);
bool res = service.InitService(appPathStr, cmdidStr, ipStr, (unsigned short)port, "", device); device->SetListener(pTerminal);
pTerminal->InitServerInfo(appPathStr, cmdidStr, ipStr, port);
pTerminal->SetPacketSize(1 * 1024); // 1K
bool res = pTerminal->Startup(device);
env->ReleaseStringUTFChars(appPath, appPathStr); env->ReleaseStringUTFChars(appPath, appPathStr);
env->ReleaseStringUTFChars(ip, ipStr); env->ReleaseStringUTFChars(ip, ipStr);
env->ReleaseStringUTFChars(cmdid, cmdidStr); env->ReleaseStringUTFChars(cmdid, cmdidStr);
return res ? JNI_TRUE : JNI_FALSE; if (!res)
{
delete pTerminal;
pTerminal = NULL;
}
return reinterpret_cast<jlong>(pTerminal);
} }
extern "C" JNIEXPORT jboolean JNICALL extern "C" JNIEXPORT jboolean JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_notifyToTakePhoto( Java_com_xinyingpower_microphoto_MicroPhotoService_notifyToTakePhoto(
JNIEnv* env, JNIEnv* env,
jobject pThis, jint channel, jint preset, jlong scheduleTime, jstring path, jstring fileName, jboolean sendToCma) { jobject pThis, jlong handler, jint channel, jint preset, jlong scheduleTime, jstring path, jstring fileName, jboolean sendToCma) {
if (channel < 1 || channel > 0xFF) if (channel < 1 || channel > 0xFF)
{ {
return JNI_FALSE; return JNI_FALSE;
} }
CTerminal* pTerminal = CTermClient::GetService().GetTerminal(); CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
if (pTerminal == NULL) if (pTerminal == NULL)
{ {
return JNI_FALSE; return JNI_FALSE;
} }
pTerminal->NotifyToTakePhoto((unsigned int)channel, (unsigned int)preset, 0, (unsigned long)scheduleTime); pTerminal->RequestCapture((unsigned int)channel, (unsigned int)preset, 0, (unsigned long)scheduleTime);
return JNI_TRUE; return JNI_TRUE;
} }
@ -144,9 +156,10 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_notifyToTakePhoto(
extern "C" JNIEXPORT jboolean JNICALL extern "C" JNIEXPORT jboolean JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_sendHeartbeat( Java_com_xinyingpower_microphoto_MicroPhotoService_sendHeartbeat(
JNIEnv* env, JNIEnv* env,
jobject pThis) { jobject pThis,
jlong handler) {
CTerminal* pTerminal = CTermClient::GetService().GetTerminal(); CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
if (pTerminal == NULL) if (pTerminal == NULL)
{ {
return JNI_FALSE; return JNI_FALSE;
@ -161,45 +174,58 @@ 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 uid) { jobject pThis, jlong handler, jlong uid, jlong times) {
IDevice* dev = CTermClient::GetService().GetDevice(); CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
IDevice* dev = pTerminal->GetDevice();
if (dev == NULL) if (dev == NULL)
{ {
return JNI_FALSE; return JNI_FALSE;
} }
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
Java_com_xinyingpower_microphoto_MicroPhotoService_uninit( Java_com_xinyingpower_microphoto_MicroPhotoService_uninit(
JNIEnv* env, JNIEnv* env,
jobject pThis) { jobject pThis, jlong handler) {
CTermClient::GetService().ExitService(); CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
if (pTerminal == NULL)
{
return JNI_FALSE;
}
pTerminal->SignalExit();
pTerminal->Shutdown();
delete pTerminal;
return JNI_TRUE; return JNI_TRUE;
} }
extern "C" JNIEXPORT jlong JNICALL extern "C" JNIEXPORT jlong JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_getHeartbeatDuration( Java_com_xinyingpower_microphoto_MicroPhotoService_getHeartbeatDuration(
JNIEnv* env, JNIEnv* env,
jobject pThis) { jobject pThis, jlong handler) {
// CTermClient::GetService().ExitService(); CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
if (pTerminal == NULL)
{
return DEFAULT_HEARTBEAT_DURATION;
}
return 60000; return pTerminal->GetHeartbeatDuration();
} }
extern "C" JNIEXPORT jlongArray JNICALL extern "C" JNIEXPORT jlongArray JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_getPhotoTimeData( Java_com_xinyingpower_microphoto_MicroPhotoService_getPhotoTimeData(
JNIEnv* env, JNIEnv* env,
jobject pThis) { jobject pThis, jlong handler) {
CTerminal* pTerminal = CTermClient::GetService().GetTerminal(); CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
if (pTerminal == NULL) if (pTerminal == NULL)
{ {
return NULL; return NULL;
@ -259,13 +285,13 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_getPhotoTimeData(
return data; return data;
} }
/*
extern "C" JNIEXPORT jlongArray JNICALL extern "C" JNIEXPORT jlongArray JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_getNextScheduleItem( Java_com_xinyingpower_microphoto_MicroPhotoService_getNextScheduleItem(
JNIEnv* env, JNIEnv* env,
jobject pThis) { jobject pThis, jlong handler) {
CTerminal* pTerminal = CTermClient::GetService().GetTerminal(); CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
if (pTerminal == NULL) if (pTerminal == NULL)
{ {
return NULL; return NULL;
@ -324,3 +350,4 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_getNextScheduleItem(
return data; return data;
} }
*/

@ -17,9 +17,8 @@
*/ */
#define LOG_TAG "CameraTestHelpers" #define LOG_TAG "CameraTestHelpers"
#include <AndroidHelper.h>
#include "PhoneDevice.h" #include "PhoneDevice.h"
#include "TermClient.h"
#include <opencv2/opencv.hpp> #include <opencv2/opencv.hpp>
#include <opencv2/core.hpp> #include <opencv2/core.hpp>
@ -34,17 +33,10 @@
#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_"
// 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
// ranges // ranges
// are normalized to eight bits. // are normalized to eight bits.
@ -143,46 +135,73 @@ CPhoneDevice::CPhoneCamera::CPhoneCamera(CPhoneDevice* dev, int32_t width, int32
{ {
} }
void CPhoneDevice::CPhoneCamera::on_image(const cv::Mat& rgb) const bool CPhoneDevice::CPhoneCamera::on_image(const cv::Mat& rgb) const
{ {
if (m_dev != NULL) if (m_dev != NULL)
{ {
m_dev->OnImageReady(rgb); return m_dev->OnImageReady(rgb);
}
return false;
}
void CPhoneDevice::CPhoneCamera::on_error(const std::string& msg) const
{
if (m_dev != NULL)
{
m_dev->onError(msg);
} }
} }
CPhoneDevice::CPhoneDevice(JavaVM* vm, jobject service) CPhoneDevice::CPhoneDevice(JavaVM* vm, jobject service)
{ {
mCamera = NULL;
m_listener = NULL;
mHeartbeatStartTime = 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);
mHeartbeatStartTime = 0;
mHeartbeatDuration = 0;
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");
mRequestWakelockMid = env->GetMethodID(classService, "requestWakelock", "(Ljava/lang/String;J)V");
mReleaseWakelockMid = env->GetMethodID(classService, "releaseWakelock", "(Ljava/lang/String;)V");
env->DeleteLocalRef(classService); env->DeleteLocalRef(classService);
if (attached) if (didAttachThread)
{ {
vm->DetachCurrentThread(); vm->DetachCurrentThread();
} }
m_timerUidFeed = time(NULL); m_timerUidFeed = time(NULL) * 1000;
m_wakelockIdFeed = (unsigned long)m_timerUidFeed;
} }
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();
} }
@ -198,17 +217,27 @@ 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;
ret = env->CallBooleanMethod(m_javaService, mUpdateTimeMid, timeInMillis);
if (didAttachThread)
{ {
jlong timeInMillis = ((jlong)ts) * 1000;
ret = env->CallBooleanMethod(m_javaService, mUpdateTimeMid, timeInMillis);
m_vm->DetachCurrentThread(); m_vm->DetachCurrentThread();
} }
return (ret == JNI_TRUE); return (ret == JNI_TRUE);
} }
bool CPhoneDevice::UpdateSchedules()
{
return true;
}
bool CPhoneDevice::QuerySystemProperties(map<string, string>& properties) bool CPhoneDevice::QuerySystemProperties(map<string, string>& properties)
{ {
char value[PROP_VALUE_MAX] = { 0 }; char value[PROP_VALUE_MAX] = { 0 };
@ -220,11 +249,9 @@ bool CPhoneDevice::QuerySystemProperties(map<string, string>& properties)
__system_property_get("ro.product.model", value); __system_property_get("ro.product.model", value);
properties[PROP_MODEL] = value; properties[PROP_MODEL] = value;
__system_property_get("ro.product.manufacturer", value); __system_property_get("ro.product.manufacturer", value);
properties[PROP_BS_MANU] = value; properties[PROP_BS_MANU] = value;
properties[PROP_BS_ID] = "SHXY"; properties[PROP_BS_ID] = "SHXY";
__system_property_get("ro.build.version.release", value); __system_property_get("ro.build.version.release", value);
@ -239,7 +266,6 @@ bool CPhoneDevice::QuerySystemProperties(map<string, string>& properties)
__system_property_get("phone.imei", value); __system_property_get("phone.imei", value);
properties[PROP_IMEI] = value; properties[PROP_IMEI] = value;
return true; return true;
} }
@ -254,18 +280,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();
} }
@ -280,12 +311,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);
if (didAttachThread)
{ {
ret = env->CallBooleanMethod(m_javaService, mUnregisterTimerMid, (jlong)uid);
m_vm->DetachCurrentThread(); m_vm->DetachCurrentThread();
} }
@ -297,7 +334,67 @@ bool CPhoneDevice::UnregisterTimer(IDevice::timer_uid_t uid)
return false; return false;
} }
bool CPhoneDevice::FireTimer(timer_uid_t uid) unsigned long CPhoneDevice::RequestWakelock(unsigned long timeout)
{
unsigned long wakelockId = m_wakelockIdFeed.fetch_add(1);
std::string name = WAKELOCK_NAME;
name += to_string(wakelockId);
ALOGI("RequestWakelock=%lld",wakelockId);
jboolean ret = JNI_FALSE;
JNIEnv* env = NULL;
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());
jlong jtimeout = (jlong)timeout;
env->CallVoidMethod(m_javaService, mRequestWakelockMid, jname, jtimeout);
// env->ReleaseStringUTFChars(jname, name.c_str());
env->DeleteLocalRef(jname);
if (didAttachThread)
{
m_vm->DetachCurrentThread();
}
return wakelockId;
}
bool CPhoneDevice::ReleaseWakelock(unsigned long wakelock)
{
ALOGI("ReleaseWakelock=%lld", wakelock);
std::string name = WAKELOCK_NAME;
name += to_string(wakelock);
jboolean ret = JNI_FALSE;
JNIEnv* env = NULL;
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());
env->CallVoidMethod(m_javaService, mReleaseWakelockMid, jname);
env->DeleteLocalRef(jname);
// env->ReleaseStringUTFChars(jname, name.c_str());
if (didAttachThread)
{
m_vm->DetachCurrentThread();
}
return true;
}
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())
@ -306,21 +403,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;
} }
@ -332,10 +429,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();
@ -346,43 +449,100 @@ IDevice::timer_uid_t CPhoneDevice::RegisterHeartbeat(unsigned int timerType, uns
bool CPhoneDevice::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<OSD_INFO>& osds, const string& path) bool CPhoneDevice::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); if (mCamera != NULL)
{
delete mCamera;
mCamera = NULL;
}
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;
mCamera = new CPhoneCamera(this, photoInfo.width, photoInfo.height); mCamera = new CPhoneCamera(this, photoInfo.width, photoInfo.height);
mCamera->open(to_string(photoInfo.channel - 1).c_str()); if (mCamera->open(to_string(photoInfo.channel - 1).c_str()) == 0)
{
}
else
{
delete mCamera;
mCamera = NULL;
return false;
}
return true; return true;
} }
void CPhoneDevice::OnImageReady(const cv::Mat& mat) const bool CPhoneDevice::CloseCamera()
{ {
if (mCamera != NULL)
{
delete mCamera;
mCamera = NULL;
}
return true;
}
bool CPhoneDevice::OnImageReady(const cv::Mat& mat) const
{
int baseline = 0; int baseline = 0;
cv::Size textSize, textSize2; cv::Size textSize, textSize2;
double fontScale = 1; // base 1024
double height = mat.size().height;
double width = mat.size().width;
double ratio = std::min(height / 1024, width / 1920);
fontScale = fontScale * ratio;
double thickness1 = 4 * ratio;
double thickness2 = 2 * ratio;
for (vector<OSD_INFO>::const_iterator it = mOsds.cbegin(); it != mOsds.cend(); ++it) for (vector<OSD_INFO>::const_iterator it = mOsds.cbegin(); it != mOsds.cend(); ++it)
{ {
// getTextSize(value, font, scale, 1, &bottom); // getTextSize(value, font, scale, 1, &bottom);
textSize = cv::getTextSize(it->text, cv::FONT_HERSHEY_COMPLEX, 1, 4, &baseline); textSize = cv::getTextSize(it->text, cv::FONT_HERSHEY_COMPLEX, fontScale, thickness1, &baseline);
cv::Point pt(it->x, it->y + textSize.height); cv::Point pt(it->x * ratio, it->y * ratio + textSize.height);
putText(mat, it->text, pt, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(0, 0, 0), 4,cv::LINE_AA); putText(mat, it->text, pt, cv::FONT_HERSHEY_COMPLEX, fontScale, cv::Scalar(0, 0, 0), thickness1,cv::LINE_AA);
textSize2 = cv::getTextSize(it->text, cv::FONT_HERSHEY_COMPLEX, 1, 2, &baseline); textSize2 = cv::getTextSize(it->text, cv::FONT_HERSHEY_COMPLEX, fontScale, thickness2, &baseline);
pt.y -= (textSize.height - textSize2.height) / 2; pt.y -= (textSize.height - textSize2.height) / 2;
putText(mat, it->text, pt, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 2,cv::LINE_AA); putText(mat, it->text, pt, cv::FONT_HERSHEY_COMPLEX, fontScale, cv::Scalar(255, 255, 255), thickness2,cv::LINE_AA);
} }
vector <int> compression_params; vector <int> compression_params;
compression_params.push_back(cv::IMWRITE_JPEG_QUALITY); compression_params.push_back(cv::IMWRITE_JPEG_QUALITY);
compression_params.push_back(80); compression_params.push_back(mPhotoInfo.quality);
bool res = cv::imwrite(mPath.c_str(), mat, compression_params); if (!std::filesystem::exists(std::filesystem::path(mPath)))
{
bool res = cv::imwrite(mPath.c_str(), mat, compression_params);
if (!res)
{
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));
return res;
}
else
{
ALOGI("Photo file exists: %s", mPath.c_str());
}
// mCamera->close();
// delete mCamera;
// mCamera = NULL;
return true;
}
void CPhoneDevice::onError(const std::string& msg) const
{
// XFLOG(XFLOG_SEVERITY_ERROR, "Failed to Take Photo: %s", msg.c_str());
TakePhotoCb(res, mPhotoInfo, mPath, time(NULL)); ALOGE("Failed to Take Photo: %s", msg.c_str());
delete mCamera; // mCamera->close();
mCamera = NULL;
TakePhotoCb(false, mPhotoInfo, mPath, 0);
} }
std::string CPhoneDevice::GetFileName() const std::string CPhoneDevice::GetFileName() const

@ -11,21 +11,17 @@
#include <map> #include <map>
#include <atomic> #include <atomic>
#include <filesystem>
#include <camera/NdkCameraManager.h> #include <camera/NdkCameraManager.h>
#include <camera/NdkCameraError.h> #include <camera/NdkCameraError.h>
#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>
#include "Camera2Helper.h" #include "camera2/Camera2Helper.h"
#include "camera2/ndkcamera.h" #include "camera2/ndkcamera.h"
@ -37,14 +33,18 @@ public:
virtual void SetListener(IListener* listener); virtual void SetListener(IListener* listener);
virtual bool UpdateTime(time_t ts); virtual bool UpdateTime(time_t ts);
virtual bool UpdateSchedules();
virtual bool QuerySystemProperties(map<string, string>& properties); virtual bool QuerySystemProperties(map<string, string>& properties);
virtual bool Reboot(); virtual bool Reboot();
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 timer_uid_t RegisterTimer(unsigned int timerType, unsigned int timeout); virtual bool CloseCamera();
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 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);
@ -65,7 +65,8 @@ protected:
return false; return false;
} }
void OnImageReady(const cv::Mat& mat) const; bool OnImageReady(const cv::Mat& mat) const;
void onError(const std::string& msg) const;
protected: protected:
@ -77,18 +78,23 @@ protected:
jmethodID mUnregisterTimerMid; jmethodID mUnregisterTimerMid;
jmethodID mUpdateTimeMid; jmethodID mUpdateTimeMid;
jmethodID mRequestWakelockMid;
jmethodID mReleaseWakelockMid;
std::string mPath; std::string mPath;
IDevice::PHOTO_INFO mPhotoInfo; IDevice::PHOTO_INFO mPhotoInfo;
vector<IDevice::OSD_INFO> mOsds; vector<IDevice::OSD_INFO> mOsds;
IListener* m_listener; IListener* m_listener;
atomic_ulong m_timerUidFeed; atomic_ulong m_timerUidFeed;
atomic_ulong m_wakelockIdFeed;
std::map<IDevice::timer_uid_t, unsigned long> mTimers; std::map<IDevice::timer_uid_t, unsigned long> mTimers;
class CPhoneCamera : public NdkCamera { class CPhoneCamera : public NdkCamera {
public: public:
CPhoneCamera(CPhoneDevice* dev, int32_t width, int32_t height); CPhoneCamera(CPhoneDevice* dev, int32_t width, int32_t height);
virtual void on_image(const cv::Mat& rgb) const; virtual bool on_image(const cv::Mat& rgb) const;
virtual void on_error(const std::string& msg) const;
protected: protected:
CPhoneDevice* m_dev; CPhoneDevice* m_dev;
@ -98,7 +104,6 @@ protected:
time_t mHeartbeatStartTime; time_t mHeartbeatStartTime;
unsigned int mHeartbeatDuration; unsigned int mHeartbeatDuration;
}; };

@ -19,7 +19,6 @@
#define LOG_TAG "CameraTestHelpers" #define LOG_TAG "CameraTestHelpers"
#include "PhoneDevice2.h" #include "PhoneDevice2.h"
#include "TermClient.h"
#include <opencv2/opencv.hpp> #include <opencv2/opencv.hpp>
#include <opencv2/core.hpp> #include <opencv2/core.hpp>
@ -33,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
@ -80,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);
@ -103,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)
{ {
@ -121,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;
bool res = GetJniEnv(m_vm, &env, attached);
if (!res)
{
ALOGE("Failed to get JNI Env");
return false;
}
jlong timeInMillis = ((jlong)ts) * 1000;
ret = env->CallBooleanMethod(m_javaService, mUpdateTimeMid, timeInMillis);
if (attached) if (attached)
{ {
jlong timeInMillis = ((jlong)ts) * 1000;
ret = env->CallBooleanMethod(m_javaService, mUpdateTimeMid, timeInMillis);
m_vm->DetachCurrentThread(); m_vm->DetachCurrentThread();
} }
@ -145,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;
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);
if (attached) if (attached)
{ {
ret = env->CallBooleanMethod(m_javaService, mRegisterTimerMid, (jlong)uid, (jint)timeout);
m_vm->DetachCurrentThread(); m_vm->DetachCurrentThread();
} }
@ -165,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;
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);
if (attached) if (attached)
{ {
ret = env->CallBooleanMethod(m_javaService, mUnregisterTimerMid, (jlong)uid);
m_vm->DetachCurrentThread(); m_vm->DetachCurrentThread();
} }
@ -214,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;
bool res = GetJniEnv(m_vm, &env, attached);
if (!res)
{
ALOGE("Failed to get JNI Env");
return 0;
}
env->CallVoidMethod(m_javaService, mRegisterHeartbeatMid, (jint)timeout);
if (attached) if (attached)
{ {
env->CallVoidMethod(m_javaService, mRegisterHeartbeatMid, (jint)timeout);
m_vm->DetachCurrentThread(); m_vm->DetachCurrentThread();
} }
@ -226,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;
@ -247,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;
@ -287,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)
{ {
@ -304,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);
@ -329,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;
} }
@ -344,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);
@ -363,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;
} }
@ -389,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);
@ -475,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;
} }
@ -493,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;
@ -546,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;
@ -563,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;
@ -584,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:
@ -609,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);
@ -858,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,15 +17,10 @@
#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>
#include "Camera2Helper.h" #include "camera2/Camera2Helper.h"
class CPhoneDevice2 : public IDevice class CPhoneDevice2 : public IDevice
{ {

@ -0,0 +1,201 @@
/* ---------------------------------------------------------------------
* Luiz Carlos doleron @ 2021
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero Public License for more details.
* ----------------------------------------------------------------------
*/
#ifndef _GET_CPU_USAGE_LINUX_
#define _GET_CPU_USAGE_LINUX_
#include <iostream>
#include <fstream>
#include <sstream>
#include <sys/statvfs.h>
namespace get_system_usage_linux
{
struct CPU_stats
{
// see http://www.linuxhowtos.org/manpages/5/proc.htm
int user;
int nice;
int system;
int idle;
int iowait;
int irq;
int softirq;
int steal;
int guest;
int guest_nice;
int get_total_idle()
const {
return idle + iowait;
}
int get_total_active()
const {
return user + nice + system + irq + softirq + steal + guest + guest_nice;
}
};
struct Memory_stats
{
int total_memory;
int available_memory;
int total_swap;
int free_swap;
float get_memory_usage() {
const float result = static_cast<float>(total_memory - available_memory) / total_memory;
return result;
}
float get_swap_usage() {
const float result = static_cast<float>(total_swap - free_swap) / total_swap;
return result;
}
};
inline CPU_stats read_cpu_data()
{
CPU_stats result;
std::ifstream proc_stat("/proc/stat");
if (proc_stat.good())
{
std::string line;
getline(proc_stat, line);
unsigned int *stats_p = (unsigned int *)&result;
std::stringstream iss(line);
std::string cpu;
iss >> cpu;
while (iss >> *stats_p)
{
stats_p++;
};
}
proc_stat.close();
return result;
}
inline int get_val(const std::string &target, const std::string &content) {
int result = -1;
std::size_t start = content.find(target);
if (start != std::string::npos) {
int begin = start + target.length();
std::size_t end = content.find("kB", start);
std::string substr = content.substr(begin, end - begin);
result = std::stoi(substr);
}
return result;
}
inline Memory_stats read_memory_data()
{
Memory_stats result;
std::ifstream proc_meminfo("/proc/meminfo");
if (proc_meminfo.good())
{
std::string content((std::istreambuf_iterator<char>(proc_meminfo)),
std::istreambuf_iterator<char>());
result.total_memory = get_val("MemTotal:", content);
result.total_swap = get_val("SwapTotal:", content);
result.free_swap = get_val("SwapFree:", content);
result.available_memory = get_val("MemAvailable:", content);
}
proc_meminfo.close();
return result;
}
inline float get_cpu_usage(const CPU_stats &first, const CPU_stats &second) {
const float active_time = static_cast<float>(second.get_total_active() - first.get_total_active());
const float idle_time = static_cast<float>(second.get_total_idle() - first.get_total_idle());
const float total_time = active_time + idle_time;
return active_time / total_time;
}
inline float get_disk_usage(const std::string & disk) {
struct statvfs diskData;
statvfs(disk.c_str(), &diskData);
auto total = diskData.f_blocks;
auto free = diskData.f_bfree;
auto diff = total - free;
float result = static_cast<float>(diff) / total;
return result;
}
//see https://unix.stackexchange.com/questions/304845/discrepancy-between-number-of-cores-and-thermal-zones-in-sys-class-thermal/342023
inline int find_thermalzone_index() {
int result = 0;
bool stop = false;
// 20 must stop anyway
for (int i = 0; !stop && i < 20; ++i) {
std::ifstream thermal_file("/sys/class/thermal/thermal_zone" + std::to_string(i) + "/type");
if (thermal_file.good())
{
std::string line;
getline(thermal_file, line);
if (line.compare("x86_pkg_temp") == 0) {
result = i;
stop = true;
}
} else {
stop = true;
}
thermal_file.close();
}
return result;
}
inline int get_thermalzone_temperature(int thermal_index) {
int result = -1;
std::ifstream thermal_file("/sys/class/thermal/thermal_zone" + std::to_string(thermal_index) + "/temp");
if (thermal_file.good())
{
std::string line;
getline(thermal_file, line);
std::stringstream iss(line);
iss >> result;
} else {
throw std::invalid_argument(std::to_string(thermal_index) + " doesn't refer to a valid thermal zone.");
}
thermal_file.close();
return result;
}
}
#endif

@ -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;

@ -19,6 +19,8 @@
#include <android/log.h> #include <android/log.h>
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include "mat.h" #include "mat.h"
#include "Camera2Helper.h"
#include <AndroidHelper.h>
static void onDisconnected(void* context, ACameraDevice* device) static void onDisconnected(void* context, ACameraDevice* device)
{ {
@ -27,7 +29,9 @@ static void onDisconnected(void* context, ACameraDevice* device)
static void onError(void* context, ACameraDevice* device, int error) static void onError(void* context, ACameraDevice* device, int error)
{ {
__android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onError %p %d", device, error); std::string msg = "NdkCamera error code=" + std::to_string(error);
((NdkCamera*)context)->on_error(msg);
// __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onError %p %d", device, error);
} }
static void onImageAvailable(void* context, AImageReader* reader) static void onImageAvailable(void* context, AImageReader* reader)
@ -67,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)
@ -76,6 +80,12 @@ NdkCamera::NdkCamera(int32_t width, int32_t height)
camera_orientation = 0; camera_orientation = 0;
m_firstFrame = true; m_firstFrame = true;
mWidth = width;
mHeight = height;
hdrSupported = false;
nightModeSupported = false;
nightPortraitModeSupported = false;
camera_manager = 0; camera_manager = 0;
camera_device = 0; camera_device = 0;
@ -86,23 +96,6 @@ NdkCamera::NdkCamera(int32_t width, int32_t height)
capture_session_output_container = 0; capture_session_output_container = 0;
capture_session_output = 0; capture_session_output = 0;
capture_session = 0; capture_session = 0;
// setup imagereader and its surface
{
AImageReader_new(width, height, AIMAGE_FORMAT_YUV_420_888, /*maxImages*/2, &image_reader);
AImageReader_ImageListener listener;
listener.context = this;
listener.onImageAvailable = ::onImageAvailable;
AImageReader_setImageListener(image_reader, &listener);
AImageReader_getWindow(image_reader, &image_reader_surface);
// ANativeWindow_setBuffersGeometry(image_reader_surface, width, height,WINDOW_FORMAT_RGBX_8888);
ANativeWindow_acquire(image_reader_surface);
}
} }
NdkCamera::~NdkCamera() NdkCamera::~NdkCamera()
@ -124,7 +117,7 @@ NdkCamera::~NdkCamera()
int NdkCamera::open(const char* cameraId) int NdkCamera::open(const char* cameraId)
{ {
__android_log_print(ANDROID_LOG_WARN, "NdkCamera", "open"); __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "DBG::open %s", cameraId);
// camera_facing = _camera_facing; // camera_facing = _camera_facing;
@ -132,6 +125,10 @@ int NdkCamera::open(const char* cameraId)
// find front camera // find front camera
std::string camera_id; std::string camera_id;
bool foundIt = false;
DisplayDimension disp(mWidth, mHeight);
DisplayDimension foundRes = disp;
{ {
ACameraIdList* camera_id_list = 0; ACameraIdList* camera_id_list = 0;
ACameraManager_getCameraIdList(camera_manager, &camera_id_list); ACameraManager_getCameraIdList(camera_manager, &camera_id_list);
@ -181,6 +178,95 @@ int NdkCamera::open(const char* cameraId)
camera_orientation = orientation; camera_orientation = orientation;
{
ACameraMetadata_const_entry e = { 0 };
ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &e);
// format of the data: format, width, height, input?, type int32
// DisplayDimension foundRes(4000, 4000);
// DisplayDimension maxJPG(0, 0);
for (int i = 0; i < e.count; i += 4) {
int32_t input = e.data.i32[i + 3];
int32_t format = e.data.i32[i + 0];
if (input) continue;
if (format == AIMAGE_FORMAT_YUV_420_888 || format == AIMAGE_FORMAT_JPEG) {
DisplayDimension res(e.data.i32[i + 1], e.data.i32[i + 2]);
if (!disp.IsSameRatio(res)) continue;
if (format == AIMAGE_FORMAT_YUV_420_888 && res > disp) {
foundIt = true;
foundRes = res;
}/* else if (format == AIMAGE_FORMAT_JPEG && res > maxJPG) {
maxJPG = res;
}*/
}
}
}
{
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);
break; break;
@ -189,11 +275,36 @@ int NdkCamera::open(const char* cameraId)
ACameraManager_deleteCameraIdList(camera_id_list); ACameraManager_deleteCameraIdList(camera_id_list);
} }
if (camera_id.empty()) if (camera_id.empty() || !foundIt)
{ {
return 1; return 1;
} }
if (camera_id == "1")
{
camera_facing = 1;
}
mCameraId = camera_id;
camera_status_t res = ACAMERA_OK;
// setup imagereader and its surface
{
AImageReader_new(foundRes.width(), foundRes.height(), AIMAGE_FORMAT_YUV_420_888, /*maxImages*/2, &image_reader);
AImageReader_ImageListener listener;
listener.context = this;
listener.onImageAvailable = ::onImageAvailable;
AImageReader_setImageListener(image_reader, &listener);
AImageReader_getWindow(image_reader, &image_reader_surface);
// ANativeWindow_setBuffersGeometry(image_reader_surface, width, height,WINDOW_FORMAT_RGBX_8888);
ANativeWindow_acquire(image_reader_surface);
}
__android_log_print(ANDROID_LOG_WARN, "NdkCamera", "open %s %d", camera_id.c_str(), camera_orientation); __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "open %s %d", camera_id.c_str(), camera_orientation);
// open camera // open camera
@ -203,16 +314,69 @@ int NdkCamera::open(const char* cameraId)
camera_device_state_callbacks.onDisconnected = onDisconnected; camera_device_state_callbacks.onDisconnected = onDisconnected;
camera_device_state_callbacks.onError = onError; camera_device_state_callbacks.onError = onError;
ACameraManager_openCamera(camera_manager, camera_id.c_str(), &camera_device_state_callbacks, &camera_device); res = ACameraManager_openCamera(camera_manager, camera_id.c_str(), &camera_device_state_callbacks, &camera_device);
if (res != ACAMERA_OK)
{
return 1;
}
} }
std::this_thread::sleep_for(std::chrono::milliseconds(128)); std::this_thread::sleep_for(std::chrono::milliseconds(128));
// capture request // capture request
{ {
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 aeMode = ACAMERA_CONTROL_AE_MODE_ON;
res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AE_MODE, 1, &aeMode);
// 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 aeMode = ACAMERA_CONTROL_AE_MODE_OFF;
res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AE_MODE, 1, &aeMode);
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);
ACameraOutputTarget_create(image_reader_surface, &image_reader_target); int32_t sensitivity = sensitivityRange.value(2);
ACaptureRequest_addTarget(capture_request, image_reader_target); 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);
}
uint8_t afMode = ACAMERA_CONTROL_AF_MODE_CONTINUOUS_VIDEO;
res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AF_MODE, 1, &afMode);
uint8_t awbMode = ACAMERA_CONTROL_AWB_MODE_AUTO;
res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AWB_MODE, 1, &awbMode);
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 = ACaptureRequest_addTarget(capture_request, image_reader_target);
} }
// capture session // capture session
@ -223,7 +387,7 @@ int NdkCamera::open(const char* cameraId)
camera_capture_session_state_callbacks.onReady = onSessionReady; camera_capture_session_state_callbacks.onReady = onSessionReady;
camera_capture_session_state_callbacks.onClosed = onSessionClosed; camera_capture_session_state_callbacks.onClosed = onSessionClosed;
ACaptureSessionOutputContainer_create(&capture_session_output_container); res = ACaptureSessionOutputContainer_create(&capture_session_output_container);
ACaptureSessionOutput_create(image_reader_surface, &capture_session_output); ACaptureSessionOutput_create(image_reader_surface, &capture_session_output);
@ -235,14 +399,14 @@ 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;
camera_capture_session_capture_callbacks.onCaptureBufferLost = 0; camera_capture_session_capture_callbacks.onCaptureBufferLost = 0;
ACameraCaptureSession_setRepeatingRequest(capture_session, &camera_capture_session_capture_callbacks, 1, &capture_request, nullptr); // ACameraCaptureSession_setRepeatingRequest(capture_session, &camera_capture_session_capture_callbacks, 1, &capture_request, nullptr);
// ACameraCaptureSession_capture(capture_session, &camera_capture_session_capture_callbacks, 1, &capture_request,nullptr); ACameraCaptureSession_capture(capture_session, &camera_capture_session_capture_callbacks, 1, &capture_request,nullptr);
} }
return 0; return 0;
@ -250,7 +414,7 @@ int NdkCamera::open(const char* cameraId)
void NdkCamera::close() void NdkCamera::close()
{ {
__android_log_print(ANDROID_LOG_WARN, "NdkCamera", "close"); __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "DBG::close %s", mCameraId.c_str());
if (capture_session) if (capture_session)
{ {
@ -316,7 +480,6 @@ void NdkCamera::onImageAvailable(AImageReader* reader)
// return; // return;
} }
int32_t format; int32_t format;
AImage_getFormat(image, &format); AImage_getFormat(image, &format);
@ -397,12 +560,15 @@ 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_image(const cv::Mat& rgb) const bool NdkCamera::on_image(const cv::Mat& rgb) const
{ {
return false;
} }
void NdkCamera::on_image(const unsigned char* nv21, int nv21_width, int nv21_height) const void NdkCamera::on_image(const unsigned char* nv21, int nv21_width, int nv21_height) const
@ -413,7 +579,8 @@ void NdkCamera::on_image(const unsigned char* nv21, int nv21_width, int nv21_hei
int h = 0; int h = 0;
int rotate_type = 0; int rotate_type = 0;
// TODO !!!??? // TODO !!!???
int co = camera_orientation > 0 ? camera_orientation - 90 : camera_orientation; // int co = camera_orientation > 0 ? camera_orientation + 90 : camera_orientation;
int co = (camera_orientation + 90) % 360;
// int co = 0; // int co = 0;
if (co == 0) if (co == 0)
{ {
@ -464,3 +631,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", exTime, 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();
@ -33,14 +46,32 @@ public:
void close(); void close();
void onImageAvailable(AImageReader* reader); void onImageAvailable(AImageReader* reader);
virtual void on_image(const cv::Mat& rgb) const; virtual bool on_image(const cv::Mat& rgb) const;
virtual void on_error(const std::string& msg) const;
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;
bool m_firstFrame; bool m_firstFrame;
int32_t mWidth;
int32_t mHeight;
std::string mCameraId;
bool hdrSupported;
bool nightModeSupported;
bool nightPortraitModeSupported;
bool afSupported;
bool awbSupported;
// int64_t exposureTime_;
RangeValue<int64_t> exposureRange;
// int32_t sensitivity_;
RangeValue<int32_t> sensitivityRange;
private: private:
ACameraManager* camera_manager; ACameraManager* camera_manager;

@ -77,7 +77,9 @@ class counting_semaphore {
static void throw_errno(const char* what_arg) static void throw_errno(const char* what_arg)
{ {
#ifndef __ANDROID__
throw std::system_error(std::error_code(errno, std::generic_category()), what_arg); throw std::system_error(std::error_code(errno, std::generic_category()), what_arg);
#endif
} }
bool do_try_acquirewait(const std::chrono::system_clock::time_point& tp) bool do_try_acquirewait(const std::chrono::system_clock::time_point& tp)

@ -0,0 +1,169 @@
package com.xinyingpower.microphoto;
import android.app.AlarmManager;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.telephony.CellLocation;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.telephony.cdma.CdmaCellLocation;
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;
public class DeviceUtil {
public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
public static final int SIGNAL_STRENGTH_POOR = 1;
public static final int SIGNAL_STRENGTH_MODERATE = 2;
public static final int SIGNAL_STRENGTH_GOOD = 3;
public static final int SIGNAL_STRENGTH_GREAT = 4;
public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
//无 ,低劣的 ,适度的 ,好 ,优异的
public static final String[] SIGNAL_STRENGTH_NAMES = {
"none", "poor", "moderate", "good", "great"
};
public static String getNetworkType(Context context) {
// ConnectionManager instance
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = connectivityManager.getActiveNetworkInfo();
// If not connected, "-" will be displayed
if (ni == null || !ni.isConnected()) return "";
// If Connected to Wifi
if (ni.getType() == ConnectivityManager.TYPE_WIFI) return "WIFI";
// If Connected to Mobile
String subTypeName = "";
if (ni.getType() == ConnectivityManager.TYPE_MOBILE) {
int subType = ni.getSubtype();
switch (subType) {
case TelephonyManager.NETWORK_TYPE_GPRS:
case TelephonyManager.NETWORK_TYPE_EDGE:
case TelephonyManager.NETWORK_TYPE_CDMA:
case TelephonyManager.NETWORK_TYPE_1xRTT:
case TelephonyManager.NETWORK_TYPE_IDEN:
case TelephonyManager.NETWORK_TYPE_GSM:
subTypeName = "2G";
break;
case TelephonyManager.NETWORK_TYPE_UMTS:
case TelephonyManager.NETWORK_TYPE_EVDO_0:
case TelephonyManager.NETWORK_TYPE_EVDO_A:
case TelephonyManager.NETWORK_TYPE_HSDPA:
case TelephonyManager.NETWORK_TYPE_HSUPA:
case TelephonyManager.NETWORK_TYPE_HSPA:
case TelephonyManager.NETWORK_TYPE_EVDO_B:
case TelephonyManager.NETWORK_TYPE_EHRPD:
case TelephonyManager.NETWORK_TYPE_HSPAP:
case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
subTypeName = "3G";
break;
case TelephonyManager.NETWORK_TYPE_LTE:
case TelephonyManager.NETWORK_TYPE_IWLAN:
case 19:
subTypeName = "4G";
break;
case TelephonyManager.NETWORK_TYPE_NR:
subTypeName = "5G";
break;
default:
subTypeName = "";
break;
}
}
return subTypeName;
}
public static void getPhoneState(Context context) {
final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener MyPhoneListener = new PhoneStateListener() {
@Override
//获取对应网络的ID这个方法在这个程序中没什么用处
public void onCellLocationChanged(CellLocation location) {
if (location instanceof GsmCellLocation) {
int CID = ((GsmCellLocation) location).getCid();
} else if (location instanceof CdmaCellLocation) {
int ID = ((CdmaCellLocation) location).getBaseStationId();
}
}
//系统自带的服务监听器,实时监听网络状态
@Override
public void onServiceStateChanged(ServiceState serviceState) {
super.onServiceStateChanged(serviceState);
}
//这个是我们的主角,就是获取对应网络信号强度
@Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
//这个ltedbm 是4G信号的值
String signalinfo = signalStrength.toString();
String[] parts = signalinfo.split(" ");
String ltedbm = parts[9];
//这个dbm 是2G和3G信号的值
int asu = signalStrength.getGsmSignalStrength();
int dbm = -113 + 2 * asu;
if (telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE) {
Log.i("NetWorkUtil", "网络LTE 信号强度:" + ltedbm + "======Detail:" + signalinfo);
} else if (telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_HSDPA ||
telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_HSPA ||
telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_HSUPA ||
telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS) {
String bin;
if (dbm > -75) {
bin = "网络很好";
} else if (dbm > -85) {
bin = "网络不错";
} else if (dbm > -95) {
bin = "网络还行";
} else if (dbm > -100) {
bin = "网络很差";
} else {
bin = "网络错误";
}
Log.i("NetWorkUtil", "网络WCDMA 信号值:" + dbm + "========强度:" + bin + "======Detail:" + signalinfo);
} else {
String bin;
if (asu < 0 || asu >= 99) bin = "网络错误";
else if (asu >= 16) bin = "网络很好";
else if (asu >= 8) bin = "网络不错";
else if (asu >= 4) bin = "网络还行";
else bin = "网络很差";
Log.i("NetWorkUtil", "网络GSM 信号值:" + dbm + "========强度:" + bin + "======Detail:" + signalinfo);
}
super.onSignalStrengthsChanged(signalStrength);
}
};
telephonyManager.listen(MyPhoneListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
}
public static boolean updateTime(Context context, long timeInMillis) {
boolean res = false;
try {
// Calendar c = Calendar.getInstance();
// c.set(2010, 1, 1, 12, 00, 00);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.setTime(timeInMillis);
res = true;
} catch (Exception ex) {
int aa = 0;
}
return true;
}
}

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

@ -1,9 +1,11 @@
package com.xinyingpower.microphoto; package com.xinyingpower.microphoto;
import android.Manifest; import android.Manifest;
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.location.Location; import android.location.Location;
@ -13,17 +15,16 @@ import android.media.MediaRecorder;
import android.os.Build; import android.os.Build;
import android.os.Environment; import android.os.Environment;
import android.os.Handler; import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemClock; import android.os.SystemClock;
//import androidx.camera.video.FallbackStrategy;
//import androidx.camera.video.Quality;
//import androidx.camera.video.QualitySelector;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
import androidx.appcompat.app.AppCompatActivity; 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;
@ -35,17 +36,25 @@ import com.xinyingpower.microphoto.databinding.ActivityMainBinding;
//import com.xinyingpower.microphoto.request.INettyMessageListener; //import com.xinyingpower.microphoto.request.INettyMessageListener;
//import com.xinyingpower.microphoto.request.NettyChatClient; //import com.xinyingpower.microphoto.request.NettyChatClient;
import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.List;
//import io.netty.util.Constant; import android.content.SharedPreferences;
public class MainActivity extends AppCompatActivity { import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
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;
@ -53,17 +62,25 @@ 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;
// private MediaRecorder mediaRecorder; @Override
protected void onDestroy() {
super.onDestroy();
}
protected class AppConfig {
public String cmdid;
public String server;
public int port;
public int protocol;
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater()); binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot()); setContentView(binding.getRoot());
// getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
Display defaultDisplay = windowManager.getDefaultDisplay(); Display defaultDisplay = windowManager.getDefaultDisplay();
@ -72,13 +89,27 @@ public class MainActivity extends AppCompatActivity {
Log.d(TAG, "Screen Size: " + width + " x " + height); Log.d(TAG, "Screen Size: " + width + " x " + height);
String cmdid = "0123456789ABCDEFG";
String server = "47.96.238.157";
Integer port = new Integer(6891);
Integer protocol = new Integer(0xFF00); // 0xFF00
AppConfig appConfig = getAppConfig();
binding.cmdid.setText(appConfig.cmdid);
binding.server.setText(appConfig.server);
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) {
String[] accessPermissions = new String[]{
String[] accessPermissions = new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.FOREGROUND_SERVICE, Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA,
/*Manifest.permission.SET_TIME,*/}; Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.FOREGROUND_SERVICE,
Manifest.permission.READ_PHONE_STATE,
/*Manifest.permission.PACKAGE_USAGE_STATS,*/
/*Manifest.permission.SET_TIME,*/
};
boolean needRequire = false; boolean needRequire = false;
for (String access : accessPermissions) { for (String access : accessPermissions) {
int curPermission = ActivityCompat.checkSelfPermission(MainActivity.this, access); int curPermission = ActivityCompat.checkSelfPermission(MainActivity.this, access);
@ -88,7 +119,10 @@ public class MainActivity extends AppCompatActivity {
} }
} }
if (needRequire) { if (needRequire) {
ActivityCompat.requestPermissions(MainActivity.this, accessPermissions, MY_PERMISSIONS_REQUEST_FOREGROUND_SERVICE); ActivityCompat.requestPermissions(
MainActivity.this,
accessPermissions,
MY_PERMISSIONS_REQUEST_FOREGROUND_SERVICE);
return; return;
} }
@ -97,8 +131,19 @@ public class MainActivity extends AppCompatActivity {
String fileName = buildPhotoFileName(channel, 255); String fileName = buildPhotoFileName(channel, 255);
// MainActivity.this.takePhoto(channel, 255, path, fileName); // MainActivity.this.takePhoto(channel, 255, path, fileName);
String cmdid = MainActivity.this.binding.cmdid.getText().toString();
String server = MainActivity.this.binding.server.getText().toString();
int port = Integer.parseInt(MainActivity.this.binding.port.getText().toString());
int protocol = 0xFF00;
MainActivity.this.saveAppConfig(cmdid, server, port, protocol);
Intent intent = new Intent(MainActivity.this, MicroPhotoService.class); Intent intent = new Intent(MainActivity.this, MicroPhotoService.class);
intent.setAction(MicroPhotoService.ACTION_START); intent.setAction(MicroPhotoService.ACTION_START);
intent.putExtra("cmdid", cmdid);
intent.putExtra("server", server);
intent.putExtra("port", port);
intent.putExtra("protocol", protocol);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
MainActivity.this.startForegroundService(intent); MainActivity.this.startForegroundService(intent);
@ -108,25 +153,30 @@ public class MainActivity extends AppCompatActivity {
binding.startServBtn.setEnabled(false); binding.startServBtn.setEnabled(false);
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() {
@Override
public void onClick(View view) {
MicroPhotoService.takePhoto(MainActivity.this, 3, 255, true);
}
});
this.binding.takePhotoBtn4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MicroPhotoService.takePhoto(MainActivity.this, 4, 255, true);
} }
}); });
@ -142,11 +192,8 @@ public class MainActivity extends AppCompatActivity {
binding.startServBtn.setEnabled(true); binding.startServBtn.setEnabled(true);
binding.stopServBtn.setEnabled(false); binding.stopServBtn.setEnabled(false);
} }
}); });
binding.simchange.setOnClickListener(new View.OnClickListener() { binding.simchange.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
@ -216,14 +263,19 @@ public class MainActivity extends AppCompatActivity {
}); });
} }
}); });
Handler handler=new Handler();
Runnable runnable=new Runnable(){ if (!TextUtils.isEmpty(appConfig.cmdid) && !TextUtils.isEmpty(appConfig.server) && appConfig.port != 0) {
@Override Handler handler = new Handler();
public void run() { Runnable runnable = new Runnable() {
binding.startServBtn.performClick(); @Override
} public void run() {
}; if (binding.startServBtn.isEnabled()) {
handler.postDelayed(runnable, 1000); binding.startServBtn.performClick();
}
}
};
handler.postDelayed(runnable, 5000);
}
binding.tcpudp.setOnClickListener(new View.OnClickListener() { binding.tcpudp.setOnClickListener(new View.OnClickListener() {
@Override @Override
@ -295,7 +347,81 @@ public class MainActivity extends AppCompatActivity {
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "wjz debug setDefaultDataSubId: error is " + e.getMessage()); Log.e(TAG, "wjz debug setDefaultDataSubId: error is " + e.getMessage());
} }
}
private AppConfig getAppConfig() {
AppConfig appConfig = new AppConfig();
String appPath = MicroPhotoService.buildAppDir(this.getApplicationContext());
InputStreamReader inputStreamReader = null;
try {
inputStreamReader = new InputStreamReader(new FileInputStream(new File(appPath + "data/App.json")), "UTF-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line;
StringBuilder stringBuilder = new StringBuilder();
while((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}
bufferedReader.close();
JSONObject jsonObject = new JSONObject(stringBuilder.toString());
appConfig.cmdid = jsonObject.getString("CMDID");
appConfig.server = jsonObject.getString("Server");
appConfig.port = jsonObject.getInt("Port");
appConfig.protocol = jsonObject.getInt("Protocol");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
finally {
if (inputStreamReader != null) {
try {
inputStreamReader.close();
} catch (Exception ex) {
}
}
}
return appConfig;
}
private void saveAppConfig(String cmdid, String server, int port, int protocol) {
String appPath = MicroPhotoService.buildAppDir(this.getApplicationContext());
OutputStreamWriter outputStreamWriter = null;
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("CMDID", cmdid);
jsonObject.put("Server", server);
jsonObject.put("Port", port);
jsonObject.put("Protocol", protocol);
outputStreamWriter = new OutputStreamWriter(new FileOutputStream(new File(appPath + "data/App.json")), "UTF-8");
outputStreamWriter.write(jsonObject.toString());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
finally {
if (outputStreamWriter != null) {
try {
outputStreamWriter.close();
} catch (Exception ex) {
}
}
}
} }
private int getDefaultDataSubId() { private int getDefaultDataSubId() {

@ -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,32 +10,22 @@ 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.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.SubscriptionManager;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
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;
import android.widget.RemoteViews; import android.widget.RemoteViews;
import android.widget.Toast; import android.widget.Toast;
import com.dowse.camera.client.DSCameraManager;
import java.io.File; import java.io.File;
import java.lang.reflect.Method;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
@ -52,62 +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 AlarmManager mAlarmManager;
private NotificationManager mNotificationManager; private NotificationManager mNotificationManager;
private final 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();
@ -115,9 +87,11 @@ public class MicroPhotoService extends Service {
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
stateService = STATE_SERVICE.NOT_CONNECTED; stateService = STATE_SERVICE.NOT_CONNECTED;
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);
@ -133,69 +107,51 @@ 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;
/*
res = DSCameraManager.getInstace().init();
ChannelPicParam picParam = new ChannelPicParam();
picParam.setColor(1);
picParam.setWidth(1920);
picParam.setHeight(1080);
picParam.setCompress_radio(40);
DSCameraManager.getInstace().setPicParam(1, picParam);
*/
// Environment.getExternalStoragePublicDirectory(String) // Environment.getExternalStoragePublicDirectory(String)
File path = new File(Environment.getExternalStorageDirectory(), "com.xyp.mp/");
if (!path.exists()) {
path.mkdirs();
}
// File path = getApplicationContext().getFilesDir();
String appPath = path.getAbsolutePath();
Log.i(TAG, "AppPath=" + appPath);
// String ip = "180.166.218.222";
String ip = "47.96.238.157";
// int port = 40032;
// String ip = "192.168.50.50";
int port = 6891;
String cmdid = "XY-ANDROIDSIM-002";
init(appPath, ip, port, cmdid);
// registerHeartbeatTimer(getHeartbeatDuration()); // registerHeartbeatTimer(getHeartbeatDuration());
}
@Override
public void onDestroy() {
Date date = new Date(); stateService = STATE_SERVICE.NOT_CONNECTED;
long nowTs = date.getTime() / 1000;
date.setHours(0);
date.setMinutes(0);
date.setSeconds(0);
long startTime = date.getTime() / 1000;
long baseTime = nowTs - startTime;
registerCaptureSchedule(startTime, baseTime); uninit(mHandler);
mHandler = 0;
// registerPhotoTimer(); unregisterReceiver(alarmReceiver);
} unregisterReceiver(screenactionreceiver);
for(Map.Entry<String, PowerManager.WakeLock> entry : mWakeLocks.entrySet()) {
entry.getValue().release();
}
mWakeLocks.clear();
super.onDestroy();
}
public static class AlarmReceiver extends BroadcastReceiver { public static class AlarmReceiver extends BroadcastReceiver {
private MicroPhotoService mService; private MicroPhotoService mService;
public AlarmReceiver() {
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.sendHeartbeat(mService.mHandler);
mService.registerHeartbeatTimer(); mService.registerHeartbeatTimer();
} else if (TextUtils.equals(ACTION_TAKE_PHOTO, action)) { } else if (TextUtils.equals(ACTION_TAKE_PHOTO, action)) {
long ts = intent.getLongExtra(EXTRA_PARAM_TIME, 0); long ts = intent.getLongExtra(EXTRA_PARAM_TIME, 0);
@ -207,7 +163,8 @@ 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);
mService.notifyToTakePhoto(channel, preset, ts, mService.buildPhotoDir(channel), mService.buildPhotoFileName(channel, preset, ts), true); 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);
} }
} }
@ -228,23 +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;
mService.notifyToTakePhoto(channel, preset, ts, mService.buildPhotoDir(channel), mService.buildPhotoFileName(channel, preset, ts), photoOrVideo); 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);
} 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(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);
PendingIntent pendingIntent = mService.mTimers.get(uidObj); if ((expectedTimes == 0) || (elapsedTimes < expectedTimes)) {
int timeout = intent.getIntExtra(EXTRA_PARAM_TIMEOUT, 0);
if (pendingIntent != null) { PendingIntent pendingIntent = mService.mTimers.get(uidObj);
mService.registerTimer(pendingIntent, uid, timeout);
if (pendingIntent != null) {
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;
@ -253,7 +221,6 @@ public class MicroPhotoService extends Service {
} }
} }
private void registerHeartbeatTimer() { private void registerHeartbeatTimer() {
// 创建延迟意图 // 创建延迟意图
@ -268,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();
@ -277,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,6 +284,28 @@ public class MicroPhotoService extends Service {
return registerTimer(pendingIntent, uid, timeout); return registerTimer(pendingIntent, uid, timeout);
} }
private void setDefaultDataSubId(int subId) {
SubscriptionManager subscriptionManager = (SubscriptionManager) getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
try {
Method method = subscriptionManager.getClass().getDeclaredMethod("setDefaultDataSubId", int.class);
method.invoke(subscriptionManager, subId);
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
Method method1 = telephonyManager.getClass().getDeclaredMethod("setDataEnabled", boolean.class);
method1.invoke(telephonyManager, true);
} catch (Exception e) {
Log.e(TAG, "wjz debug setDefaultDataSubId: error is " + e.getMessage());
}
}
private int getDefaultDataSubId() {
SubscriptionManager subscriptionManager = (SubscriptionManager) getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
try {
Method method = subscriptionManager.getClass().getDeclaredMethod("getDefaultDataSubscriptionId");
return (int) method.invoke(subscriptionManager);
} catch (Exception e) {
Log.e(TAG, "wjz debug getDefaultDataSubId: error is " + e.getMessage());
}
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);
@ -320,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);
@ -336,10 +330,9 @@ 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(); long[] photoTimeData = getPhotoTimeData(mHandler);
if (photoTimeData == null) { if (photoTimeData == null) {
return false; return false;
} }
@ -373,9 +366,16 @@ public class MicroPhotoService extends Service {
preset = (short) ((val & 0xFF00L) >> 8); preset = (short) ((val & 0xFF00L) >> 8);
schedules.add(Long.valueOf(val)); schedules.add(Long.valueOf(val));
Log.i(TAG, "PhotoTimer Reg: CH=" + channel + " PR=" + preset);
} else if (ts > currentTs) { } else if (ts > currentTs) {
break; break;
} else { } else {
channel = (short) ((val & 0xFF0000L) >> 16);
preset = (short) ((val & 0xFF00L) >> 8);
Log.i(TAG, "PhotoTimer Reg: CH=" + channel + " PR=" + preset);
schedules.add(Long.valueOf(val)); schedules.add(Long.valueOf(val));
} }
} }
@ -398,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
@ -420,13 +423,42 @@ public class MicroPhotoService extends Service {
Log.d(TAG, "Received user starts foreground intent"); Log.d(TAG, "Received user starts foreground intent");
startForeground(NOTIFICATION_ID_FOREGROUND_SERVICE, prepareNotification()); startForeground(NOTIFICATION_ID_FOREGROUND_SERVICE, prepareNotification());
// Start the locker receiver connect();
final ScreenActionReceiver screenactionreceiver = new ScreenActionReceiver();
registerReceiver(screenactionreceiver, screenactionreceiver.getFilter()); registerReceiver(screenactionreceiver, screenactionreceiver.getFilter());
connect();
// File path = getApplicationContext().getFilesDir();
String appPath = buildAppDir(this.getApplicationContext());
String ip = intent.getStringExtra("server");
int port = intent.getIntExtra("port", 0);
String cmdid = intent.getStringExtra("cmdid");
int protocol = intent.getIntExtra("protocol", 0);
Log.i(TAG, "AppPath=" + appPath + " Server=" + ip + ":" + port + " cmdid=" + cmdid + " protocol" + protocol);
mHandler = init(appPath, ip, port, cmdid, protocol);
// Start the locker receiver
if (mHandler !=0) {
Date date = new Date();
long nowTs = date.getTime() / 1000;
date.setHours(0);
date.setMinutes(0);
date.setSeconds(0);
long startTime = date.getTime() / 1000;
long baseTime = nowTs - startTime;
registerCaptureSchedule(startTime, baseTime);
}
// registerPhotoTimer();
break; break;
case ACTION_STOP: case ACTION_STOP:
unregisterReceiver(screenactionreceiver);
stopForeground(true); stopForeground(true);
stopSelf(); stopSelf();
break; break;
@ -438,6 +470,31 @@ public class MicroPhotoService extends Service {
return START_NOT_STICKY; return START_NOT_STICKY;
} }
public void requestWakelock(String name, long timeout) {
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, name);
PowerManager.WakeLock wl2 = null;
synchronized (mWakeLocks) {
wl2 = mWakeLocks.replace(name, wl);
}
if (wl2 != null) {
wl2.release();
}
if (timeout == 0) wl.acquire();
else wl.acquire(timeout);
}
public void releaseWakelock(String name) {
PowerManager.WakeLock wl = null;
synchronized (mWakeLocks) {
wl = mWakeLocks.get(name);
mWakeLocks.remove(name);
}
if (wl != null) {
wl.release();
}
}
private void connect() { private void connect() {
// after 10 seconds its connected // after 10 seconds its connected
new android.os.Handler().postDelayed( new android.os.Handler().postDelayed(
@ -510,188 +567,42 @@ 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();
} }
protected String getNetworkType() {
// ConnectionManager instance
ConnectivityManager connectivityManager = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = connectivityManager.getActiveNetworkInfo();
// If not connected, "-" will be displayed
if (ni == null || !ni.isConnected()) return "";
// If Connected to Wifi
if (ni.getType() == ConnectivityManager.TYPE_WIFI) return "WIFI";
// If Connected to Mobile
String subTypeName = "";
if (ni.getType() == ConnectivityManager.TYPE_MOBILE) {
int subType = ni.getSubtype();
switch (subType) {
case TelephonyManager.NETWORK_TYPE_GPRS:
case TelephonyManager.NETWORK_TYPE_EDGE:
case TelephonyManager.NETWORK_TYPE_CDMA:
case TelephonyManager.NETWORK_TYPE_1xRTT:
case TelephonyManager.NETWORK_TYPE_IDEN:
case TelephonyManager.NETWORK_TYPE_GSM:
subTypeName = "2G";
break;
case TelephonyManager.NETWORK_TYPE_UMTS:
case TelephonyManager.NETWORK_TYPE_EVDO_0:
case TelephonyManager.NETWORK_TYPE_EVDO_A:
case TelephonyManager.NETWORK_TYPE_HSDPA:
case TelephonyManager.NETWORK_TYPE_HSUPA:
case TelephonyManager.NETWORK_TYPE_HSPA:
case TelephonyManager.NETWORK_TYPE_EVDO_B:
case TelephonyManager.NETWORK_TYPE_EHRPD:
case TelephonyManager.NETWORK_TYPE_HSPAP:
case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
subTypeName = "3G";
break;
case TelephonyManager.NETWORK_TYPE_LTE:
case TelephonyManager.NETWORK_TYPE_IWLAN:
case 19:
subTypeName = "4G";
break;
case TelephonyManager.NETWORK_TYPE_NR:
subTypeName = "5G";
break;
default:
subTypeName = "";
break;
}
}
return subTypeName;
}
public static void getPhoneState(Context context) {
final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener MyPhoneListener = new PhoneStateListener() {
@Override
//获取对应网络的ID这个方法在这个程序中没什么用处
public void onCellLocationChanged(CellLocation location) {
if (location instanceof GsmCellLocation) {
int CID = ((GsmCellLocation) location).getCid();
} else if (location instanceof CdmaCellLocation) {
int ID = ((CdmaCellLocation) location).getBaseStationId();
}
}
//系统自带的服务监听器,实时监听网络状态
@Override
public void onServiceStateChanged(ServiceState serviceState) {
super.onServiceStateChanged(serviceState);
}
//这个是我们的主角,就是获取对应网络信号强度
@Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
//这个ltedbm 是4G信号的值
String signalinfo = signalStrength.toString();
String[] parts = signalinfo.split(" ");
String ltedbm = parts[9];
//这个dbm 是2G和3G信号的值
int asu = signalStrength.getGsmSignalStrength();
int dbm = -113 + 2 * asu;
if (telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE) {
Log.i("NetWorkUtil", "网络LTE 信号强度:" + ltedbm + "======Detail:" + signalinfo);
} else if (telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_HSDPA ||
telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_HSPA ||
telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_HSUPA ||
telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS) {
String bin;
if (dbm > -75) {
bin = "网络很好";
} else if (dbm > -85) {
bin = "网络不错";
} else if (dbm > -95) {
bin = "网络还行";
} else if (dbm > -100) {
bin = "网络很差";
} else {
bin = "网络错误";
}
Log.i("NetWorkUtil", "网络WCDMA 信号值:" + dbm + "========强度:" + bin + "======Detail:" + signalinfo);
} else {
String bin;
if (asu < 0 || asu >= 99) bin = "网络错误";
else if (asu >= 16) bin = "网络很好";
else if (asu >= 8) bin = "网络不错";
else if (asu >= 4) bin = "网络还行";
else bin = "网络很差";
Log.i("NetWorkUtil", "网络GSM 信号值:" + dbm + "========强度:" + bin + "======Detail:" + signalinfo);
}
super.onSignalStrengthsChanged(signalStrength);
}
};
telephonyManager.listen(MyPhoneListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
}
/*
public boolean takePhoto(short channel, short preset, String path) {
boolean res = DSCameraManager.getInstace().takePhoto(path, channel, 0, 0); public static String buildAppDir(Context contxt) {
if (!res) { File[] paths = contxt.getExternalFilesDirs(null);
int idx = 0; if (paths == null || paths.length == 0) {
do { return null;
res = DSCameraManager.getInstace().isCameraServiceOK();
if (!res)
{
try {
Thread.sleep(1000L);
} catch (InterruptedException ex) {
// ex.printStackTrace();
}
}
} while(idx < 6);
if (DSCameraManager.getInstace().isCameraServiceOK()) {
res = DSCameraManager.getInstace().takePhoto(path, channel, 0, 0);
}
} }
return res;
File path = paths[0];
if (!path.exists() && !path.mkdirs()) {
return null;
}
String p = path.getAbsolutePath();
if (!p.endsWith(File.separator)) {
p += File.separator;
}
return p;
} }
*/ public static String buildPhotoDir(Context contxt, int channel) {
// File path = new File(Environment.getExternalStorageDirectory(), "com.xinyingpower.mp/photos/");
@Override
public void onDestroy() {
stateService = STATE_SERVICE.NOT_CONNECTED;
uninit();
DSCameraManager.getInstace().unInit();
super.onDestroy();
}
protected boolean updateTime(long timeInMillis) { String appDir = buildAppDir(contxt);
boolean res = false; if (appDir == null) {
try { return null;
// Calendar c = Calendar.getInstance();
// c.set(2010, 1, 1, 12, 00, 00);
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
am.setTime(timeInMillis);
res = true;
} catch (Exception ex) {
int aa = 0;
} }
return true;
}
public String buildPhotoDir(int channel) { File path = new File(appDir, "photos/");
File path = new File(Environment.getExternalStorageDirectory(), "com.xyp.mp/photos/");
if (!path.exists() && !path.mkdirs()) { if (!path.exists() && !path.mkdirs()) {
return null; return null;
@ -711,16 +622,38 @@ public class MicroPhotoService extends Service {
} }
public boolean updateTime(long timeInMillis) {
boolean res = false;
try {
// Calendar c = Calendar.getInstance();
// c.set(2010, 1, 1, 12, 00, 00);
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
am.setTime(timeInMillis);
res = true;
} catch (Exception ex) {
int aa = 0;
}
return true;
}
/*
TelephonyManager telephonyManager = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
// for example value of first element
CellInfoGsm cellInfoGsm = (CellInfoGsm)telephonyManager.getAllCellInfo().get(0);
CellSignalStrengthGsm cellSignalStrengthGsm = cellInfoGsm.getCellSignalStrength();
cellSignalStrengthGsm.getDbm();
*/
protected native boolean 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(); protected native long getHeartbeatDuration(long handler);
protected native long[] getPhotoTimeData(); protected native long[] getPhotoTimeData(long handler);
protected native long[] getNextScheduleItem(); // protected native long[] getNextScheduleItem(long handler);
protected native boolean notifyToTakePhoto(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(); protected native boolean sendHeartbeat(long handler);
protected native boolean fireTimeout(long uid); protected native boolean fireTimeout(long handler, long uid, long times);
protected native boolean uninit(); protected native boolean uninit(long handler);
protected long mHandler = 0; protected long mHandler = 0;
private AlarmReceiver alarmReceiver = null; private AlarmReceiver alarmReceiver = null;
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))

@ -4,91 +4,156 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:clickable="false"
android:orientation="horizontal" android:orientation="horizontal"
tools:context=".MainActivity"> tools:context=".MainActivity">
<TextView <TextView
android:id="@+id/textView" android:id="@+id/textViewCmdId"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="38dp" android:layout_marginLeft="20dp"
android:layout_marginTop="38dp" android:text="CMDID"
android:text="Server" app:layout_constraintBottom_toBottomOf="@+id/cmdid"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="@+id/cmdid" />
<EditText <EditText
android:id="@+id/server" android:id="@+id/cmdid"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="114dp" android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:ems="10" android:ems="10"
android:inputType="" android:text="XY-ANDROIDSIM-001"
app:layout_constraintBottom_toBottomOf="@+id/textView" app:layout_constraintLeft_toRightOf="@+id/textViewCmdId"
app:layout_constraintStart_toEndOf="@+id/textView" app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toTopOf="@+id/textView" />
<Spinner
android:id="@+id/protocol"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
app:layout_constraintLeft_toRightOf="@+id/cmdid"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@+id/cmdid" />
<TextView <TextView
android:id="@+id/textView2" android:id="@+id/textView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="12dp" android:layout_marginTop="20dp"
android:layout_marginTop="52dp" android:text="Server"
android:gravity="center" app:layout_constraintBottom_toBottomOf="@+id/server"
android:text="Port" app:layout_constraintStart_toStartOf="@id/textViewCmdId"
app:layout_constraintLeft_toLeftOf="@+id/textView" app:layout_constraintTop_toTopOf="@+id/server" />
app:layout_constraintTop_toBottomOf="@+id/textView" />
<EditText <EditText
android:id="@+id/port" android:id="@+id/server"
android:layout_width="wrap_content" android:layout_width="160dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:ems="10" android:ems="10"
android:inputType="" android:inputType=""
android:text="Name" android:text="47.96.238.157"
app:layout_constraintBottom_toBottomOf="@+id/textView2" app:layout_constraintStart_toStartOf="@+id/cmdid"
app:layout_constraintLeft_toLeftOf="@+id/server" app:layout_constraintTop_toBottomOf="@+id/cmdid" />
app:layout_constraintLeft_toRightOf="@+id/textView2"
app:layout_constraintTop_toTopOf="@+id/textView2" /> <EditText
android:id="@+id/port"
android:layout_width="64dp"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number"
android:text="6891"
app:layout_constraintBottom_toBottomOf="@+id/server"
app:layout_constraintLeft_toRightOf="@+id/server"
app:layout_constraintTop_toTopOf="@+id/server" />
<Button
android:id="@+id/startServBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="24dp"
android:text="Start"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/port"
/>
<Button <Button
android:id="@+id/stopServBtn" android:id="@+id/stopServBtn"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="24dp"
android:enabled="false" android:enabled="false"
android:text="Stop" /> android:text="Stop"
app:layout_constraintStart_toEndOf="@+id/startServBtn"
app:layout_constraintTop_toBottomOf="@+id/port" />
<Button <Button
android:id="@+id/startServBtn" android:id="@+id/simchange"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Start" /> android:layout_marginStart="20dp"
android:layout_marginTop="24dp"
android:text="sim卡获取"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/startServBtn" />
<Button <Button
android:id="@+id/takePhotoBtn2" android:id="@+id/simchange2"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Take Photo2" /> android:layout_marginStart="4dp"
android:layout_marginTop="24dp"
android:text="切换sim2"
app:layout_constraintStart_toEndOf="@+id/simchange"
app:layout_constraintTop_toBottomOf="@+id/startServBtn" />
<Button <Button
android:id="@+id/takePhotoBtn" android:id="@+id/takePhotoBtn"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Take Photo" /> android:layout_marginTop="16dp"
android:text="TK Photo"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/simchange" />
<Button <Button
android:id="@+id/simchange" android:id="@+id/takePhotoBtn2"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="sim卡获取" /> android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="TP 2"
app:layout_constraintStart_toEndOf="@+id/takePhotoBtn"
app:layout_constraintTop_toBottomOf="@+id/simchange" />
<Button <Button
android:id="@+id/simchange2" android:id="@+id/takePhotoBtn3"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="切换sim2" /> android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:text="TP 3"
app:layout_constraintStart_toEndOf="@+id/takePhotoBtn2"
app:layout_constraintTop_toBottomOf="@+id/simchange" />
<Button
android:id="@+id/takePhotoBtn4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:text="TP 4"
app:layout_constraintStart_toEndOf="@+id/takePhotoBtn3"
app:layout_constraintTop_toBottomOf="@+id/simchange" />
<Button <Button
android:id="@+id/gps" android:id="@+id/gps"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -142,11 +207,10 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Hello World!" android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent" android:visibility="invisible"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintVertical_bias="0.929" />
<SurfaceView <SurfaceView
android:id="@+id/surfaceView" android:id="@+id/surfaceView"

@ -18,6 +18,7 @@ android.nonTransitiveRClass=true
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
opencvsdk=D:/Workspace/deps/opencv-mobile-4.6.0-android # opencvsdk=D:/Workspace/deps/opencv-mobile-4.8.0-android
opencvsdk=D:/Workspace/deps/opencv-v5
asioroot=D:/Workspace/deps/asio-1.28.0 asioroot=D:/Workspace/deps/asio-1.28.0
evpproot=D:/Workspace/Github/evpp evpproot=D:/Workspace/Github/evpp
Loading…
Cancel
Save