private void onFailureInternal(
      String id, DataSource<T> dataSource, Throwable throwable, boolean isFinished) {
    if (FrescoSystrace.isTracing()) {
      FrescoSystrace.beginSection("AbstractDraweeController#onFailureInternal");
    }
    // ignore late callbacks (data source that failed is not the one we expected)
    if (!isExpectedDataSource(id, dataSource)) {
      logMessageAndFailure("ignore_old_datasource @ onFailure", throwable);
      dataSource.close();
      if (FrescoSystrace.isTracing()) {
        FrescoSystrace.endSection();
      }
      return;
    }
    mEventTracker.recordEvent(
        isFinished ? Event.ON_DATASOURCE_FAILURE : Event.ON_DATASOURCE_FAILURE_INT);
    // fail only if the data source is finished
    if (isFinished) {
      logMessageAndFailure("final_failed @ onFailure", throwable);
      mDataSource = null;
      mHasFetchFailed = true;
      // Set the previously available image if available.
      final SettableDraweeHierarchy hierarchy = mSettableDraweeHierarchy;
      if (hierarchy != null) {
        if (mRetainImageOnFailure && mDrawable != null) {
          hierarchy.setImage(mDrawable, 1f, true);
        } else if (shouldRetryOnTap()) {
          hierarchy.setRetry(throwable);
        } else {
          hierarchy.setFailure(throwable);
        }
      }
      reportFailure(throwable, dataSource);
      // IMPORTANT: do not execute any instance-specific code after this point
    } else {
      logMessageAndFailure("intermediate_failed @ onFailure", throwable);
      reportIntermediateFailure(throwable);
      // IMPORTANT: do not execute any instance-specific code after this point
    }
    if (FrescoSystrace.isTracing()) {
      FrescoSystrace.endSection();
    }
  }
Returns whether the gesture should be handled by the controller
drawee/src/main/java/com/facebook/drawee/controller/AbstractDraweeController.java