class MediaPeriodQueue {

  public boolean updateQueuedPeriods(long rendererPositionUs, long maxRendererReadPositionUs) {
    // TODO: Merge this into setTimeline so that the queue gets updated as soon as the new timeline
    // is set, once all cases handled by ExoPlayerImplInternal.handleSourceInfoRefreshed can be
    // handled here.
    MediaPeriodHolder previousPeriodHolder = null;
    MediaPeriodHolder periodHolder = getFrontPeriod();
    while (periodHolder != null) {
      MediaPeriodInfo oldPeriodInfo = periodHolder.info;

      // Get period info based on new timeline.
      MediaPeriodInfo newPeriodInfo;
      if (previousPeriodHolder == null) {
        // The id and start position of the first period have already been verified by
        // ExoPlayerImplInternal.handleSourceInfoRefreshed. Just update duration, isLastInTimeline
        // and isLastInPeriod flags.
        newPeriodInfo = getUpdatedMediaPeriodInfo(oldPeriodInfo);
      } else {
        newPeriodInfo = getFollowingMediaPeriodInfo(previousPeriodHolder, rendererPositionUs);
        if (newPeriodInfo == null) {
          // We've loaded a next media period that is not in the new timeline.
          return !removeAfter(previousPeriodHolder);
        }
        if (!canKeepMediaPeriodHolder(oldPeriodInfo, newPeriodInfo)) {
          // The new media period has a different id or start position.
          return !removeAfter(previousPeriodHolder);
        }
      }

      // Use new period info, but keep old content position.
      periodHolder.info = newPeriodInfo.copyWithContentPositionUs(oldPeriodInfo.contentPositionUs);

      if (!areDurationsCompatible(oldPeriodInfo.durationUs, newPeriodInfo.durationUs)) {
        // The period duration changed. Remove all subsequent periods and check whether we read
        // beyond the new duration.
        long newDurationInRendererTime =
            newPeriodInfo.durationUs == C.TIME_UNSET
                ? Long.MAX_VALUE
                : periodHolder.toRendererTime(newPeriodInfo.durationUs);
        boolean isReadingAndReadBeyondNewDuration =
            periodHolder == reading
                && (maxRendererReadPositionUs == C.TIME_END_OF_SOURCE
                    || maxRendererReadPositionUs >= newDurationInRendererTime);
        boolean readingPeriodRemoved = removeAfter(periodHolder);
        return !readingPeriodRemoved && !isReadingAndReadBeyondNewDuration;
      }

      previousPeriodHolder = periodHolder;
      periodHolder = periodHolder.getNext();
    }
    return true;
  }

  public  MediaPeriodQueue();

}