Merge "Animated vector drawable support" into nyc-dev
diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java
new file mode 100644
index 0000000..200fe3b
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License") {}
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable;
+
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.internal.view.animation.NativeInterpolatorFactoryHelper_Delegate;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.drawable.AnimatedVectorDrawable.VectorDrawableAnimatorRT;
+import android.graphics.drawable.VectorDrawable_Delegate.VFullPath_Delegate;
+import android.graphics.drawable.VectorDrawable_Delegate.VGroup_Delegate;
+import android.graphics.drawable.VectorDrawable_Delegate.VNativeObject;
+import android.graphics.drawable.VectorDrawable_Delegate.VPathRenderer_Delegate;
+
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link
+ * AnimatedVectorDrawable}
+ * <p>
+ * Through the layoutlib_create tool, the original  methods of AnimatedVectorDrawable have been
+ * replaced by calls to methods of the same name in this delegate class.
+ */
+@SuppressWarnings("unused")
+public class AnimatedVectorDrawable_Delegate {
+    private static DelegateManager<AnimatorSetHolder> sAnimatorSets = new
+            DelegateManager<>(AnimatorSetHolder.class);
+    private static DelegateManager<PropertySetter> sHolders = new
+            DelegateManager<>(PropertySetter.class);
+
+
+    @LayoutlibDelegate
+    /*package*/ static long nCreateAnimatorSet() {
+        return sAnimatorSets.addNewDelegate(new AnimatorSetHolder());
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void nAddAnimator(long setPtr, long propertyValuesHolder,
+            long nativeInterpolator, long startDelay, long duration, int repeatCount) {
+        PropertySetter holder = sHolders.getDelegate(propertyValuesHolder);
+        if (holder == null || holder.getValues() == null) {
+            return;
+        }
+
+        ObjectAnimator animator = new ObjectAnimator();
+        animator.setValues(holder.getValues());
+        animator.setInterpolator(
+                NativeInterpolatorFactoryHelper_Delegate.getDelegate(nativeInterpolator));
+        animator.setStartDelay(startDelay);
+        animator.setDuration(duration);
+        animator.setRepeatCount(repeatCount);
+        animator.setTarget(holder);
+        animator.setPropertyName(holder.getValues().getPropertyName());
+
+        AnimatorSetHolder set = sAnimatorSets.getDelegate(setPtr);
+        assert set != null;
+        set.addAnimator(animator);
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long nCreateGroupPropertyHolder(long nativePtr, int propertyId,
+            float startValue, float endValue) {
+        VGroup_Delegate group = VNativeObject.getDelegate(nativePtr);
+        Consumer<Float> setter = group.getPropertySetter(propertyId);
+
+        return sHolders.addNewDelegate(FloatPropertySetter.of(setter, startValue,
+                endValue));
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long nCreatePathDataPropertyHolder(long nativePtr, long startValuePtr,
+            long endValuePtr) {
+        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, "AnimatedVectorDrawable path " +
+                "animations are not supported.", null, null);
+        return 0;
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long nCreatePathColorPropertyHolder(long nativePtr, int propertyId,
+            int startValue, int endValue) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(nativePtr);
+        Consumer<Integer> setter = path.getIntPropertySetter(propertyId);
+
+        return sHolders.addNewDelegate(IntPropertySetter.of(setter, startValue,
+                endValue));
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long nCreatePathPropertyHolder(long nativePtr, int propertyId,
+            float startValue, float endValue) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(nativePtr);
+        Consumer<Float> setter = path.getFloatPropertySetter(propertyId);
+
+        return sHolders.addNewDelegate(FloatPropertySetter.of(setter, startValue,
+                endValue));
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue,
+            float endValue) {
+        VPathRenderer_Delegate renderer = VNativeObject.getDelegate(nativePtr);
+
+        return sHolders.addNewDelegate(FloatPropertySetter.of(renderer::setRootAlpha,
+                startValue,
+                endValue));
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void nSetPropertyHolderData(long nativePtr, float[] data, int length) {
+        PropertySetter setter = sHolders.getDelegate(nativePtr);
+        assert setter != null;
+
+        setter.setValues(data);
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void nStart(long animatorSetPtr, VectorDrawableAnimatorRT set, int id) {
+        AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
+        assert animatorSet != null;
+
+        animatorSet.start();
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void nReverse(long animatorSetPtr, VectorDrawableAnimatorRT set, int id) {
+        AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
+        assert animatorSet != null;
+
+        animatorSet.reverse();
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void nEnd(long animatorSetPtr) {
+        AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
+        assert animatorSet != null;
+
+        animatorSet.end();
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void nReset(long animatorSetPtr) {
+        AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
+        assert animatorSet != null;
+
+        animatorSet.end();
+        animatorSet.start();
+    }
+
+    private static class AnimatorSetHolder {
+        private ArrayList<Animator> mAnimators = new ArrayList<>();
+        private AnimatorSet mAnimatorSet = null;
+
+        private void addAnimator(@NonNull Animator animator) {
+            mAnimators.add(animator);
+        }
+
+        private void ensureAnimatorSet() {
+            if (mAnimatorSet == null) {
+                mAnimatorSet = new AnimatorSet();
+                mAnimatorSet.playTogether(mAnimators);
+            }
+        }
+
+        private void start() {
+            ensureAnimatorSet();
+
+            mAnimatorSet.start();
+        }
+
+        private void end() {
+            mAnimatorSet.end();
+        }
+
+        private void reset() {
+            end();
+            start();
+        }
+
+        private void reverse() {
+            mAnimatorSet.reverse();
+        }
+    }
+
+    /**
+     * Class that allows setting a value and holds the range of values for the given property.
+     *
+     * @param <T> the type of the property
+     */
+    private static class PropertySetter<T> {
+        final Consumer<T> mValueSetter;
+        private PropertyValuesHolder mValues;
+
+        private PropertySetter(@NonNull Consumer<T> valueSetter) {
+            mValueSetter = valueSetter;
+        }
+
+        /**
+         * Method to set an {@link Integer} value for this property. The default implementation of
+         * this method doesn't do anything. This method is accessed via reflection by the
+         * PropertyValuesHolder.
+         */
+        public void setIntValue(Integer value) {
+        }
+
+        /**
+         * Method to set an {@link Integer} value for this property. The default implementation of
+         * this method doesn't do anything. This method is accessed via reflection by the
+         * PropertyValuesHolder.
+         */
+        public void setFloatValue(Float value) {
+        }
+
+        void setValues(float... values) {
+            mValues = PropertyValuesHolder.ofFloat("floatValue", values);
+        }
+
+        @Nullable
+        PropertyValuesHolder getValues() {
+            return mValues;
+        }
+
+        void setValues(int... values) {
+            mValues = PropertyValuesHolder.ofInt("intValue", values);
+        }
+    }
+
+    private static class IntPropertySetter extends PropertySetter<Integer> {
+        private IntPropertySetter(Consumer<Integer> valueSetter) {
+            super(valueSetter);
+        }
+
+        private static PropertySetter of(Consumer<Integer> valueSetter, int... values) {
+            PropertySetter setter = new IntPropertySetter(valueSetter);
+            setter.setValues(values);
+
+            return setter;
+        }
+
+        public void setIntValue(Integer value) {
+            mValueSetter.accept(value);
+        }
+    }
+
+    private static class FloatPropertySetter extends PropertySetter<Float> {
+        private FloatPropertySetter(Consumer<Float> valueSetter) {
+            super(valueSetter);
+        }
+
+        private static PropertySetter of(Consumer<Float> valueSetter, float... values) {
+            PropertySetter setter = new FloatPropertySetter(valueSetter);
+            setter.setValues(values);
+
+            return setter;
+        }
+
+        public void setFloatValue(Float value) {
+            mValueSetter.accept(value);
+        }
+
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java
new file mode 100644
index 0000000..3d78931
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.graphics.drawable.AnimatedVectorDrawable.VectorDrawableAnimatorRT;
+
+public class AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate {
+    @LayoutlibDelegate
+    /*package*/ static boolean useLastSeenTarget(VectorDrawableAnimatorRT thisDrawableAnimator) {
+        return true;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
index 2e3e7e8..6e3aa40 100644
--- a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
@@ -19,6 +19,7 @@
 import com.android.layoutlib.bridge.impl.DelegateManager;
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 
+import android.annotation.NonNull;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
@@ -44,6 +45,7 @@
 import java.nio.ByteOrder;
 import java.nio.FloatBuffer;
 import java.util.ArrayList;
+import java.util.function.Consumer;
 
 import static android.graphics.Canvas.CLIP_SAVE_FLAG;
 import static android.graphics.Canvas.MATRIX_SAVE_FLAG;
@@ -68,14 +70,6 @@
     private static final DelegateManager<VNativeObject> sPathManager =
             new DelegateManager<>(VNativeObject.class);
 
-    private static <T> T getDelegate(long nativePtr) {
-        //noinspection unchecked
-        T object = (T) sPathManager.getDelegate(nativePtr);
-        assert object != null;
-
-        return object;
-    }
-
     /**
      * Obtains styled attributes from the theme, if available, or unstyled resources if the theme is
      * null.
@@ -97,21 +91,21 @@
 
     @LayoutlibDelegate
     static long nCreateRenderer(long rootGroupPtr) {
-        VGroup_Delegate rootGroup = getDelegate(rootGroupPtr);
+        VGroup_Delegate rootGroup = VNativeObject.getDelegate(rootGroupPtr);
         return sPathManager.addNewDelegate(new VPathRenderer_Delegate(rootGroup));
     }
 
     @LayoutlibDelegate
     static void nSetRendererViewportSize(long rendererPtr, float viewportWidth,
             float viewportHeight) {
-        VPathRenderer_Delegate nativePathRenderer = getDelegate(rendererPtr);
+        VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr);
         nativePathRenderer.mViewportWidth = viewportWidth;
         nativePathRenderer.mViewportHeight = viewportHeight;
     }
 
     @LayoutlibDelegate
     static boolean nSetRootAlpha(long rendererPtr, float alpha) {
-        VPathRenderer_Delegate nativePathRenderer = getDelegate(rendererPtr);
+        VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr);
         nativePathRenderer.setRootAlpha(alpha);
 
         return true;
@@ -119,7 +113,7 @@
 
     @LayoutlibDelegate
     static float nGetRootAlpha(long rendererPtr) {
-        VPathRenderer_Delegate nativePathRenderer = getDelegate(rendererPtr);
+        VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr);
 
         return nativePathRenderer.getRootAlpha();
     }
@@ -132,8 +126,7 @@
     @LayoutlibDelegate
     static void nDraw(long rendererPtr, long canvasWrapperPtr,
             long colorFilterPtr, Rect bounds, boolean needsMirroring, boolean canReuseCache) {
-        VPathRenderer_Delegate nativePathRenderer =
-                getDelegate(rendererPtr);
+        VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr);
 
         Canvas_Delegate.native_save(canvasWrapperPtr, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
         Canvas_Delegate.native_translate(canvasWrapperPtr, bounds.left, bounds.top);
@@ -159,7 +152,7 @@
 
     @LayoutlibDelegate
     static long nCreateFullPath(long nativeFullPathPtr) {
-        VFullPath_Delegate original = getDelegate(nativeFullPathPtr);
+        VFullPath_Delegate original = VNativeObject.getDelegate(nativeFullPathPtr);
 
         return sPathManager.addNewDelegate(new VFullPath_Delegate(original));
     }
@@ -167,7 +160,7 @@
     @LayoutlibDelegate
     static boolean nGetFullPathProperties(long pathPtr, byte[] propertiesData,
             int length) {
-        VFullPath_Delegate path = getDelegate(pathPtr);
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
 
         ByteBuffer properties = ByteBuffer.wrap(propertiesData);
         properties.order(ByteOrder.nativeOrder());
@@ -194,7 +187,7 @@
             int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart,
             float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap,
             int strokeLineJoin) {
-        VFullPath_Delegate path = getDelegate(pathPtr);
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
 
         path.setStrokeWidth(strokeWidth);
         path.setStrokeColor(strokeColor);
@@ -230,7 +223,7 @@
 
     @LayoutlibDelegate
     static long nCreateClipPath(long clipPathPtr) {
-        VClipPath_Delegate original = getDelegate(clipPathPtr);
+        VClipPath_Delegate original = VNativeObject.getDelegate(clipPathPtr);
         return sPathManager.addNewDelegate(new VClipPath_Delegate(original));
     }
 
@@ -241,21 +234,21 @@
 
     @LayoutlibDelegate
     static long nCreateGroup(long groupPtr) {
-        VGroup_Delegate original = getDelegate(groupPtr);
+        VGroup_Delegate original = VNativeObject.getDelegate(groupPtr);
         return sPathManager.addNewDelegate(
                 new VGroup_Delegate(original, new ArrayMap<String, Object>()));
     }
 
     @LayoutlibDelegate
     static void nSetName(long nodePtr, String name) {
-        VNativeObject group = getDelegate(nodePtr);
+        VNativeObject group = VNativeObject.getDelegate(nodePtr);
         group.setName(name);
     }
 
     @LayoutlibDelegate
     static boolean nGetGroupProperties(long groupPtr, float[] propertiesData,
             int length) {
-        VGroup_Delegate group = getDelegate(groupPtr);
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
 
         FloatBuffer properties = FloatBuffer.wrap(propertiesData);
 
@@ -272,7 +265,7 @@
     @LayoutlibDelegate
     static void nUpdateGroupProperties(long groupPtr, float rotate, float pivotX,
             float pivotY, float scaleX, float scaleY, float translateX, float translateY) {
-        VGroup_Delegate group = getDelegate(groupPtr);
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
 
         group.setRotation(rotate);
         group.setPivotX(pivotX);
@@ -285,13 +278,13 @@
 
     @LayoutlibDelegate
     static void nAddChild(long groupPtr, long nodePtr) {
-        VGroup_Delegate group = getDelegate(groupPtr);
-        group.mChildren.add(getDelegate(nodePtr));
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+        group.mChildren.add(VNativeObject.getDelegate(nodePtr));
     }
 
     @LayoutlibDelegate
     static void nSetPathString(long pathPtr, String pathString, int length) {
-        VPath_Delegate path = getDelegate(pathPtr);
+        VPath_Delegate path = VNativeObject.getDelegate(pathPtr);
         path.setPathData(PathParser_Delegate.createNodesFromPathData(pathString));
     }
 
@@ -304,187 +297,187 @@
     // Setters and getters during animation.
     @LayoutlibDelegate
     static float nGetRotation(long groupPtr) {
-        VGroup_Delegate group = getDelegate(groupPtr);
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
         return group.getRotation();
     }
 
     @LayoutlibDelegate
     static void nSetRotation(long groupPtr, float rotation) {
-        VGroup_Delegate group = getDelegate(groupPtr);
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
         group.setRotation(rotation);
     }
 
     @LayoutlibDelegate
     static float nGetPivotX(long groupPtr) {
-        VGroup_Delegate group = getDelegate(groupPtr);
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
         return group.getPivotX();
     }
 
     @LayoutlibDelegate
     static void nSetPivotX(long groupPtr, float pivotX) {
-        VGroup_Delegate group = getDelegate(groupPtr);
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
         group.setPivotX(pivotX);
     }
 
     @LayoutlibDelegate
     static float nGetPivotY(long groupPtr) {
-        VGroup_Delegate group = getDelegate(groupPtr);
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
         return group.getPivotY();
     }
 
     @LayoutlibDelegate
     static void nSetPivotY(long groupPtr, float pivotY) {
-        VGroup_Delegate group = getDelegate(groupPtr);
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
         group.setPivotY(pivotY);
     }
 
     @LayoutlibDelegate
     static float nGetScaleX(long groupPtr) {
-        VGroup_Delegate group = getDelegate(groupPtr);
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
         return group.getScaleX();
     }
 
     @LayoutlibDelegate
     static void nSetScaleX(long groupPtr, float scaleX) {
-        VGroup_Delegate group = getDelegate(groupPtr);
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
         group.setScaleX(scaleX);
     }
 
     @LayoutlibDelegate
     static float nGetScaleY(long groupPtr) {
-        VGroup_Delegate group = getDelegate(groupPtr);
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
         return group.getScaleY();
     }
 
     @LayoutlibDelegate
     static void nSetScaleY(long groupPtr, float scaleY) {
-        VGroup_Delegate group = getDelegate(groupPtr);
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
         group.setScaleY(scaleY);
     }
 
     @LayoutlibDelegate
     static float nGetTranslateX(long groupPtr) {
-        VGroup_Delegate group = getDelegate(groupPtr);
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
         return group.getTranslateX();
     }
 
     @LayoutlibDelegate
     static void nSetTranslateX(long groupPtr, float translateX) {
-        VGroup_Delegate group = getDelegate(groupPtr);
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
         group.setTranslateX(translateX);
     }
 
     @LayoutlibDelegate
     static float nGetTranslateY(long groupPtr) {
-        VGroup_Delegate group = getDelegate(groupPtr);
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
         return group.getTranslateY();
     }
 
     @LayoutlibDelegate
     static void nSetTranslateY(long groupPtr, float translateY) {
-        VGroup_Delegate group = getDelegate(groupPtr);
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
         group.setTranslateY(translateY);
     }
 
     @LayoutlibDelegate
     static void nSetPathData(long pathPtr, long pathDataPtr) {
-        VPath_Delegate path = getDelegate(pathPtr);
+        VPath_Delegate path = VNativeObject.getDelegate(pathPtr);
         path.setPathData(PathParser_Delegate.getDelegate(pathDataPtr).getPathDataNodes());
     }
 
     @LayoutlibDelegate
     static float nGetStrokeWidth(long pathPtr) {
-        VFullPath_Delegate path = getDelegate(pathPtr);
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
         return path.getStrokeWidth();
     }
 
     @LayoutlibDelegate
     static void nSetStrokeWidth(long pathPtr, float width) {
-        VFullPath_Delegate path = getDelegate(pathPtr);
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
         path.setStrokeWidth(width);
     }
 
     @LayoutlibDelegate
     static int nGetStrokeColor(long pathPtr) {
-        VFullPath_Delegate path = getDelegate(pathPtr);
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
         return path.getStrokeColor();
     }
 
     @LayoutlibDelegate
     static void nSetStrokeColor(long pathPtr, int strokeColor) {
-        VFullPath_Delegate path = getDelegate(pathPtr);
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
         path.setStrokeColor(strokeColor);
     }
 
     @LayoutlibDelegate
     static float nGetStrokeAlpha(long pathPtr) {
-        VFullPath_Delegate path = getDelegate(pathPtr);
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
         return path.getStrokeAlpha();
     }
 
     @LayoutlibDelegate
     static void nSetStrokeAlpha(long pathPtr, float alpha) {
-        VFullPath_Delegate path = getDelegate(pathPtr);
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
         path.setStrokeAlpha(alpha);
     }
 
     @LayoutlibDelegate
     static int nGetFillColor(long pathPtr) {
-        VFullPath_Delegate path = getDelegate(pathPtr);
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
         return path.getFillColor();
     }
 
     @LayoutlibDelegate
     static void nSetFillColor(long pathPtr, int fillColor) {
-        VFullPath_Delegate path = getDelegate(pathPtr);
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
         path.setFillColor(fillColor);
     }
 
     @LayoutlibDelegate
     static float nGetFillAlpha(long pathPtr) {
-        VFullPath_Delegate path = getDelegate(pathPtr);
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
         return path.getFillAlpha();
     }
 
     @LayoutlibDelegate
     static void nSetFillAlpha(long pathPtr, float fillAlpha) {
-        VFullPath_Delegate path = getDelegate(pathPtr);
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
         path.setFillAlpha(fillAlpha);
     }
 
     @LayoutlibDelegate
     static float nGetTrimPathStart(long pathPtr) {
-        VFullPath_Delegate path = getDelegate(pathPtr);
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
         return path.getTrimPathStart();
     }
 
     @LayoutlibDelegate
     static void nSetTrimPathStart(long pathPtr, float trimPathStart) {
-        VFullPath_Delegate path = getDelegate(pathPtr);
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
         path.setTrimPathStart(trimPathStart);
     }
 
     @LayoutlibDelegate
     static float nGetTrimPathEnd(long pathPtr) {
-        VFullPath_Delegate path = getDelegate(pathPtr);
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
         return path.getTrimPathEnd();
     }
 
     @LayoutlibDelegate
     static void nSetTrimPathEnd(long pathPtr, float trimPathEnd) {
-        VFullPath_Delegate path = getDelegate(pathPtr);
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
         path.setTrimPathEnd(trimPathEnd);
     }
 
     @LayoutlibDelegate
     static float nGetTrimPathOffset(long pathPtr) {
-        VFullPath_Delegate path = getDelegate(pathPtr);
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
         return path.getTrimPathOffset();
     }
 
     @LayoutlibDelegate
     static void nSetTrimPathOffset(long pathPtr, float trimPathOffset) {
-        VFullPath_Delegate path = getDelegate(pathPtr);
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
         path.setTrimPathOffset(trimPathOffset);
     }
 
@@ -496,7 +489,16 @@
      *     not need it
      * </ol>
      */
-    private interface VNativeObject {
+    interface VNativeObject {
+        @NonNull
+        static <T> T getDelegate(long nativePtr) {
+            //noinspection unchecked
+            T vNativeObject = (T) sPathManager.getDelegate(nativePtr);
+
+            assert vNativeObject != null;
+            return vNativeObject;
+        }
+
         void setName(String name);
     }
 
@@ -515,7 +517,7 @@
         }
     }
 
-    private static class VFullPath_Delegate extends VPath_Delegate {
+    static class VFullPath_Delegate extends VPath_Delegate {
         // These constants need to be kept in sync with their values in VectorDrawable.VFullPath
         private static final int STROKE_WIDTH_INDEX = 0;
         private static final int STROKE_COLOR_INDEX = 1;
@@ -537,6 +539,38 @@
         private static final int LINEJOIN_ROUND = 1;
         private static final int LINEJOIN_BEVEL = 2;
 
+        @NonNull
+        public Consumer<Float> getFloatPropertySetter(int propertyIdx) {
+            switch (propertyIdx) {
+                case STROKE_ALPHA_INDEX:
+                    return this::setStrokeAlpha;
+                case FILL_ALPHA_INDEX:
+                    return this::setFillAlpha;
+                case TRIM_PATH_START_INDEX:
+                    return this::setTrimPathStart;
+                case TRIM_PATH_END_INDEX:
+                    return this::setTrimPathEnd;
+                case TRIM_PATH_OFFSET_INDEX:
+                    return this::setTrimPathOffset;
+            }
+
+            throw new IllegalArgumentException("Invalid VFullPath_Delegate property index "
+                    + propertyIdx);
+        }
+
+        @NonNull
+        public Consumer<Integer> getIntPropertySetter(int propertyIdx) {
+            switch (propertyIdx) {
+                case STROKE_COLOR_INDEX:
+                    return this::setStrokeColor;
+                case FILL_COLOR_INDEX:
+                    return this::setFillColor;
+            }
+
+            throw new IllegalArgumentException("Invalid VFullPath_Delegate property index "
+                    + propertyIdx);
+        }
+
         /////////////////////////////////////////////////////
         // Variables below need to be copied (deep copy if applicable) for mutation.
 
@@ -723,7 +757,7 @@
         }
     }
 
-    private static class VGroup_Delegate implements VNativeObject {
+    static class VGroup_Delegate implements VNativeObject {
         // This constants need to be kept in sync with their definitions in VectorDrawable.Group
         private static final int ROTATE_INDEX = 0;
         private static final int PIVOT_X_INDEX = 1;
@@ -733,6 +767,28 @@
         private static final int TRANSLATE_X_INDEX = 5;
         private static final int TRANSLATE_Y_INDEX = 6;
 
+        public Consumer<Float> getPropertySetter(int propertyIdx) {
+            switch (propertyIdx) {
+                case ROTATE_INDEX:
+                    return this::setRotation;
+                case PIVOT_X_INDEX:
+                    return this::setPivotX;
+                case PIVOT_Y_INDEX:
+                    return this::setPivotY;
+                case SCALE_X_INDEX:
+                    return this::setScaleX;
+                case SCALE_Y_INDEX:
+                    return this::setScaleY;
+                case TRANSLATE_X_INDEX:
+                    return this::setTranslateX;
+                case TRANSLATE_Y_INDEX:
+                    return this::setTranslateY;
+            }
+
+            throw new IllegalArgumentException("Invalid VGroup_Delegate property index "
+                    + propertyIdx);
+        }
+
         /////////////////////////////////////////////////////
         // Variables below need to be copied (deep copy if applicable) for mutation.
         final ArrayList<Object> mChildren = new ArrayList<>();
@@ -931,7 +987,7 @@
         }
     }
 
-    private static class VPathRenderer_Delegate implements VNativeObject {
+    static class VPathRenderer_Delegate implements VNativeObject {
         /* Right now the internal data structure is organized as a tree.
          * Each node can be a group node, or a path.
          * A group node can have groups or paths as children, but a path node has
@@ -967,7 +1023,7 @@
             return mRootAlpha;
         }
 
-        private void setRootAlpha(float alpha) {
+        void setRootAlpha(float alpha) {
             mRootAlpha = alpha;
         }
 
diff --git a/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java
new file mode 100644
index 0000000..0f39e80
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view.animation;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.util.MathUtils;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.AnticipateInterpolator;
+import android.view.animation.AnticipateOvershootInterpolator;
+import android.view.animation.BaseInterpolator;
+import android.view.animation.BounceInterpolator;
+import android.view.animation.CycleInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
+import android.view.animation.OvershootInterpolator;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link
+ * NativeInterpolatorFactoryHelper}
+ * <p>
+ * Through the layoutlib_create tool, the original  methods of NativeInterpolatorFactoryHelper have
+ * been replaced by calls to methods of the same name in this delegate class.
+ */
+@SuppressWarnings("unused")
+public class NativeInterpolatorFactoryHelper_Delegate {
+    private static final DelegateManager<Interpolator> sManager = new DelegateManager<>
+            (Interpolator.class);
+
+    public static Interpolator getDelegate(long nativePtr) {
+        return sManager.getDelegate(nativePtr);
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createAccelerateDecelerateInterpolator() {
+        return sManager.addNewDelegate(new AccelerateDecelerateInterpolator());
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createAccelerateInterpolator(float factor) {
+        return sManager.addNewDelegate(new AccelerateInterpolator(factor));
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createAnticipateInterpolator(float tension) {
+        return sManager.addNewDelegate(new AnticipateInterpolator(tension));
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createAnticipateOvershootInterpolator(float tension) {
+        return sManager.addNewDelegate(new AnticipateOvershootInterpolator(tension));
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createBounceInterpolator() {
+        return sManager.addNewDelegate(new BounceInterpolator());
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createCycleInterpolator(float cycles) {
+        return sManager.addNewDelegate(new CycleInterpolator(cycles));
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createDecelerateInterpolator(float factor) {
+        return sManager.addNewDelegate(new DecelerateInterpolator(factor));
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createLinearInterpolator() {
+        return sManager.addNewDelegate(new LinearInterpolator());
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createOvershootInterpolator(float tension) {
+        return sManager.addNewDelegate(new OvershootInterpolator(tension));
+    }
+
+    private static class LutInterpolator extends BaseInterpolator {
+        private final float[] mValues;
+        private final int mSize;
+
+        private LutInterpolator(float[] values) {
+            mValues = values;
+            mSize = mValues.length;
+        }
+
+        @Override
+        public float getInterpolation(float input) {
+            float lutpos = input * mSize;
+            if (lutpos >= (mSize - 1)) {
+                return mValues[mSize - 1];
+            }
+
+            int ipart = (int) lutpos;
+            float weight = lutpos - ipart;
+
+            int i1 = ipart;
+            int i2 = Math.min(i1 + 1, mSize - 1);
+
+            assert i1 >= 0 && i2 >= 0 : "Negatives in the interpolation";
+
+            return MathUtils.lerp(mValues[i1], mValues[i2], weight);
+        }
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createLutInterpolator(float[] values) {
+        return sManager.addNewDelegate(new LutInterpolator(values));
+    }
+}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 8c3bd2f..351be83 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -164,6 +164,7 @@
         "android.content.res.TypedArray#obtain",
         "android.graphics.BitmapFactory#finishDecode",
         "android.graphics.BitmapFactory#setDensityFromOptions",
+        "android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT#useLastSeenTarget",
         "android.graphics.drawable.GradientDrawable#buildRing",
         "android.graphics.Typeface#getSystemFontConfigLocation",
         "android.graphics.Typeface#makeFamilyFromParsed",
@@ -269,6 +270,7 @@
         "android.graphics.SweepGradient",
         "android.graphics.Typeface",
         "android.graphics.Xfermode",
+        "android.graphics.drawable.AnimatedVectorDrawable",
         "android.graphics.drawable.VectorDrawable",
         "android.os.SystemClock",
         "android.os.SystemProperties",
@@ -276,6 +278,7 @@
         "android.text.StaticLayout",
         "android.util.PathParser",
         "android.view.Display",
+        "com.android.internal.view.animation.NativeInterpolatorFactoryHelper",
         "libcore.icu.ICU",
     };