public Result tick() {
    if (System.currentTimeMillis() >= mLastEventHorizonMs) {
      return Result.EXPIRED;
    }
    if (System.currentTimeMillis() < mNextEventMs) {
      return Result.NOT_READY;
    }
    mNextEventMs = System.currentTimeMillis() + mIntervalMs;
    long next = Math.min(mIntervalMs * 2, mMaxIntervalMs);
    // Account for overflow.
    if (next < mIntervalMs) {
      next = Integer.MAX_VALUE;
    }
    mIntervalMs = next;
    mNumEvents++;
    return Result.READY;
  }
@Test
  public void expiration() {
    int maxTotalWaitTimeMs = 1000;
    ExponentialTimer timer = new ExponentialTimer(0, 0, 0, maxTotalWaitTimeMs);
    assertEquals(ExponentialTimer.Result.READY, timer.tick());
    CommonUtils.sleepMs(maxTotalWaitTimeMs);
    assertEquals(ExponentialTimer.Result.EXPIRED, timer.tick());
  }