You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
302 lines
9.5 KiB
C++
302 lines
9.5 KiB
C++
#ifndef __PHONE_DEVICE_H__
|
|
#define __PHONE_DEVICE_H__
|
|
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
|
|
#include <map>
|
|
#include <atomic>
|
|
#include <filesystem>
|
|
#include <thread>
|
|
|
|
#include <camera/NdkCameraManager.h>
|
|
#include <camera/NdkCameraError.h>
|
|
#include <camera/NdkCameraDevice.h>
|
|
#include <camera/NdkCameraMetadataTags.h>
|
|
#include <media/NdkImageReader.h>
|
|
#include <Client/Device.h>
|
|
#include <string>
|
|
|
|
#include "camera2/Camera2Helper.h"
|
|
#include "camera2/ndkcamera.h"
|
|
|
|
#include <opencv2/opencv.hpp>
|
|
#include <android/bitmap.h>
|
|
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "error", __VA_ARGS__))
|
|
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, "debug", __VA_ARGS__))
|
|
|
|
#if 0
|
|
void BitmapToMat2(JNIEnv *env, jobject& bitmap, cv::Mat& mat, jboolean needUnPremultiplyAlpha) {
|
|
AndroidBitmapInfo info;
|
|
void *pixels = 0;
|
|
cv::Mat &dst = mat;
|
|
|
|
// try {
|
|
ALOGD("nBitmapToMat");
|
|
CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);
|
|
CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
|
|
info.format == ANDROID_BITMAP_FORMAT_RGB_565);
|
|
CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);
|
|
CV_Assert(pixels);
|
|
dst.create(info.height, info.width, CV_8UC4);
|
|
if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
|
|
ALOGD("nBitmapToMat: RGBA_8888 -> CV_8UC4");
|
|
cv::Mat tmp(info.height, info.width, CV_8UC4, pixels);
|
|
if (needUnPremultiplyAlpha) cvtColor(tmp, dst, cv::COLOR_mRGBA2RGBA);
|
|
else tmp.copyTo(dst);
|
|
} else {
|
|
// info.format == ANDROID_BITMAP_FORMAT_RGB_565
|
|
ALOGD("nBitmapToMat: RGB_565 -> CV_8UC4");
|
|
cv::Mat tmp(info.height, info.width, CV_8UC2, pixels);
|
|
cvtColor(tmp, dst, cv::COLOR_BGR5652RGBA);
|
|
}
|
|
AndroidBitmap_unlockPixels(env, bitmap);
|
|
return;
|
|
/*
|
|
} catch (const cv::Exception &e) {
|
|
AndroidBitmap_unlockPixels(env, bitmap);
|
|
LOGE("nBitmapToMat catched cv::Exception: %s", e.what());
|
|
jclass je = env->FindClass("org/opencv/core/CvException");
|
|
if (!je) je = env->FindClass("java/lang/Exception");
|
|
env->ThrowNew(je, e.what());
|
|
return;
|
|
} catch (...) {
|
|
AndroidBitmap_unlockPixels(env, bitmap);
|
|
LOGE("nBitmapToMat catched unknown exception (...)");
|
|
jclass je = env->FindClass("java/lang/Exception");
|
|
env->ThrowNew(je, "Unknown exception in JNI code {nBitmapToMat}");
|
|
return;
|
|
}
|
|
*/
|
|
}
|
|
|
|
void BitmapToMat(JNIEnv *env, jobject& bitmap, cv::Mat& mat) {
|
|
BitmapToMat2(env, bitmap, mat, false);
|
|
}
|
|
|
|
void MatToBitmap2
|
|
(JNIEnv *env, cv::Mat& mat, jobject& bitmap, jboolean needPremultiplyAlpha) {
|
|
AndroidBitmapInfo info;
|
|
void *pixels = 0;
|
|
cv::Mat &src = mat;
|
|
|
|
// try {
|
|
ALOGD("nMatToBitmap");
|
|
CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);
|
|
CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
|
|
info.format == ANDROID_BITMAP_FORMAT_RGB_565);
|
|
CV_Assert(src.dims == 2 && info.height == (uint32_t) src.rows &&
|
|
info.width == (uint32_t) src.cols);
|
|
CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC3 || src.type() == CV_8UC4);
|
|
CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);
|
|
CV_Assert(pixels);
|
|
if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
|
|
cv::Mat tmp(info.height, info.width, CV_8UC4, pixels);
|
|
if (src.type() == CV_8UC1) {
|
|
ALOGD("nMatToBitmap: CV_8UC1 -> RGBA_8888");
|
|
cvtColor(src, tmp, cv::COLOR_GRAY2RGBA);
|
|
} else if (src.type() == CV_8UC3) {
|
|
ALOGD("nMatToBitmap: CV_8UC3 -> RGBA_8888");
|
|
cvtColor(src, tmp, cv::COLOR_RGB2RGBA);
|
|
} else if (src.type() == CV_8UC4) {
|
|
ALOGD("nMatToBitmap: CV_8UC4 -> RGBA_8888");
|
|
if (needPremultiplyAlpha)
|
|
cvtColor(src, tmp, cv::COLOR_RGBA2mRGBA);
|
|
else
|
|
src.copyTo(tmp);
|
|
}
|
|
} else {
|
|
// info.format == ANDROID_BITMAP_FORMAT_RGB_565
|
|
cv::Mat tmp(info.height, info.width, CV_8UC2, pixels);
|
|
if (src.type() == CV_8UC1) {
|
|
ALOGD("nMatToBitmap: CV_8UC1 -> RGB_565");
|
|
cvtColor(src, tmp, cv::COLOR_GRAY2BGR565);
|
|
} else if (src.type() == CV_8UC3) {
|
|
ALOGD("nMatToBitmap: CV_8UC3 -> RGB_565");
|
|
cvtColor(src, tmp, cv::COLOR_RGB2BGR565);
|
|
} else if (src.type() == CV_8UC4) {
|
|
ALOGD("nMatToBitmap: CV_8UC4 -> RGB_565");
|
|
cvtColor(src, tmp, cv::COLOR_RGBA2BGR565);
|
|
}
|
|
}
|
|
AndroidBitmap_unlockPixels(env, bitmap);
|
|
return;
|
|
/*
|
|
} catch (const cv::Exception &e) {
|
|
AndroidBitmap_unlockPixels(env, bitmap);
|
|
LOGE("nMatToBitmap catched cv::Exception: %s", e.what());
|
|
jclass je = env->FindClass("org/opencv/core/CvException");
|
|
if (!je) je = env->FindClass("java/lang/Exception");
|
|
env->ThrowNew(je, e.what());
|
|
return;
|
|
} catch (...) {
|
|
AndroidBitmap_unlockPixels(env, bitmap);
|
|
LOGE("nMatToBitmap catched unknown exception (...)");
|
|
jclass je = env->FindClass("java/lang/Exception");
|
|
env->ThrowNew(je, "Unknown exception in JNI code {nMatToBitmap}");
|
|
return;
|
|
}*/
|
|
|
|
}
|
|
|
|
void MatToBitmap(JNIEnv *env, cv::Mat& mat, jobject& bitmap) {
|
|
MatToBitmap2(env, mat, bitmap, false);
|
|
}
|
|
#endif
|
|
|
|
class CPhoneDevice : public IDevice
|
|
{
|
|
public:
|
|
|
|
class CPhoneCamera : public NdkCamera {
|
|
public:
|
|
CPhoneCamera(CPhoneDevice* dev, int32_t width, int32_t height, const NdkCamera::CAMERA_PARAMS& params);
|
|
virtual ~CPhoneCamera();
|
|
virtual bool on_image(cv::Mat& rgb);
|
|
virtual void on_error(const std::string& msg);
|
|
|
|
protected:
|
|
CPhoneDevice* m_dev;
|
|
};
|
|
|
|
struct TIMER_CONTEXT
|
|
{
|
|
CPhoneDevice* device;
|
|
unsigned int timerType;
|
|
unsigned long times;
|
|
void* data;
|
|
unsigned long expectedTimes;
|
|
unsigned long uid;
|
|
};
|
|
|
|
CPhoneDevice(JavaVM* vm, jobject service, const std::string& appPath, unsigned int netId, unsigned int versionCode);
|
|
virtual ~CPhoneDevice();
|
|
|
|
virtual void SetListener(IListener* listener);
|
|
virtual void SetRecognizationCfg(const CFG_RECOGNIZATION* pRecognizationCfg);
|
|
virtual bool BindNetwork(int sock);
|
|
virtual bool UpdateTime(time_t ts);
|
|
virtual bool UpdateSchedules();
|
|
virtual bool QuerySystemProperties(map<string, string>& properties);
|
|
virtual bool InstallAPP(const std::string& path, unsigned int delayedTime);
|
|
virtual bool Reboot(int resetType);
|
|
virtual bool EnableGPS(bool enabled);
|
|
virtual float QueryBattaryVoltage(int timesForAvg, bool* isCharging);
|
|
virtual bool RequestPosition();
|
|
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 std::string& path);
|
|
virtual bool CloseCamera();
|
|
virtual timer_uid_t RegisterTimer(unsigned int timerType, unsigned int timeout, void* data, unsigned long times = 0);
|
|
virtual bool UnregisterTimer(timer_uid_t uid);
|
|
virtual unsigned long RequestWakelock(unsigned long timeout);
|
|
virtual bool ReleaseWakelock(unsigned long wakelock);
|
|
|
|
bool GetNextScheduleItem(uint32_t tsBasedZero, uint32_t scheduleTime, vector<uint32_t>& items);
|
|
|
|
void UpdatePosition(double lon, double lat, double radius, time_t ts);
|
|
bool OnVideoReady(bool result, const char* path, unsigned int photoId);
|
|
void UpdateSignalLevel(int signalLevel);
|
|
|
|
protected:
|
|
|
|
std::string GetFileName() const;
|
|
|
|
bool SendBroadcastMessage(std::string action, int value);
|
|
// bool MatchCaptureSizeRequest(ACameraManager *cameraManager, const char *selectedCameraId, unsigned int width, unsigned int height, uint32_t cameraOrientation_,
|
|
|
|
inline bool TakePhotoCb(bool res, const IDevice::PHOTO_INFO& photoInfo, const string& path, time_t photoTime, const std::vector<IDevice::RECOG_OBJECT>& objects) const
|
|
{
|
|
if (m_listener != NULL)
|
|
{
|
|
return m_listener->OnPhotoTaken(res, photoInfo, path, photoTime, objects);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
inline bool TakePhotoCb(bool res, const IDevice::PHOTO_INFO& photoInfo, const string& path, time_t photoTime) const
|
|
{
|
|
if (m_listener != NULL)
|
|
{
|
|
std::vector<IDevice::RECOG_OBJECT> objects;
|
|
return m_listener->OnPhotoTaken(res, photoInfo, path, photoTime, objects);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void QueryPowerInfo(std::map<std::string, std::string>& powerInfo);
|
|
std::string QueryCpuTemperature();
|
|
|
|
bool OnImageReady(cv::Mat& mat);
|
|
void onError(const std::string& msg);
|
|
|
|
void CloseCamera2(CPhoneCamera* camera, unsigned int photoId, bool turnOffOtg);
|
|
|
|
void TurnOnCameraPower(JNIEnv* env);
|
|
void TurnOffCameraPower(JNIEnv* env);
|
|
|
|
void TurnOnOtg(JNIEnv* env);
|
|
void TurnOffOtg(JNIEnv* env);
|
|
|
|
static void handleSignal(int sig, siginfo_t *si, void *uc);
|
|
bool RegisterHandlerForSignal(int sig);
|
|
void static handleTimer(union sigval v);
|
|
void handleTimerImpl(TIMER_CONTEXT* context);
|
|
|
|
protected:
|
|
|
|
std::mutex m_devLocker;
|
|
|
|
JavaVM* m_vm;
|
|
jobject m_javaService;
|
|
std::string m_appPath;
|
|
|
|
jmethodID mRegisterHeartbeatMid;
|
|
jmethodID mUpdateCaptureScheduleMid;
|
|
jmethodID mUpdateTimeMid;
|
|
jmethodID mStartRecordingMid;
|
|
|
|
jmethodID mRequestWakelockMid;
|
|
jmethodID mReleaseWakelockMid;
|
|
|
|
jmethodID mGetSystemInfoMid;
|
|
|
|
jmethodID mRebootMid;
|
|
jmethodID mInstallAppMid;
|
|
jmethodID mEnableGpsMid;
|
|
jmethodID mRequestPositionMid;
|
|
|
|
std::string mPath;
|
|
IDevice::PHOTO_INFO mPhotoInfo;
|
|
vector<IDevice::OSD_INFO> mOsds;
|
|
IListener* m_listener;
|
|
const CFG_RECOGNIZATION* m_pRecognizationCfg;
|
|
unsigned int mNetId;
|
|
unsigned int mVersionCode;
|
|
|
|
atomic_ulong m_timerUidFeed;
|
|
atomic_ulong m_wakelockIdFeed;
|
|
std::map<IDevice::timer_uid_t, TIMER_CONTEXT*> mTimers;
|
|
|
|
mutable CPhoneCamera* mCamera;
|
|
|
|
time_t mHeartbeatStartTime;
|
|
unsigned int mHeartbeatDuration;
|
|
|
|
long mCameraPowerCount;
|
|
long mOtgCount;
|
|
std::thread m_threadClose;
|
|
|
|
int m_signalLevel;
|
|
time_t m_signalLevelUpdateTime;
|
|
|
|
};
|
|
|
|
|
|
#endif // __PHONE_DEVICE_H__
|