Program: 110367
Project: 110367
Buggy source:
public void invalidate(Timeline timeline) throws ExoPlaybackException, IOException {
  Timeline oldTimeline=this.timeline;
  this.timeline=timeline;
  eventHandler.obtainMessage(MSG_TIMELINE_CHANGED,timeline).sendToTarget();
  if (playingPeriod != null) {
    int index=timeline.getIndexOfPeriod(playingPeriod.id);
    if (index == Timeline.NO_PERIOD_INDEX) {
      int newPlayingPeriodIndex=mediaSource.getNewPlayingPeriodIndex(playingPeriod.index,oldTimeline);
      if (newPlayingPeriodIndex == Timeline.NO_PERIOD_INDEX) {
        stopInternal();
        return;
      }
      releasePeriodsFrom(playingPeriod);
      playingPeriod=null;
      seekToPeriodPosition(newPlayingPeriodIndex,0);
      return;
    }
    int periodCount=timeline.getPeriodCount();
    playingPeriod.index=index;
    playingPeriod.isLast=timeline.isFinal() && index == periodCount - 1;
    Period previousPeriod=playingPeriod;
    boolean seenReadingPeriod=false;
    while (previousPeriod != null) {
      Period period=previousPeriod.nextPeriod;
      index++;
      if (!period.id.equals(timeline.getPeriodId(index))) {
        if (!seenReadingPeriod) {
          index=playingPeriod.index;
          releasePeriodsFrom(playingPeriod);
          playingPeriod=null;
          seekToPeriodPosition(index,0);
          return;
        }
        loadingPeriod=previousPeriod;
        loadingPeriod.nextPeriod=null;
        releasePeriodsFrom(period);
        break;
      }
      period.index=index;
      period.isLast=timeline.isFinal() && index == periodCount - 1;
      if (period == readingPeriod) {
        seenReadingPeriod=true;
      }
      previousPeriod=period;
    }
  }
 else   if (loadingPeriod != null) {
    Object id=loadingPeriod.id;
    int index=timeline.getIndexOfPeriod(id);
    if (index == Timeline.NO_PERIOD_INDEX) {
      loadingPeriod.release();
      loadingPeriod=null;
    }
 else {
      int periodCount=timeline.getPeriodCount();
      loadingPeriod.index=index;
      loadingPeriod.isLast=timeline.isFinal() && index == periodCount - 1;
    }
  }
  if (oldTimeline != null) {
    int newPlayingIndex=playingPeriod != null ? playingPeriod.index : loadingPeriod != null ? loadingPeriod.index : mediaSource.getNewPlayingPeriodIndex(playbackInfo.periodIndex,oldTimeline);
    if (newPlayingIndex != Timeline.NO_PERIOD_INDEX && newPlayingIndex != playbackInfo.periodIndex) {
      playbackInfo=new PlaybackInfo(newPlayingIndex);
      updatePlaybackPositions();
      eventHandler.obtainMessage(MSG_PERIOD_CHANGED,playbackInfo).sendToTarget();
    }
  }
}

Fixed version (ground truth):
public void invalidate(Timeline timeline) throws ExoPlaybackException, IOException {
  Timeline oldTimeline=this.timeline;
  this.timeline=timeline;
  eventHandler.obtainMessage(MSG_TIMELINE_CHANGED,timeline).sendToTarget();
  if (playingPeriod != null) {
    int index=timeline.getIndexOfPeriod(playingPeriod.id);
    if (index == Timeline.NO_PERIOD_INDEX) {
      int newPlayingPeriodIndex=mediaSource.getNewPlayingPeriodIndex(playingPeriod.index,oldTimeline);
      if (newPlayingPeriodIndex == Timeline.NO_PERIOD_INDEX) {
        stopInternal();
        return;
      }
      releasePeriodsFrom(playingPeriod);
      playingPeriod=null;
      seekToPeriodPosition(newPlayingPeriodIndex,0);
      return;
    }
    int periodCount=timeline.getPeriodCount();
    playingPeriod.index=index;
    playingPeriod.isLast=timeline.isFinal() && index == periodCount - 1;
    Period previousPeriod=playingPeriod;
    boolean seenReadingPeriod=false;
    while (previousPeriod.nextPeriod != null) {
      Period period=previousPeriod.nextPeriod;
      index++;
      if (!period.id.equals(timeline.getPeriodId(index))) {
        if (!seenReadingPeriod) {
          index=playingPeriod.index;
          releasePeriodsFrom(playingPeriod);
          playingPeriod=null;
          seekToPeriodPosition(index,0);
          return;
        }
        loadingPeriod=previousPeriod;
        loadingPeriod.nextPeriod=null;
        releasePeriodsFrom(period);
        break;
      }
      period.index=index;
      period.isLast=timeline.isFinal() && index == periodCount - 1;
      if (period == readingPeriod) {
        seenReadingPeriod=true;
      }
      previousPeriod=period;
    }
  }
 else   if (loadingPeriod != null) {
    Object id=loadingPeriod.id;
    int index=timeline.getIndexOfPeriod(id);
    if (index == Timeline.NO_PERIOD_INDEX) {
      loadingPeriod.release();
      loadingPeriod=null;
    }
 else {
      int periodCount=timeline.getPeriodCount();
      loadingPeriod.index=index;
      loadingPeriod.isLast=timeline.isFinal() && index == periodCount - 1;
    }
  }
  if (oldTimeline != null) {
    int newPlayingIndex=playingPeriod != null ? playingPeriod.index : loadingPeriod != null ? loadingPeriod.index : mediaSource.getNewPlayingPeriodIndex(playbackInfo.periodIndex,oldTimeline);
    if (newPlayingIndex != Timeline.NO_PERIOD_INDEX && newPlayingIndex != playbackInfo.periodIndex) {
      playbackInfo=new PlaybackInfo(newPlayingIndex);
      updatePlaybackPositions();
      eventHandler.obtainMessage(MSG_PERIOD_CHANGED,playbackInfo).sendToTarget();
    }
  }
}