+
+ /**
+ * Sets the retry timer
+ */
+ private void setRetryTimer(ErrorState error)
+ {
+ long timeout;
+
+ switch (error)
+ {
+ case AUTH_FAILED:
+ timeout = 20000;
+ break;
+ case PEER_AUTH_FAILED:
+ timeout = 20000;
+ break;
+ case LOOKUP_FAILED:
+ timeout = 10000;
+ break;
+ case UNREACHABLE:
+ timeout = 10000;
+ break;
+ case PASSWORD_MISSING:
+ /* this needs user intervention (entering the password) */
+ timeout = 0;
+ break;
+ case CERTIFICATE_UNAVAILABLE:
+ /* if this is because the device has to be unlocked we might be able to reconnect */
+ timeout = 10000;
+ break;
+ default:
+ timeout = 20000;
+ break;
+ }
+ mRetryTimeout = mRetryIn = timeout;
+ if (timeout <= 0)
+ {
+ return;
+ }
+ mHandler.sendMessageAtTime(mHandler.obtainMessage(RETRY_MSG), SystemClock.uptimeMillis() + RETRY_INTERVAL);
+ }
+
+ /**
+ * Reset the retry timer
+ */
+ private void resetRetryTimer()
+ {
+ mRetryTimeout = 0;
+ mRetryIn = 0;
+ }
+
+ /**
+ * Special Handler subclass that handles the retry countdown (more accurate than CountDownTimer)
+ */
+ private static class RetryHandler extends Handler {
+ WeakReference<VpnStateService> mService;
+
+ public RetryHandler(VpnStateService service)
+ {
+ mService = new WeakReference<>(service);
+ }
+
+ @Override
+ public void handleMessage(Message msg)
+ {
+ /* handle retry countdown */
+ if (mService.get().mRetryTimeout <= 0)
+ {
+ return;
+ }
+ mService.get().mRetryIn -= RETRY_INTERVAL;
+ if (mService.get().mRetryIn > 0)
+ {
+ /* calculate next interval before notifying listeners */
+ long next = SystemClock.uptimeMillis() + RETRY_INTERVAL;
+
+ for (VpnStateListener listener : mService.get().mListeners)
+ {
+ listener.stateChanged();
+ }
+ sendMessageAtTime(obtainMessage(RETRY_MSG), next);
+ }
+ else
+ {
+ mService.get().reconnect();
+ }
+ }
+ }