1

We are trying to implement timer for native code in android .The timer should work precisely during wake and sleep mode .When timer expires then our native code will send DPD(Dead peer detection) messages to the network We tried following approaches .

  1. Using android framework API's for alarm manager in userspace code and below are the results:

    • This doesn't give the accurate results even during wake state for small timers like 2s,3s,5s.
    • Does not work precisely for sleep mode also.
  2. We tried to use kernel timer in kernel space code and below are the results:

    • Works perfectly for wake state.
    • But for sleep state timers do not expire at all.When we wake the device up manually then the timers get expire .So,in conclusion kernel timers do not work during sleep state.

3.Using wake lock *We are trying to avoid use of wake lock as it may cause significant performance issues

P.S - Open source Ipsec implementation strongswan sends the DPD messages precise time even during sleep mode .But it seems that strongswan does not use wake lock ,so we are still trying to figure out how it works during sleep mode.Anybody searching for answer to this question might want to look into that code.

Can anyone please suggest something to resolve this issue.

somil
  • 13
  • 3

3 Answers3

0

When Android goes to sleep it will have several states, the last one is freezing all the processes and turning off the CPU. In that case your times are not going to fire. You must create an event that will wake up the kernel and set a wake lock so the cpu will not turn off again. This can be done using android alarms.

skoperst
  • 2,259
  • 1
  • 23
  • 35
0

The only way to have the timer work precisely in sleep mode is to keep device partially awake using Wakelock. But make sure your application really need the timer to work all the time, because the document says,

Device battery life will be significantly affected by the use of this API. Do not acquire PowerManager.WakeLocks unless you really need them, use the minimum levels possible, and be sure to release them as soon as possible.

Go through PowerManager Class, use the below code to acquire partial wake lock

  PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
  PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");
  wl.acquire();
  ..cpu will stay on during this section..
  wl.release();
Shree
  • 354
  • 2
  • 21
-1

Initiate timer and when app goes background then start alarmManager. Again if app comes foreground and timer is not expired then it will re trigger the timer and will remove the alarm manager.

private int timeToStart;
private TimerState timerState;

 private static final int MAX_TIME = 60;  //Time length is 60 seconds

private enum TimerState {
    STOPPED,
    RUNNING

}


private void initTimer() {
    Log.e(TAG,"initTimer called");

    long startTime = mPrefs.getStartedTime(); //here mprefs is your shared preference manager
    if (startTime > 0) {
        timeToStart = (int) (MAX_TIME - (getNow() - startTime));
        if (timeToStart <= 0) {
            // TIMER EXPIRED
            onTimerFinish();
        } else {
            startTimer();
            timerState = TimerState.RUNNING;
        }
    } else {
        timeToStart = MAX_TIME;
        timerState = TimerState.STOPPED;
    }
}

    private long getNow() {
    Calendar rightNow = Calendar.getInstance();
    return rightNow.getTimeInMillis() / 1000;
}

    private void onTimerFinish() {
    Log.e(TAG,"onTimerFinish() called");

    timerState = TimerState.STOPPED;
    mPrefs.setStartedTime(0);
    timeToStart = MAX_TIME;

}

private void startTimer() {
    Log.e(TAG,"startTimer() called");

    countDownTimer = new CountDownTimer(timeToStart * 1000, 1000) {

        @Override
        public void onTick(long millisUntilFinished) {
            timeToStart -= 1;
        }

        @Override
        public void onFinish() {
            onTimerFinish();
        }
    }.start();
}

    public void setAlarmManager() {
    int wakeUpTime = (mPrefs.getStartedTime() + MAX_TIME) * 1000;
    AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(this, TimeReceiver.class);
    PendingIntent sender = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        am.setAlarmClock(new AlarmManager.AlarmClockInfo(wakeUpTime, sender), sender);
    } else {
        am.set(AlarmManager.RTC_WAKEUP, wakeUpTime, sender);
    }
}

    public void removeAlarmManager() {
    Intent intent = new Intent(this, TimeReceiver.class);
    PendingIntent sender = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    am.cancel(sender);
}

    @Override
    protected void onResume() {
    super.onResume();
        initTimer();
        removeAlarmManager();

}
demo_Ashif
  • 316
  • 4
  • 10