/**
     * Periodically ping (that is send a CONNECT_MEDIATOR packet) the BackEnd to detect when the
     * device is reachable again. When the BackEnd receives a CONNECT_MEDIATOR packet it resets the
     * input connection --> If blocked waiting for incoming commands, the InputManager thread should
     * get an IOException.
     */
    public void run() {
      int attemptCnt = 0;
      long startTime = System.currentTimeMillis();
      try {
        while (!ping(attemptCnt)) {
          attemptCnt++;
          if ((System.currentTimeMillis() - startTime) > maxDisconnectionTime) {
            throw new ICPException("Max disconnection timeout expired");
          } else {
            waitABit(retryTime);
          }
        }

        // Ping succeeded
        myLogger.log(Logger.INFO, "Reconnection ping OK.");
        synchronized (this) {
          pingOK = true;
          setReachable();
          myKeepAliveManager.update();
          // Activate postponed commands flushing
          waitingForFlush = myStub.flush();
        }
      } catch (ICPException icpe) {
        // Impossible to reconnect to the BackEnd
        myLogger.log(
            Logger.SEVERE,
            "Impossible to reconnect to the BackEnd (" + System.currentTimeMillis() + ")",
            icpe);
        if (myConnectionListener != null) {
          myConnectionListener.handleConnectionEvent(ConnectionListener.RECONNECTION_FAILURE, null);
        }
      }
    }
 private synchronized void update() {
   if (kaTimeout > 0) {
     TimerDispatcher td = TimerDispatcher.getTimerDispatcher();
     if (kaTimer != null) {
       td.remove(kaTimer);
     }
     kaTimer = td.add(new Timer(System.currentTimeMillis() + kaTimeout, this));
   }
 }
 /**
  * Set the reachability state as "unreachable" and starts a separate thread that periodically
  * ping the back-end to detect when we are reachable again
  */
 private synchronized void setUnreachable(boolean missingKA) {
   if (reachable) {
     if (missingKA || !pingOK) {
       if (myConnectionListener != null) {
         myConnectionListener.handleConnectionEvent(ConnectionListener.DISCONNECTED, null);
       }
       reachable = false;
       myLogger.log(Logger.INFO, "Starting DM (" + System.currentTimeMillis() + ").");
       myThread = new Thread(this);
       myThread.start();
       if (pingOK) {
         // The InputManager is blocked waiting for data that will never arrive
         // Kill it and create a new one
         myInputManager.kill();
         myInputManager = new InputManager();
         myInputManager.start();
       }
     }
   }
 }