@Override
    public boolean shouldRetry(
        AmazonWebServiceRequest originalRequest,
        AmazonClientException exception,
        int retriesAttempted) {
      // Always retry on client exceptions caused by IOException
      if (exception.getCause() instanceof IOException) return true;

      // Only retry on a subset of service exceptions
      if (exception instanceof AmazonServiceException) {
        AmazonServiceException ase = (AmazonServiceException) exception;

        /*
         * For 500 internal server errors and 503 service
         * unavailable errors, we want to retry, but we need to use
         * an exponential back-off strategy so that we don't overload
         * a server with a flood of retries.
         */
        if (ase.getStatusCode() == HttpStatus.SC_INTERNAL_SERVER_ERROR
            || ase.getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE) {
          return true;
        }

        /*
         * Throttling is reported as a 400 error from newer services. To try
         * and smooth out an occasional throttling error, we'll pause and
         * retry, hoping that the pause is long enough for the request to
         * get through the next time.
         */
        if (RetryUtils.isThrottlingException(ase)) return true;

        /*
         * Clock skew exception. If it is then we will get the time offset
         * between the device time and the server time to set the clock skew
         * and then retry the request.
         */
        if (RetryUtils.isClockSkewError(ase)) return true;
      }

      return false;
    }
    /** {@inheritDoc} */
    @Override
    public final long delayBeforeNextRetry(
        AmazonWebServiceRequest originalRequest,
        AmazonClientException exception,
        int retriesAttempted) {
      if (retriesAttempted < 0) return 0;
      if (retriesAttempted > MAX_RETRIES_BEFORE_MAX_BACKOFF) return MAX_BACKOFF_IN_MILLISECONDS;

      int scaleFactor;
      if (exception instanceof AmazonServiceException
          && RetryUtils.isThrottlingException((AmazonServiceException) exception)) {
        scaleFactor =
            THROTTLING_SCALE_FACTOR + random.nextInt(THROTTLING_SCALE_FACTOR_RANDOM_RANGE);
      } else {
        scaleFactor = SCALE_FACTOR;
      }

      long delay = (1L << retriesAttempted) * scaleFactor;
      delay = Math.min(delay, MAX_BACKOFF_IN_MILLISECONDS);

      return delay;
    }