Add COMPOSITION in KeyPath to target root composition layer. (#1559)

diff --git a/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/LottieTest.kt b/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/LottieTest.kt
index 123c20f..973b21e 100644
--- a/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/LottieTest.kt
+++ b/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/LottieTest.kt
@@ -728,6 +728,14 @@
             drawable.addValueCallback(KeyPath("Linear", "Rectangle", "Gradient Fill"), LottieProperty.OPACITY, value)
         }
 
+        withDrawable("Tests/MatteTimeStretchScan.json", "Mirror animation", "Mirror animation") {
+            drawable ->
+            drawable.addValueCallback(KeyPath.COMPOSITION, LottieProperty.TRANSFORM_ANCHOR_POINT,
+                    { PointF(drawable.bounds.width().toFloat(), 0f) })
+            drawable.addValueCallback(KeyPath.COMPOSITION, LottieProperty.TRANSFORM_SCALE,
+                    { ScaleXY(-1.0f, 1.0f) })
+        }
+
         withDrawable("Tests/Text.json", "Text", "Text Fill (Blue -> Green)") { drawable ->
             val value = object : LottieValueCallback<Int>() {
                 override fun getValue(frameInfo: LottieFrameInfo<Int>?) = Color.GREEN
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java b/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
index 70fa4af..1969ec6 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
@@ -972,7 +972,10 @@
       return;
     }
     boolean invalidate;
-    if (keyPath.getResolvedElement() != null) {
+    if (keyPath == KeyPath.COMPOSITION) {
+      compositionLayer.addValueCallback(property, callback);
+      invalidate = true;
+    } else if (keyPath.getResolvedElement() != null) {
       keyPath.getResolvedElement().addValueCallback(property, callback);
       invalidate = true;
     } else {
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/KeyPath.java b/lottie/src/main/java/com/airbnb/lottie/model/KeyPath.java
index 31a50cf..64fe09f 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/KeyPath.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/KeyPath.java
@@ -11,7 +11,8 @@
 /**
  * Defines which content to target.
  * The keypath can contain wildcards ('*') with match exactly 1 item.
- * or globstars ('**') which match 0 or more items.
+ * or globstars ('**') which match 0 or more items. or KeyPath.COMPOSITION
+ * to represent the root composition layer.
  *
  * For example, if your content were arranged like this:
  * Gabriel (Shape Layer)
@@ -35,12 +36,19 @@
  *        new KeyPath("*", "Body", Left Hand", "Fill");
  *     Match anything with the name Fill:
  *        new KeyPath("**", "Fill");
+ *     Target the the root composition layer:
+ *        KeyPath.COMPOSITION
  *
  *
  * NOTE: Content that are part of merge paths or repeaters cannot currently be resolved with
  * a {@link KeyPath}. This may be fixed in the future.
  */
 public class KeyPath {
+  /**
+   * A singleton KeyPath that targets on the root composition layer.
+   * This is useful if you want to apply transformer to the animation as a whole.
+   */
+  public final static KeyPath COMPOSITION = new KeyPath("COMPOSITION");
 
   private final List<String> keys;
   @Nullable private KeyPathElement resolvedElement;