重新实现Timer

serial
BlueMatthew 1 year ago
parent 8b11ff38b6
commit ae49534733

@ -265,7 +265,8 @@ Java_com_xypower_mpapp_MicroPhotoService_fireTimeout(
}
CPhoneDevice* phoneDevice = (CPhoneDevice *)dev;
return phoneDevice->FireTimer((IDevice::timer_uid_t)uid, static_cast<unsigned long>(times)) ? JNI_TRUE : JNI_FALSE;
return JNI_FALSE;
// return phoneDevice->FireTimer((IDevice::timer_uid_t)uid, static_cast<unsigned long>(times)) ? JNI_TRUE : JNI_FALSE;
}
extern "C" JNIEXPORT void JNICALL

@ -162,6 +162,8 @@ CPhoneDevice::CPhoneDevice(JavaVM* vm, jobject service, const std::string& appPa
m_sysApiClass = NULL;
RegisterHandlerForSignal(SIGUSR2);
m_vm = vm;
JNIEnv* env = NULL;
bool didAttachThread = false;
@ -518,57 +520,121 @@ bool CPhoneDevice::RequestPosition()
return (ret == JNI_TRUE);
}
IDevice::timer_uid_t CPhoneDevice::RegisterTimer(unsigned int timerType, unsigned int timeout, unsigned long times/* = 0*/)
void CPhoneDevice::handleSignal(int sig, siginfo_t *si, void *uc)
{
IDevice::timer_uid_t uid = m_timerUidFeed.fetch_add(1);
ALOGI("NDK RegTimer: uid=%lld Type=%u timeout=%u", uid, timerType, timeout);
TIMER_CONTEXT* context = (TIMER_CONTEXT*)(si->si_value.sival_ptr);
context->device->handleTimerImpl(context);
}
JNIEnv* env = NULL;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
bool CPhoneDevice::RegisterHandlerForSignal(int sig)
{
return true;
// Establish handler for timer signal
struct sigaction sa;
sigset_t mask;
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = CPhoneDevice::handleSignal;
sigemptyset(&sa.sa_mask);
if (sigaction(sig, &sa, NULL) == -1)
{
ALOGE("Failed to get JNI Env");
return 0;
return false;
}
jboolean ret = env->CallBooleanMethod(m_javaService, mRegisterTimerMid, (jlong)uid, (jint)timeout, (jlong)times);
if (didAttachThread)
return true;
// Block timer signal temporarily
// printf("Blocking signal %d\n", SIG);
sigemptyset(&mask);
sigaddset(&mask, sig);
if (sigprocmask(SIG_SETMASK, &mask, NULL) == -1)
{
m_vm->DetachCurrentThread();
return false;
}
if (ret == JNI_TRUE)
return true;
}
void CPhoneDevice::handleTimer(union sigval v)
{
TIMER_CONTEXT* context = (TIMER_CONTEXT*)(v.sival_ptr);
context->device->handleTimerImpl(context);
}
void CPhoneDevice::handleTimerImpl(CPhoneDevice::TIMER_CONTEXT* context)
{
context->times++;
if (context->expectedTimes == 0 || context->times <= context->expectedTimes)
{
unsigned long val = timerType;
mTimers.insert(mTimers.end(), std::pair<IDevice::timer_uid_t, unsigned long>(uid, val));
return uid;
if (m_listener != NULL)
{
m_listener->OnTimeout(context->uid, context->timerType, context->times);
}
}
return 0;
}
bool CPhoneDevice::UnregisterTimer(IDevice::timer_uid_t uid)
IDevice::timer_uid_t CPhoneDevice::RegisterTimer(unsigned int timerType, unsigned int timeout, unsigned long times/* = 0*/)
{
jboolean ret = JNI_FALSE;
JNIEnv* env = NULL;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
struct sigevent evp = { 0 };
struct itimerspec ts = { 0 };
timer_t timer;
int ret;
TIMER_CONTEXT* context = new TIMER_CONTEXT();
context->device = this;
context->timerType = timerType;
context->expectedTimes = times;
evp.sigev_value.sival_ptr = context;
evp.sigev_notify = SIGEV_THREAD; //SIGEV_THREAD_ID;
evp.sigev_notify_function = CPhoneDevice::handleTimer;
// evp.sigev_notify_thread_id = gettid();
// evp.sigev_notify = SIGEV_SIGNAL;
// evp.sigev_signo = SIGUSR2;
ret = timer_create(CLOCK_REALTIME, &evp, &timer);
if( ret)
{
ALOGE("Failed to get JNI Env");
return false;
int err = errno;
delete context;
return INVALID_TIMER_UID;
}
ret = env->CallBooleanMethod(m_javaService, mUnregisterTimerMid, (jlong)uid);
if (didAttachThread)
context->uid = (unsigned long)timer;
ts.it_value.tv_sec = (timeout / 1000);
ts.it_value.tv_nsec = (timeout % 1000) * 1000;
if (times != 1)
{
m_vm->DetachCurrentThread();
ts.it_interval.tv_sec = ts.it_value.tv_sec;
ts.it_interval.tv_nsec = ts.it_value.tv_nsec;
}
if (ret == JNI_TRUE)
ret = timer_settime(timer, 0, &ts, NULL);
if(ret)
{
mTimers.erase(uid);
timer_delete(timer);
delete context;
return INVALID_TIMER_UID;
}
mTimers.insert(mTimers.end(), std::pair<IDevice::timer_uid_t, TIMER_CONTEXT*>((IDevice::timer_uid_t)timer, context));
return (IDevice::timer_uid_t)timer;
}
bool CPhoneDevice::UnregisterTimer(IDevice::timer_uid_t uid)
{
timer_t timer = (timer_t)uid;
int res = timer_delete(timer);
std::map<IDevice::timer_uid_t, TIMER_CONTEXT*>::iterator it = mTimers.find(uid);
if (it != mTimers.end())
{
delete it->second;
mTimers.erase(it);
return true;
}
return false;
}
@ -632,33 +698,6 @@ bool CPhoneDevice::ReleaseWakelock(unsigned long wakelock)
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);
if (it == mTimers.end())
{
return false;
}
unsigned long timerType = it->second & 0xFFFFFFFF;
unsigned long ntimes = (it->second & 0xFFFFFFFF00000000) >> 32;
ntimes++;
if (timerType != 100)
{
// int aa = 0;
}
it->second = timerType | (ntimes << 32);
if (m_listener == NULL)
{
return false;
}
m_listener->OnTimeout(uid, timerType, ntimes);
return true;
}
IDevice::timer_uid_t CPhoneDevice::RegisterHeartbeat(unsigned int timerType, unsigned int timeout)
{
mHeartbeatStartTime = time(NULL);

@ -162,6 +162,15 @@ public:
CPhoneDevice* m_dev;
};
struct TIMER_CONTEXT
{
CPhoneDevice* device;
unsigned int timerType;
unsigned long times;
unsigned long expectedTimes;
unsigned long uid;
};
CPhoneDevice(JavaVM* vm, jobject service, const std::string& appPath, unsigned int netId);
virtual ~CPhoneDevice();
@ -182,8 +191,6 @@ public:
virtual unsigned long RequestWakelock(unsigned long timeout);
virtual bool ReleaseWakelock(unsigned long wakelock);
virtual bool FireTimer(timer_uid_t uid, unsigned long times);
bool GetNextScheduleItem(uint32_t tsBasedZero, uint32_t scheduleTime, vector<uint32_t>& items);
void UpdatePosition(double lon, double lat, time_t ts);
@ -220,7 +227,6 @@ protected:
void QueryPowerInfo(std::map<std::string, std::string>& powerInfo);
std::string QueryCpuTemperature();
bool OnImageReady(cv::Mat& mat);
void onError(const std::string& msg);
@ -232,6 +238,11 @@ protected:
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:
JavaVM* m_vm;
@ -266,7 +277,7 @@ protected:
atomic_ulong m_timerUidFeed;
atomic_ulong m_wakelockIdFeed;
std::map<IDevice::timer_uid_t, unsigned long> mTimers;
std::map<IDevice::timer_uid_t, TIMER_CONTEXT*> mTimers;
mutable CPhoneCamera* mCamera;

@ -40,6 +40,7 @@ import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import androidx.core.content.FileProvider;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
@ -485,43 +486,24 @@ public class MicroPhotoService extends Service {
// private HashMap<Long, Integer> mTimers = new HashMap<Long, Integer>();
public boolean registerTimer(long uid, int timeout, long times) {
Context context = getApplicationContext();
// 创建延迟意图
Intent alarmIntent = new Intent();
alarmIntent.setAction(ACTION_TIMEOUT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
alarmIntent.setIdentifier(Long.toString(uid));
}
alarmIntent.putExtra(EXTRA_PARAM_TIMER_UID, uid);
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(context, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mTimers.put(Long.valueOf(uid), pendingIntent);
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) {
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
@ -534,8 +516,18 @@ public class MicroPhotoService extends Service {
public boolean unregisterTimer(long uid) {
/*
Context context = getApplicationContext();
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, pendingIntent., PendingIntent.FLAG_NO_CREATE);
if (pendingIntent != null && alarmManager != null) {
alarmManager.cancel(pendingIntent);
}
*/
Long uidObj = Long.valueOf(uid);
PendingIntent pendingIntent = mTimers.get(uidObj);
if (pendingIntent != null) {
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
@ -1201,4 +1193,27 @@ cellSignalStrengthGsm.getDbm();
};
////////////////////////GPS////////////////////
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;
}
}
Loading…
Cancel
Save