|
|
|
@ -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);
|
|
|
|
|
TIMER_CONTEXT* context = (TIMER_CONTEXT*)(si->si_value.sival_ptr);
|
|
|
|
|
context->device->handleTimerImpl(context);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ALOGI("NDK RegTimer: uid=%lld Type=%u timeout=%u", uid, timerType, timeout);
|
|
|
|
|
bool CPhoneDevice::RegisterHandlerForSignal(int sig)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
// Establish handler for timer signal
|
|
|
|
|
struct sigaction sa;
|
|
|
|
|
sigset_t mask;
|
|
|
|
|
|
|
|
|
|
JNIEnv* env = NULL;
|
|
|
|
|
bool didAttachThread = false;
|
|
|
|
|
bool res = GetJniEnv(m_vm, &env, didAttachThread);
|
|
|
|
|
if (!res)
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
unsigned long val = timerType;
|
|
|
|
|
mTimers.insert(mTimers.end(), std::pair<IDevice::timer_uid_t, unsigned long>(uid, val));
|
|
|
|
|
return uid;
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = timer_settime(timer, 0, &ts, NULL);
|
|
|
|
|
|
|
|
|
|
if(ret)
|
|
|
|
|
{
|
|
|
|
|
timer_delete(timer);
|
|
|
|
|
delete context;
|
|
|
|
|
return INVALID_TIMER_UID;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ret == JNI_TRUE)
|
|
|
|
|
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())
|
|
|
|
|
{
|
|
|
|
|
mTimers.erase(uid);
|
|
|
|
|
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);
|
|
|
|
|