@Override
  public void draw(@NonNull Canvas canvas) {
    CompositionLayer compositionLayer = this.compositionLayer;
    if (compositionLayer == null) {
      return;
    }
    boolean asyncUpdatesEnabled = getAsyncUpdatesEnabled();
    try {
      if (asyncUpdatesEnabled) {
        setProgressDrawLock.acquire();
      }
      if (L.isTraceEnabled()) {
        L.beginSection("Drawable#draw");
      }

      if (asyncUpdatesEnabled && shouldSetProgressBeforeDrawing()) {
        setProgress(animator.getAnimatedValueAbsolute());
      }

      if (safeMode) {
        try {
          if (useSoftwareRendering) {
            renderAndDrawAsBitmap(canvas, compositionLayer);
          } else {
            drawDirectlyToCanvas(canvas);
          }
        } catch (Throwable e) {
          Logger.error("Lottie crashed in draw!", e);
        }
      } else {
        if (useSoftwareRendering) {
          renderAndDrawAsBitmap(canvas, compositionLayer);
        } else {
          drawDirectlyToCanvas(canvas);
        }
      }

      isDirty = false;
    } catch (InterruptedException e) {
      // Do nothing.
    } finally {
      if (L.isTraceEnabled()) {
        L.endSection("Drawable#draw");
      }
      if (asyncUpdatesEnabled) {
        setProgressDrawLock.release();
        if (compositionLayer.getProgress() != animator.getAnimatedValueAbsolute()) {
          setProgressExecutor.execute(updateProgressRunnable);
        }
      }
    }
  }
Helper for the async execution path to potentially call setProgress
before drawing if the current progress has drifted sufficiently far
from the last set progress.

@see AsyncUpdates
@see #setAsyncUpdates(AsyncUpdates)
lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java