code: @Override
      public boolean onIdleTimeout() {
          switch (closed.get()) {
              case NOT_CLOSED: {
                  long elapsed = Millisecond100Clock.currentTimeMillis() - idleTime;
                  if (log.isDebugEnabled()) {
                      log.debug("HTTP2 session on idle timeout. The elapsed time is {} - {}", elapsed, endPoint.getMaxIdleTimeout());
                  }
                  return elapsed >= endPoint.getMaxIdleTimeout() && notifyIdleTimeout(this);
              }
              case LOCALLY_CLOSED:
              case REMOTELY_CLOSED: {
                  abort(new TimeoutException("Idle timeout " + endPoint.getMaxIdleTimeout() + " ms"));
                  return false;
              }
              default: {
                  return false;
              }
          }
      }
docs: This method is invoked when the idle timeout triggers. We check the close state
  to act appropriately:
  <ul>
  <li>NOT_CLOSED: it's a real idle timeout, we just initiate a close, see
  {@link #close(int, String, Callback)}.</li>
  <li>LOCALLY_CLOSED: we have sent a GO_AWAY and only shutdown the output, but the
  other peer did not close the connection so we never received the TCP FIN, and
  therefore we terminate.</li>
  <li>REMOTELY_CLOSED: the other peer sent us a GO_AWAY, we should have queued a
  disconnect, but for some reason it was not processed (for example, queue was
  stuck because of TCP congestion), therefore we terminate.
  See {@link #onGoAway(GoAwayFrame)}.</li>
  </ul>
  
  @return true if the session should be closed, false otherwise
  @see #onGoAway(GoAwayFrame)
  @see #close(int, String, Callback)
  @see #onShutdown()