Works
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieProperty.java b/lottie/src/main/java/com/airbnb/lottie/LottieProperty.java
index 4932ded..b9ec204 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieProperty.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieProperty.java
@@ -74,6 +74,7 @@
    * [0,100]
    */
   Integer OPACITY = 4;
+  Integer DROP_SHADOW_COLOR = 5;
   /**
    * In Px
    */
@@ -167,6 +168,22 @@
    * In Dp
    */
   Float TEXT_SIZE = 14f;
+  /**
+   * [0,100]
+   */
+  Float DROP_SHADOW_OPACITY = 15f;
+  /**
+   * Degrees from 12 o'clock.
+   */
+  Float DROP_SHADOW_DIRECTION = 16f;
+  /**
+   * In Px
+   */
+  Float DROP_SHADOW_DISTANCE = 17f;
+  /**
+   * In Px
+   */
+  Float DROP_SHADOW_RADIUS = 18f;
 
   ColorFilter COLOR_FILTER = new ColorFilter();
   /**
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/BaseStrokeContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/BaseStrokeContent.java
index c257238..643d9ce 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/BaseStrokeContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/BaseStrokeContent.java
@@ -20,6 +20,7 @@
 import com.airbnb.lottie.LottieProperty;
 import com.airbnb.lottie.animation.LPaint;
 import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
+import com.airbnb.lottie.animation.keyframe.DropShadowKeyframeAnimation;
 import com.airbnb.lottie.animation.keyframe.FloatKeyframeAnimation;
 import com.airbnb.lottie.animation.keyframe.IntegerKeyframeAnimation;
 import com.airbnb.lottie.animation.keyframe.ValueCallbackKeyframeAnimation;
@@ -57,6 +58,8 @@
   @Nullable private BaseKeyframeAnimation<Float, Float> blurAnimation;
   float blurMaskFilterRadius = 0f;
 
+  @Nullable private DropShadowKeyframeAnimation dropShadowAnimation;
+
   BaseStrokeContent(final LottieDrawable lottieDrawable, BaseLayer layer, Paint.Cap cap,
       Paint.Join join, float miterLimit, AnimatableIntegerValue opacity, AnimatableFloatValue width,
       List<AnimatableFloatValue> dashPattern, AnimatableFloatValue offset) {
@@ -102,13 +105,14 @@
       dashPatternOffsetAnimation.addUpdateListener(this);
     }
 
-    if (layer.getBlurEffect() == null) {
-      blurAnimation = null;
-    } else {
+    if (layer.getBlurEffect() != null) {
       blurAnimation = layer.getBlurEffect().getBlurriness().createAnimation();
       blurAnimation.addUpdateListener(this);
       layer.addAnimation(blurAnimation);
     }
+    if (layer.getDropShadowEffect() != null) {
+      dropShadowAnimation = new DropShadowKeyframeAnimation(this, layer, layer.getDropShadowEffect());
+    }
   }
 
   @Override public void onValueChanged() {
@@ -180,6 +184,9 @@
       }
       blurMaskFilterRadius = blurRadius;
     }
+    if (dropShadowAnimation != null) {
+      dropShadowAnimation.applyTo(paint);
+    }
 
     for (int i = 0; i < pathGroups.size(); i++) {
       PathGroup pathGroup = pathGroups.get(i);
@@ -359,6 +366,16 @@
         blurAnimation.addUpdateListener(this);
         layer.addAnimation(blurAnimation);
       }
+    } else if (property == LottieProperty.DROP_SHADOW_COLOR && dropShadowAnimation != null) {
+      dropShadowAnimation.setColorCallback((LottieValueCallback<Integer>) callback);
+    } else if (property == LottieProperty.DROP_SHADOW_OPACITY && dropShadowAnimation != null) {
+      dropShadowAnimation.setOpacityCallback((LottieValueCallback<Float>) callback);
+    } else if (property == LottieProperty.DROP_SHADOW_DIRECTION && dropShadowAnimation != null) {
+      dropShadowAnimation.setDirectionCallback((LottieValueCallback<Float>) callback);
+    } else if (property == LottieProperty.DROP_SHADOW_DISTANCE && dropShadowAnimation != null) {
+      dropShadowAnimation.setDistanceCallback((LottieValueCallback<Float>) callback);
+    } else if (property == LottieProperty.DROP_SHADOW_RADIUS && dropShadowAnimation != null) {
+      dropShadowAnimation.setRadiusCallback((LottieValueCallback<Float>) callback);
     }
   }
 
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java
index 0578295..35f472f 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java
@@ -18,7 +18,7 @@
 import com.airbnb.lottie.animation.LPaint;
 import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
 import com.airbnb.lottie.animation.keyframe.ColorKeyframeAnimation;
-import com.airbnb.lottie.animation.keyframe.FloatKeyframeAnimation;
+import com.airbnb.lottie.animation.keyframe.DropShadowKeyframeAnimation;
 import com.airbnb.lottie.animation.keyframe.ValueCallbackKeyframeAnimation;
 import com.airbnb.lottie.model.KeyPath;
 import com.airbnb.lottie.model.content.ShapeFill;
@@ -44,18 +44,21 @@
   @Nullable private BaseKeyframeAnimation<Float, Float> blurAnimation;
   float blurMaskFilterRadius;
 
+  @Nullable private DropShadowKeyframeAnimation dropShadowAnimation;
+
   public FillContent(final LottieDrawable lottieDrawable, BaseLayer layer, ShapeFill fill) {
     this.layer = layer;
     name = fill.getName();
     hidden = fill.isHidden();
     this.lottieDrawable = lottieDrawable;
-    if (layer.getBlurEffect() == null) {
-      blurAnimation = null;
-    } else {
+    if (layer.getBlurEffect() != null) {
       blurAnimation = layer.getBlurEffect().getBlurriness().createAnimation();
       blurAnimation.addUpdateListener(this);
       layer.addAnimation(blurAnimation);
     }
+    if (layer.getDropShadowEffect() != null) {
+      dropShadowAnimation = new DropShadowKeyframeAnimation(this, layer, layer.getDropShadowEffect());
+    }
 
     if (fill.getColor() == null || fill.getOpacity() == null) {
       colorAnimation = null;
@@ -107,12 +110,15 @@
       float blurRadius = blurAnimation.getValue();
       if (blurRadius == 0f) {
         paint.setMaskFilter(null);
-      } else if (blurRadius != blurMaskFilterRadius){
+      } else if (blurRadius != blurMaskFilterRadius) {
         BlurMaskFilter blur = layer.getBlurMaskFilter(blurRadius);
         paint.setMaskFilter(blur);
       }
       blurMaskFilterRadius = blurRadius;
     }
+    if (dropShadowAnimation != null) {
+      dropShadowAnimation.applyTo(paint);
+    }
 
     path.reset();
     for (int i = 0; i < paths.size(); i++) {
@@ -173,6 +179,16 @@
         blurAnimation.addUpdateListener(this);
         layer.addAnimation(blurAnimation);
       }
+    } else if (property == LottieProperty.DROP_SHADOW_COLOR && dropShadowAnimation != null) {
+      dropShadowAnimation.setColorCallback((LottieValueCallback<Integer>) callback);
+    } else if (property == LottieProperty.DROP_SHADOW_OPACITY && dropShadowAnimation != null) {
+      dropShadowAnimation.setOpacityCallback((LottieValueCallback<Float>) callback);
+    } else if (property == LottieProperty.DROP_SHADOW_DIRECTION && dropShadowAnimation != null) {
+      dropShadowAnimation.setDirectionCallback((LottieValueCallback<Float>) callback);
+    } else if (property == LottieProperty.DROP_SHADOW_DISTANCE && dropShadowAnimation != null) {
+      dropShadowAnimation.setDistanceCallback((LottieValueCallback<Float>) callback);
+    } else if (property == LottieProperty.DROP_SHADOW_RADIUS && dropShadowAnimation != null) {
+      dropShadowAnimation.setRadiusCallback((LottieValueCallback<Float>) callback);
     }
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java
index c5a4478..8d3c5ca 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java
@@ -23,6 +23,7 @@
 import com.airbnb.lottie.LottieProperty;
 import com.airbnb.lottie.animation.LPaint;
 import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
+import com.airbnb.lottie.animation.keyframe.DropShadowKeyframeAnimation;
 import com.airbnb.lottie.animation.keyframe.FloatKeyframeAnimation;
 import com.airbnb.lottie.animation.keyframe.ValueCallbackKeyframeAnimation;
 import com.airbnb.lottie.model.KeyPath;
@@ -62,6 +63,7 @@
   private final int cacheSteps;
   @Nullable private BaseKeyframeAnimation<Float, Float> blurAnimation;
   float blurMaskFilterRadius = 0f;
+  @Nullable private DropShadowKeyframeAnimation dropShadowAnimation;
 
   public GradientFillContent(final LottieDrawable lottieDrawable, BaseLayer layer, GradientFill fill) {
     this.layer = layer;
@@ -88,13 +90,14 @@
     endPointAnimation.addUpdateListener(this);
     layer.addAnimation(endPointAnimation);
 
-    if (layer.getBlurEffect() == null) {
-      blurAnimation = null;
-    } else {
+    if (layer.getBlurEffect() != null) {
       blurAnimation = layer.getBlurEffect().getBlurriness().createAnimation();
       blurAnimation.addUpdateListener(this);
       layer.addAnimation(blurAnimation);
     }
+    if (layer.getDropShadowEffect() != null) {
+      dropShadowAnimation = new DropShadowKeyframeAnimation(this, layer, layer.getDropShadowEffect());
+    }
   }
 
   @Override public void onValueChanged() {
@@ -145,6 +148,9 @@
       }
       blurMaskFilterRadius = blurRadius;
     }
+    if (dropShadowAnimation != null) {
+      dropShadowAnimation.applyTo(paint);
+    }
 
     int alpha = (int) ((parentAlpha / 255f * opacityAnimation.getValue() / 100f) * 255);
     paint.setAlpha(clamp(alpha, 0, 255));
@@ -295,6 +301,16 @@
         blurAnimation.addUpdateListener(this);
         layer.addAnimation(blurAnimation);
       }
+    } else if (property == LottieProperty.DROP_SHADOW_COLOR && dropShadowAnimation != null) {
+      dropShadowAnimation.setColorCallback((LottieValueCallback<Integer>) callback);
+    } else if (property == LottieProperty.DROP_SHADOW_OPACITY && dropShadowAnimation != null) {
+      dropShadowAnimation.setOpacityCallback((LottieValueCallback<Float>) callback);
+    } else if (property == LottieProperty.DROP_SHADOW_DIRECTION && dropShadowAnimation != null) {
+      dropShadowAnimation.setDirectionCallback((LottieValueCallback<Float>) callback);
+    } else if (property == LottieProperty.DROP_SHADOW_DISTANCE && dropShadowAnimation != null) {
+      dropShadowAnimation.setDistanceCallback((LottieValueCallback<Float>) callback);
+    } else if (property == LottieProperty.DROP_SHADOW_RADIUS && dropShadowAnimation != null) {
+      dropShadowAnimation.setRadiusCallback((LottieValueCallback<Float>) callback);
     }
   }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/DropShadowKeyframeAnimation.java b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/DropShadowKeyframeAnimation.java
new file mode 100644
index 0000000..128913a
--- /dev/null
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/DropShadowKeyframeAnimation.java
@@ -0,0 +1,100 @@
+package com.airbnb.lottie.animation.keyframe;
+
+import android.graphics.Color;
+import android.graphics.Paint;
+
+import androidx.annotation.Nullable;
+
+import com.airbnb.lottie.model.layer.BaseLayer;
+import com.airbnb.lottie.parser.DropShadowEffect;
+import com.airbnb.lottie.value.LottieFrameInfo;
+import com.airbnb.lottie.value.LottieValueCallback;
+
+public class DropShadowKeyframeAnimation implements BaseKeyframeAnimation.AnimationListener {
+  private static final double DEG_TO_RAD = Math.PI / 180.0;
+
+  private final BaseKeyframeAnimation.AnimationListener listener;
+  private final BaseKeyframeAnimation<Integer, Integer> color;
+  private final BaseKeyframeAnimation<Float, Float> opacity;
+  private final BaseKeyframeAnimation<Float, Float> direction;
+  private final BaseKeyframeAnimation<Float, Float> distance;
+  private final BaseKeyframeAnimation<Float, Float> radius;
+
+  private boolean isDirty = true;
+
+  public DropShadowKeyframeAnimation(BaseKeyframeAnimation.AnimationListener listener, BaseLayer layer, DropShadowEffect dropShadowEffect) {
+    this.listener = listener;
+    color = dropShadowEffect.getColor().createAnimation();
+    color.addUpdateListener(this);
+    layer.addAnimation(color);
+    opacity = dropShadowEffect.getOpacity().createAnimation();
+    opacity.addUpdateListener(this);
+    layer.addAnimation(opacity);
+    direction = dropShadowEffect.getDirection().createAnimation();
+    direction.addUpdateListener(this);
+    layer.addAnimation(direction);
+    distance = dropShadowEffect.getDistance().createAnimation();
+    distance.addUpdateListener(this);
+    layer.addAnimation(distance);
+    radius = dropShadowEffect.getRadius().createAnimation();
+    radius.addUpdateListener(this);
+    layer.addAnimation(radius);
+  }
+
+  @Override public void onValueChanged() {
+    isDirty = true;
+    listener.onValueChanged();
+  }
+
+  public void applyTo(Paint paint) {
+    if (!isDirty) {
+      return;
+    }
+    isDirty = false;
+
+    double directionRad = ((double) direction.getValue()) * DEG_TO_RAD;
+    float distance = this.distance.getValue();
+    float x = ((float) Math.sin(directionRad)) * distance;
+    float y = ((float) Math.cos(directionRad + Math.PI)) * distance;
+    int baseColor = color.getValue();
+    int opacity = Math.round(this.opacity.getValue());
+    int color = Color.argb(opacity, Color.red(baseColor), Color.green(baseColor), Color.blue(baseColor));
+    float radius = this.radius.getValue();
+    paint.setShadowLayer(radius, x, y, color);
+  }
+
+  public void setColorCallback(@Nullable  LottieValueCallback<Integer> callback) {
+   color.setValueCallback(callback);
+  }
+
+  public void setOpacityCallback(@Nullable final LottieValueCallback<Float> callback) {
+    if (callback == null) {
+      opacity.setValueCallback(null);
+      return;
+    }
+    opacity.setValueCallback(new LottieValueCallback<Float>() {
+      @Nullable
+      @Override
+      public Float getValue(LottieFrameInfo<Float> frameInfo) {
+        Float value = callback.getValue(frameInfo);
+        if (value == null) {
+          return null;
+        }
+        // Convert [0,100] to [0,255] because other dynamic properties use [0,100].
+        return value * 2.55f;
+      }
+    });
+  }
+
+  public void setDirectionCallback(@Nullable LottieValueCallback<Float> callback) {
+    direction.setValueCallback(callback);
+  }
+
+  public void setDistanceCallback(@Nullable LottieValueCallback<Float> callback) {
+    distance.setValueCallback(callback);
+  }
+
+  public void setRadiusCallback(@Nullable LottieValueCallback<Float> callback) {
+    radius.setValueCallback(callback);
+  }
+}
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
index bc496da..c0a1cb1 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
@@ -31,6 +31,7 @@
 import com.airbnb.lottie.model.content.BlurEffect;
 import com.airbnb.lottie.model.content.Mask;
 import com.airbnb.lottie.model.content.ShapeData;
+import com.airbnb.lottie.parser.DropShadowEffect;
 import com.airbnb.lottie.utils.Logger;
 import com.airbnb.lottie.utils.Utils;
 import com.airbnb.lottie.value.LottieValueCallback;
@@ -606,6 +607,11 @@
     return blurMaskFilter;
   }
 
+  @Nullable
+  public DropShadowEffect getDropShadowEffect() {
+    return layerModel.getDropShadowEffect();
+  }
+
   @Override
   public void setContents(List<Content> contentsBefore, List<Content> contentsAfter) {
     // Do nothing
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java
index 18d2a95..c20ae75 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java
@@ -28,7 +28,7 @@
   private final List<BaseLayer> layers = new ArrayList<>();
   private final RectF rect = new RectF();
   private final RectF newClipRect = new RectF();
-  private Paint layerPaint = new Paint();
+  private final Paint layerPaint = new Paint();
 
   @Nullable private Boolean hasMatte;
   @Nullable private Boolean hasMasks;
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/Layer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/Layer.java
index f7f5531..e2fa79d 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/Layer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/Layer.java
@@ -10,6 +10,7 @@
 import com.airbnb.lottie.model.content.BlurEffect;
 import com.airbnb.lottie.model.content.ContentModel;
 import com.airbnb.lottie.model.content.Mask;
+import com.airbnb.lottie.parser.DropShadowEffect;
 import com.airbnb.lottie.value.Keyframe;
 
 import java.util.List;
@@ -59,6 +60,7 @@
   private final MatteType matteType;
   private final boolean hidden;
   @Nullable private final BlurEffect blurEffect;
+  @Nullable private final DropShadowEffect dropShadowEffect;
 
   public Layer(List<ContentModel> shapes, LottieComposition composition, String layerName, long layerId,
       LayerType layerType, long parentId, @Nullable String refId, List<Mask> masks,
@@ -66,7 +68,8 @@
       float timeStretch, float startFrame, int preCompWidth, int preCompHeight,
       @Nullable AnimatableTextFrame text, @Nullable AnimatableTextProperties textProperties,
       List<Keyframe<Float>> inOutKeyframes, MatteType matteType,
-      @Nullable AnimatableFloatValue timeRemapping, boolean hidden, @Nullable BlurEffect blurEffect) {
+      @Nullable AnimatableFloatValue timeRemapping, boolean hidden, @Nullable BlurEffect blurEffect,
+      @Nullable DropShadowEffect dropShadowEffect) {
     this.shapes = shapes;
     this.composition = composition;
     this.layerName = layerName;
@@ -90,6 +93,7 @@
     this.timeRemapping = timeRemapping;
     this.hidden = hidden;
     this.blurEffect = blurEffect;
+    this.dropShadowEffect = dropShadowEffect;
   }
 
   LottieComposition getComposition() {
@@ -188,6 +192,10 @@
     return blurEffect;
   }
 
+  @Nullable public DropShadowEffect getDropShadowEffect() {
+    return dropShadowEffect;
+  }
+
   public String toString(String prefix) {
     StringBuilder sb = new StringBuilder();
     sb.append(prefix).append(getName()).append("\n");
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/ShapeLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/ShapeLayer.java
index b8d83a7..4250d8e 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/ShapeLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/ShapeLayer.java
@@ -13,6 +13,7 @@
 import com.airbnb.lottie.model.KeyPath;
 import com.airbnb.lottie.model.content.BlurEffect;
 import com.airbnb.lottie.model.content.ShapeGroup;
+import com.airbnb.lottie.parser.DropShadowEffect;
 
 import java.util.Collections;
 import java.util.List;
@@ -48,6 +49,14 @@
     return compositionLayer.getBlurEffect();
   }
 
+  @Nullable @Override public DropShadowEffect getDropShadowEffect() {
+    DropShadowEffect layerDropShadow = super.getDropShadowEffect();
+    if (layerDropShadow != null) {
+      return layerDropShadow;
+    }
+    return compositionLayer.getDropShadowEffect();
+  }
+
   @Override
   protected void resolveChildKeyPath(KeyPath keyPath, int depth, List<KeyPath> accumulator,
       KeyPath currentPartialKeyPath) {
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/DropShadowEffect.java b/lottie/src/main/java/com/airbnb/lottie/parser/DropShadowEffect.java
new file mode 100644
index 0000000..4d15a07
--- /dev/null
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/DropShadowEffect.java
@@ -0,0 +1,41 @@
+package com.airbnb.lottie.parser;
+
+import com.airbnb.lottie.model.animatable.AnimatableColorValue;
+import com.airbnb.lottie.model.animatable.AnimatableFloatValue;
+
+public class DropShadowEffect {
+  private final AnimatableColorValue color;
+  private final AnimatableFloatValue opacity;
+  private final AnimatableFloatValue direction;
+  private final AnimatableFloatValue distance;
+  private final AnimatableFloatValue radius;
+
+  DropShadowEffect(AnimatableColorValue color, AnimatableFloatValue opacity, AnimatableFloatValue direction,
+      AnimatableFloatValue distance, AnimatableFloatValue radius) {
+    this.color = color;
+    this.opacity = opacity;
+    this.direction = direction;
+    this.distance = distance;
+    this.radius = radius;
+  }
+
+  public AnimatableColorValue getColor() {
+    return color;
+  }
+
+  public AnimatableFloatValue getOpacity() {
+    return opacity;
+  }
+
+  public AnimatableFloatValue getDirection() {
+    return direction;
+  }
+
+  public AnimatableFloatValue getDistance() {
+    return distance;
+  }
+
+  public AnimatableFloatValue getRadius() {
+    return radius;
+  }
+}
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/DropShadowEffectParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/DropShadowEffectParser.java
new file mode 100644
index 0000000..e4bb5d8
--- /dev/null
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/DropShadowEffectParser.java
@@ -0,0 +1,87 @@
+package com.airbnb.lottie.parser;
+
+import androidx.annotation.Nullable;
+
+import com.airbnb.lottie.LottieComposition;
+import com.airbnb.lottie.model.animatable.AnimatableColorValue;
+import com.airbnb.lottie.model.animatable.AnimatableFloatValue;
+import com.airbnb.lottie.parser.moshi.JsonReader;
+
+import java.io.IOException;
+
+public class DropShadowEffectParser {
+
+  private static final JsonReader.Options DROP_SHADOW_EFFECT_NAMES = JsonReader.Options.of(
+      "ef"
+  );
+  private static final JsonReader.Options INNER_EFFECT_NAMES = JsonReader.Options.of(
+      "nm",
+      "v"
+  );
+
+  private AnimatableColorValue color;
+  private AnimatableFloatValue opacity;
+  private AnimatableFloatValue direction;
+  private AnimatableFloatValue distance;
+  private AnimatableFloatValue radius;
+
+  @Nullable
+  DropShadowEffect parse(JsonReader reader, LottieComposition composition) throws IOException {
+    while (reader.hasNext()) {
+      switch (reader.selectName(DROP_SHADOW_EFFECT_NAMES)) {
+        case 0:
+          reader.beginArray();
+          while (reader.hasNext()) {
+            maybeParseInnerEffect(reader, composition);
+          }
+          reader.endArray();
+          break;
+        default:
+          reader.skipName();
+          reader.skipValue();
+      }
+    }
+    if (color != null && opacity != null && direction != null && distance != null && radius != null) {
+      return new DropShadowEffect(color, opacity, direction, distance, radius);
+    }
+    return null;
+  }
+
+  private void maybeParseInnerEffect(JsonReader reader, LottieComposition composition) throws IOException {
+    String currentEffectName = "";
+    reader.beginObject();
+    while (reader.hasNext()) {
+      switch (reader.selectName(INNER_EFFECT_NAMES)) {
+        case 0:
+          currentEffectName = reader.nextString();
+          break;
+        case 1:
+          switch (currentEffectName) {
+            case "Shadow Color":
+              color = AnimatableValueParser.parseColor(reader, composition);
+              break;
+            case "Opacity":
+              opacity = AnimatableValueParser.parseFloat(reader, composition, false);
+              break;
+            case "Direction":
+              direction = AnimatableValueParser.parseFloat(reader, composition, false);
+              break;
+            case "Distance":
+              distance = AnimatableValueParser.parseFloat(reader, composition);
+              break;
+            case "Softness":
+              radius = AnimatableValueParser.parseFloat(reader, composition);
+              break;
+            default:
+              reader.skipValue();
+              break;
+          }
+          break;
+        default:
+          reader.skipName();
+          reader.skipValue();
+      }
+    }
+    reader.endObject();
+  }
+}
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/LayerParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/LayerParser.java
index 5bd7544..6881a02 100644
--- a/lottie/src/main/java/com/airbnb/lottie/parser/LayerParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/LayerParser.java
@@ -59,7 +59,7 @@
         Layer.LayerType.PRE_COMP, -1, null, Collections.<Mask>emptyList(),
         new AnimatableTransform(), 0, 0, 0, 0, 0,
         bounds.width(), bounds.height(), null, null, Collections.<Keyframe<Float>>emptyList(),
-        Layer.MatteType.NONE, null, false, null);
+        Layer.MatteType.NONE, null, false, null, null);
   }
 
   private static final JsonReader.Options TEXT_NAMES = JsonReader.Options.of(
@@ -92,6 +92,7 @@
     String cl = null;
     boolean hidden = false;
     BlurEffect blurEffect = null;
+    DropShadowEffect dropShadowEffect = null;
 
     Layer.MatteType matteType = Layer.MatteType.NONE;
     AnimatableTransform transform = null;
@@ -207,6 +208,8 @@
                   int type = reader.nextInt();
                   if (type == 29) {
                     blurEffect = BlurEffectParser.parse(reader, composition);
+                  } else if (type == 25) {
+                    dropShadowEffect = new DropShadowEffectParser().parse(reader, composition);
                   }
                   break;
                 case 1:
@@ -284,6 +287,6 @@
     return new Layer(shapes, composition, layerName, layerId, layerType, parentId, refId,
         masks, transform, solidWidth, solidHeight, solidColor, timeStretch, startFrame,
         preCompWidth, preCompHeight, text, textProperties, inOutKeyframes, matteType,
-        timeRemapping, hidden, blurEffect);
+        timeRemapping, hidden, blurEffect, dropShadowEffect);
   }
 }
diff --git a/sample/src/androidTest/java/com/airbnb/lottie/samples/LottieTest.kt b/sample/src/androidTest/java/com/airbnb/lottie/samples/LottieTest.kt
index 9d1b1b3..92239d6 100644
--- a/sample/src/androidTest/java/com/airbnb/lottie/samples/LottieTest.kt
+++ b/sample/src/androidTest/java/com/airbnb/lottie/samples/LottieTest.kt
@@ -714,6 +714,27 @@
                 LottieInterpolatedIntegerValue(10, 100),
                 1f)
 
+        testDynamicProperty(
+            "Drop Shadow Color",
+            KeyPath("Shape Layer 1", "**"),
+            LottieProperty.DROP_SHADOW_COLOR,
+            LottieValueCallback(Color.RED),
+            assetName = "Tests/AnimatedShadow.json")
+
+        testDynamicProperty(
+            "Drop Shadow Distance",
+            KeyPath("Shape Layer 1", "**"),
+            LottieProperty.DROP_SHADOW_DISTANCE,
+            LottieValueCallback(30f),
+            assetName = "Tests/AnimatedShadow.json")
+
+        testDynamicProperty(
+            "Drop Shadow Distance",
+            KeyPath("Shape Layer 1", "**"),
+            LottieProperty.DROP_SHADOW_DIRECTION,
+            LottieValueCallback(30f),
+            assetName = "Tests/AnimatedShadow.json")
+
         withDrawable("Tests/DynamicGradient.json", "Gradient Colors", "Linear Gradient Fill") { drawable ->
             val value = object : LottieValueCallback<Array<Int>>() {
                 override fun getValue(frameInfo: LottieFrameInfo<Array<Int>>?): Array<Int> {
diff --git a/sample/src/main/assets/Tests/AnimatedShadow.json b/sample/src/main/assets/Tests/AnimatedShadow.json
new file mode 100644
index 0000000..ec86bb8
--- /dev/null
+++ b/sample/src/main/assets/Tests/AnimatedShadow.json
@@ -0,0 +1 @@
+{"v":"5.7.7","fr":29.9700012207031,"ip":0,"op":181.000007372281,"w":375,"h":375,"nm":"Square","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,187.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow2","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0,0,0,1]},{"t":151.000006150356,"s":[0,0.371857702732,1,1]}],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":0,"s":[127.5]},{"t":151.000006150356,"s":[127.5]}],"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":151.000006150356,"s":[360]}],"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[10]},{"t":151.000006150356,"s":[15]}],"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[20]},{"t":151.000006150356,"s":[50]}],"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[217.641,217.641],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-4.68,-1.68],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":184.000007494474,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/sample/src/main/assets/Tests/StaticShadow.json b/sample/src/main/assets/Tests/StaticShadow.json
new file mode 100644
index 0000000..e842acd
--- /dev/null
+++ b/sample/src/main/assets/Tests/StaticShadow.json
@@ -0,0 +1 @@
+{"v":"5.7.7","fr":29.9700012207031,"ip":0,"op":181.000007372281,"w":375,"h":375,"nm":"Square","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,187.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow2","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,1,0.609851837158,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":127.5,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":0,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":10,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":20,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[217.641,217.641],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-4.68,-1.68],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":184.000007494474,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file