/*
 * Copyright (C) 2010 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.animation;

import android.annotation.AnimatorRes;
import android.annotation.AnyRes;
import android.annotation.NonNull;
import android.content.Context;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ConfigurationBoundResourceCache;
import android.content.res.ConstantState;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.util.PathParser;
import android.util.StateSet;
import android.util.TypedValue;
import android.util.Xml;
import android.view.InflateException;
import android.view.animation.AnimationUtils;
import android.view.animation.BaseInterpolator;
import android.view.animation.Interpolator;

import com.android.internal.R;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.ArrayList;

/**
 * This class is used to instantiate animator XML files into Animator objects.
 * <p>
 * For performance reasons, inflation relies heavily on pre-processing of
 * XML files that is done at build time. Therefore, it is not currently possible
 * to use this inflater with an XmlPullParser over a plain XML file at runtime;
 * it only works with an XmlPullParser returned from a compiled resource (R.
 * <em>something</em> file.)
 */
public class AnimatorInflater {
    private static final String TAG = "AnimatorInflater";
    /**
     * These flags are used when parsing AnimatorSet objects
     */
    private static final int TOGETHER = 0;
    private static final int SEQUENTIALLY = 1;

    /**
     * Enum values used in XML attributes to indicate the value for mValueType
     */
    private static final int VALUE_TYPE_FLOAT       = 0;
    private static final int VALUE_TYPE_INT         = 1;
    private static final int VALUE_TYPE_PATH        = 2;
    private static final int VALUE_TYPE_COLOR       = 3;
    private static final int VALUE_TYPE_UNDEFINED   = 4;

    private static final boolean DBG_ANIMATOR_INFLATER = false;

    // used to calculate changing configs for resource references
    private static final TypedValue sTmpTypedValue = new TypedValue();

    /**
     * Loads an {@link Animator} object from a resource
     *
     * @param context Application context used to access resources
     * @param id The resource id of the animation to load
     * @return The animator object reference by the specified id
     * @throws android.content.res.Resources.NotFoundException when the animation cannot be loaded
     */
    public static Animator loadAnimator(Context context, @AnimatorRes int id)
            throws NotFoundException {
        return loadAnimator(context.getResources(), context.getTheme(), id);
    }

    /**
     * Loads an {@link Animator} object from a resource
     *
     * @param resources The resources
     * @param theme The theme
     * @param id The resource id of the animation to load
     * @return The animator object reference by the specified id
     * @throws android.content.res.Resources.NotFoundException when the animation cannot be loaded
     * @hide
     */
    public static Animator loadAnimator(Resources resources, Theme theme, int id)
            throws NotFoundException {
        return loadAnimator(resources, theme, id, 1);
    }

    /** @hide */
    public static Animator loadAnimator(Resources resources, Theme theme, int id,
            float pathErrorScale) throws NotFoundException {
        final ConfigurationBoundResourceCache<Animator> animatorCache = resources
                .getAnimatorCache();
        Animator animator = animatorCache.getInstance(id, resources, theme);
        if (animator != null) {
            if (DBG_ANIMATOR_INFLATER) {
                Log.d(TAG, "loaded animator from cache, " + resources.getResourceName(id));
            }
            return animator;
        } else if (DBG_ANIMATOR_INFLATER) {
            Log.d(TAG, "cache miss for animator " + resources.getResourceName(id));
        }
        XmlResourceParser parser = null;
        try {
            parser = resources.getAnimation(id);
            animator = createAnimatorFromXml(resources, theme, parser, pathErrorScale);
            if (animator != null) {
                animator.appendChangingConfigurations(getChangingConfigs(resources, id));
                final ConstantState<Animator> constantState = animator.createConstantState();
                if (constantState != null) {
                    if (DBG_ANIMATOR_INFLATER) {
                        Log.d(TAG, "caching animator for res " + resources.getResourceName(id));
                    }
                    animatorCache.put(id, theme, constantState);
                    // create a new animator so that cached version is never used by the user
                    animator = constantState.newInstance(resources, theme);
                }
            }
            return animator;
        } catch (XmlPullParserException ex) {
            Resources.NotFoundException rnf =
                    new Resources.NotFoundException("Can't load animation resource ID #0x" +
                            Integer.toHexString(id));
            rnf.initCause(ex);
            throw rnf;
        } catch (IOException ex) {
            Resources.NotFoundException rnf =
                    new Resources.NotFoundException("Can't load animation resource ID #0x" +
                            Integer.toHexString(id));
            rnf.initCause(ex);
            throw rnf;
        } finally {
            if (parser != null) parser.close();
        }
    }

    public static StateListAnimator loadStateListAnimator(Context context, int id)
            throws NotFoundException {
        final Resources resources = context.getResources();
        final ConfigurationBoundResourceCache<StateListAnimator> cache = resources
                .getStateListAnimatorCache();
        final Theme theme = context.getTheme();
        StateListAnimator animator = cache.getInstance(id, resources, theme);
        if (animator != null) {
            return animator;
        }
        XmlResourceParser parser = null;
        try {
            parser = resources.getAnimation(id);
            animator = createStateListAnimatorFromXml(context, parser, Xml.asAttributeSet(parser));
            if (animator != null) {
                animator.appendChangingConfigurations(getChangingConfigs(resources, id));
                final ConstantState<StateListAnimator> constantState = animator
                        .createConstantState();
                if (constantState != null) {
                    cache.put(id, theme, constantState);
                    // return a clone so that the animator in constant state is never used.
                    animator = constantState.newInstance(resources, theme);
                }
            }
            return animator;
        } catch (XmlPullParserException ex) {
            Resources.NotFoundException rnf =
                    new Resources.NotFoundException(
                            "Can't load state list animator resource ID #0x" +
                                    Integer.toHexString(id)
                    );
            rnf.initCause(ex);
            throw rnf;
        } catch (IOException ex) {
            Resources.NotFoundException rnf =
                    new Resources.NotFoundException(
                            "Can't load state list animator resource ID #0x" +
                                    Integer.toHexString(id)
                    );
            rnf.initCause(ex);
            throw rnf;
        } finally {
            if (parser != null) {
                parser.close();
            }
        }
    }

    private static StateListAnimator createStateListAnimatorFromXml(Context context,
            XmlPullParser parser, AttributeSet attributeSet)
            throws IOException, XmlPullParserException {
        int type;
        StateListAnimator stateListAnimator = new StateListAnimator();

        while (true) {
            type = parser.next();
            switch (type) {
                case XmlPullParser.END_DOCUMENT:
                case XmlPullParser.END_TAG:
                    return stateListAnimator;

                case XmlPullParser.START_TAG:
                    // parse item
                    Animator animator = null;
                    if ("item".equals(parser.getName())) {
                        int attributeCount = parser.getAttributeCount();
                        int[] states = new int[attributeCount];
                        int stateIndex = 0;
                        for (int i = 0; i < attributeCount; i++) {
                            int attrName = attributeSet.getAttributeNameResource(i);
                            if (attrName == R.attr.animation) {
                                final int animId = attributeSet.getAttributeResourceValue(i, 0);
                                animator = loadAnimator(context, animId);
                            } else {
                                states[stateIndex++] =
                                        attributeSet.getAttributeBooleanValue(i, false) ?
                                                attrName : -attrName;
                            }
                        }
                        if (animator == null) {
                            animator = createAnimatorFromXml(context.getResources(),
                                    context.getTheme(), parser, 1f);
                        }

                        if (animator == null) {
                            throw new Resources.NotFoundException(
                                    "animation state item must have a valid animation");
                        }
                        stateListAnimator
                                .addState(StateSet.trimStateSet(states, stateIndex), animator);
                    }
                    break;
            }
        }
    }

    /**
     * PathDataEvaluator is used to interpolate between two paths which are
     * represented in the same format but different control points' values.
     * The path is represented as verbs and points for each of the verbs.
     */
    private static class PathDataEvaluator implements TypeEvaluator<PathParser.PathData> {
        private final PathParser.PathData mPathData = new PathParser.PathData();

        @Override
        public PathParser.PathData evaluate(float fraction, PathParser.PathData startPathData,
                    PathParser.PathData endPathData) {
            if (!PathParser.interpolatePathData(mPathData, startPathData, endPathData, fraction)) {
                throw new IllegalArgumentException("Can't interpolate between"
                        + " two incompatible pathData");
            }
            return mPathData;
        }
    }

    private static PropertyValuesHolder getPVH(TypedArray styledAttributes, int valueType,
            int valueFromId, int valueToId, String propertyName) {

        TypedValue tvFrom = styledAttributes.peekValue(valueFromId);
        boolean hasFrom = (tvFrom != null);
        int fromType = hasFrom ? tvFrom.type : 0;
        TypedValue tvTo = styledAttributes.peekValue(valueToId);
        boolean hasTo = (tvTo != null);
        int toType = hasTo ? tvTo.type : 0;

        if (valueType == VALUE_TYPE_UNDEFINED) {
            // Check whether it's color type. If not, fall back to default type (i.e. float type)
            if ((hasFrom && isColorType(fromType)) || (hasTo && isColorType(toType))) {
                valueType = VALUE_TYPE_COLOR;
            } else {
                valueType = VALUE_TYPE_FLOAT;
            }
        }

        boolean getFloats = (valueType == VALUE_TYPE_FLOAT);

        PropertyValuesHolder returnValue = null;

        if (valueType == VALUE_TYPE_PATH) {
            String fromString = styledAttributes.getString(valueFromId);
            String toString = styledAttributes.getString(valueToId);
            PathParser.PathData nodesFrom = fromString == null
                    ? null : new PathParser.PathData(fromString);
            PathParser.PathData nodesTo = toString == null
                    ? null : new PathParser.PathData(toString);

            if (nodesFrom != null || nodesTo != null) {
                if (nodesFrom != null) {
                    TypeEvaluator evaluator = new PathDataEvaluator();
                    if (nodesTo != null) {
                        if (!PathParser.canMorph(nodesFrom, nodesTo)) {
                            throw new InflateException(" Can't morph from " + fromString + " to " +
                                    toString);
                        }
                        returnValue = PropertyValuesHolder.ofObject(propertyName, evaluator,
                                nodesFrom, nodesTo);
                    } else {
                        returnValue = PropertyValuesHolder.ofObject(propertyName, evaluator,
                                (Object) nodesFrom);
                    }
                } else if (nodesTo != null) {
                    TypeEvaluator evaluator = new PathDataEvaluator();
                    returnValue = PropertyValuesHolder.ofObject(propertyName, evaluator,
                            (Object) nodesTo);
                }
            }
        } else {
            TypeEvaluator evaluator = null;
            // Integer and float value types are handled here.
            if (valueType == VALUE_TYPE_COLOR) {
                // special case for colors: ignore valueType and get ints
                evaluator = ArgbEvaluator.getInstance();
            }
            if (getFloats) {
                float valueFrom;
                float valueTo;
                if (hasFrom) {
                    if (fromType == TypedValue.TYPE_DIMENSION) {
                        valueFrom = styledAttributes.getDimension(valueFromId, 0f);
                    } else {
                        valueFrom = styledAttributes.getFloat(valueFromId, 0f);
                    }
                    if (hasTo) {
                        if (toType == TypedValue.TYPE_DIMENSION) {
                            valueTo = styledAttributes.getDimension(valueToId, 0f);
                        } else {
                            valueTo = styledAttributes.getFloat(valueToId, 0f);
                        }
                        returnValue = PropertyValuesHolder.ofFloat(propertyName,
                                valueFrom, valueTo);
                    } else {
                        returnValue = PropertyValuesHolder.ofFloat(propertyName, valueFrom);
                    }
                } else {
                    if (toType == TypedValue.TYPE_DIMENSION) {
                        valueTo = styledAttributes.getDimension(valueToId, 0f);
                    } else {
                        valueTo = styledAttributes.getFloat(valueToId, 0f);
                    }
                    returnValue = PropertyValuesHolder.ofFloat(propertyName, valueTo);
                }
            } else {
                int valueFrom;
                int valueTo;
                if (hasFrom) {
                    if (fromType == TypedValue.TYPE_DIMENSION) {
                        valueFrom = (int) styledAttributes.getDimension(valueFromId, 0f);
                    } else if (isColorType(fromType)) {
                        valueFrom = styledAttributes.getColor(valueFromId, 0);
                    } else {
                        valueFrom = styledAttributes.getInt(valueFromId, 0);
                    }
                    if (hasTo) {
                        if (toType == TypedValue.TYPE_DIMENSION) {
                            valueTo = (int) styledAttributes.getDimension(valueToId, 0f);
                        } else if (isColorType(toType)) {
                            valueTo = styledAttributes.getColor(valueToId, 0);
                        } else {
                            valueTo = styledAttributes.getInt(valueToId, 0);
                        }
                        returnValue = PropertyValuesHolder.ofInt(propertyName, valueFrom, valueTo);
                    } else {
                        returnValue = PropertyValuesHolder.ofInt(propertyName, valueFrom);
                    }
                } else {
                    if (hasTo) {
                        if (toType == TypedValue.TYPE_DIMENSION) {
                            valueTo = (int) styledAttributes.getDimension(valueToId, 0f);
                        } else if (isColorType(toType)) {
                            valueTo = styledAttributes.getColor(valueToId, 0);
                        } else {
                            valueTo = styledAttributes.getInt(valueToId, 0);
                        }
                        returnValue = PropertyValuesHolder.ofInt(propertyName, valueTo);
                    }
                }
            }
            if (returnValue != null && evaluator != null) {
                returnValue.setEvaluator(evaluator);
            }
        }

        return returnValue;
    }

    /**
     * @param anim The animator, must not be null
     * @param arrayAnimator Incoming typed array for Animator's attributes.
     * @param arrayObjectAnimator Incoming typed array for Object Animator's
     *            attributes.
     * @param pixelSize The relative pixel size, used to calculate the
     *                  maximum error for path animations.
     */
    private static void parseAnimatorFromTypeArray(ValueAnimator anim,
            TypedArray arrayAnimator, TypedArray arrayObjectAnimator, float pixelSize) {
        long duration = arrayAnimator.getInt(R.styleable.Animator_duration, 300);

        long startDelay = arrayAnimator.getInt(R.styleable.Animator_startOffset, 0);

        int valueType = arrayAnimator.getInt(R.styleable.Animator_valueType, VALUE_TYPE_UNDEFINED);

        if (valueType == VALUE_TYPE_UNDEFINED) {
            valueType = inferValueTypeFromValues(arrayAnimator, R.styleable.Animator_valueFrom,
                    R.styleable.Animator_valueTo);
        }
        PropertyValuesHolder pvh = getPVH(arrayAnimator, valueType,
                R.styleable.Animator_valueFrom, R.styleable.Animator_valueTo, "");
        if (pvh != null) {
            anim.setValues(pvh);
        }

        anim.setDuration(duration);
        anim.setStartDelay(startDelay);

        if (arrayAnimator.hasValue(R.styleable.Animator_repeatCount)) {
            anim.setRepeatCount(
                    arrayAnimator.getInt(R.styleable.Animator_repeatCount, 0));
        }
        if (arrayAnimator.hasValue(R.styleable.Animator_repeatMode)) {
            anim.setRepeatMode(
                    arrayAnimator.getInt(R.styleable.Animator_repeatMode,
                            ValueAnimator.RESTART));
        }

        if (arrayObjectAnimator != null) {
            setupObjectAnimator(anim, arrayObjectAnimator, valueType, pixelSize);
        }
    }

    /**
     * Setup the Animator to achieve path morphing.
     *
     * @param anim The target Animator which will be updated.
     * @param arrayAnimator TypedArray for the ValueAnimator.
     * @return the PathDataEvaluator.
     */
    private static TypeEvaluator setupAnimatorForPath(ValueAnimator anim,
             TypedArray arrayAnimator) {
        TypeEvaluator evaluator = null;
        String fromString = arrayAnimator.getString(R.styleable.Animator_valueFrom);
        String toString = arrayAnimator.getString(R.styleable.Animator_valueTo);
        PathParser.PathData pathDataFrom = fromString == null
                ? null : new PathParser.PathData(fromString);
        PathParser.PathData pathDataTo = toString == null
                ? null : new PathParser.PathData(toString);

        if (pathDataFrom != null) {
            if (pathDataTo != null) {
                anim.setObjectValues(pathDataFrom, pathDataTo);
                if (!PathParser.canMorph(pathDataFrom, pathDataTo)) {
                    throw new InflateException(arrayAnimator.getPositionDescription()
                            + " Can't morph from " + fromString + " to " + toString);
                }
            } else {
                anim.setObjectValues((Object)pathDataFrom);
            }
            evaluator = new PathDataEvaluator();
        } else if (pathDataTo != null) {
            anim.setObjectValues((Object)pathDataTo);
            evaluator = new PathDataEvaluator();
        }

        if (DBG_ANIMATOR_INFLATER && evaluator != null) {
            Log.v(TAG, "create a new PathDataEvaluator here");
        }

        return evaluator;
    }

    /**
     * Setup ObjectAnimator's property or values from pathData.
     *
     * @param anim The target Animator which will be updated.
     * @param arrayObjectAnimator TypedArray for the ObjectAnimator.
     * @param getFloats True if the value type is float.
     * @param pixelSize The relative pixel size, used to calculate the
     *                  maximum error for path animations.
     */
    private static void setupObjectAnimator(ValueAnimator anim, TypedArray arrayObjectAnimator,
            int valueType, float pixelSize) {
        ObjectAnimator oa = (ObjectAnimator) anim;
        String pathData = arrayObjectAnimator.getString(R.styleable.PropertyAnimator_pathData);

        // Path can be involved in an ObjectAnimator in the following 3 ways:
        // 1) Path morphing: the property to be animated is pathData, and valueFrom and valueTo
        //    are both of pathType. valueType = pathType needs to be explicitly defined.
        // 2) A property in X or Y dimension can be animated along a path: the property needs to be
        //    defined in propertyXName or propertyYName attribute, the path will be defined in the
        //    pathData attribute. valueFrom and valueTo will not be necessary for this animation.
        // 3) PathInterpolator can also define a path (in pathData) for its interpolation curve.
        // Here we are dealing with case 2:
        if (pathData != null) {
            String propertyXName =
                    arrayObjectAnimator.getString(R.styleable.PropertyAnimator_propertyXName);
            String propertyYName =
                    arrayObjectAnimator.getString(R.styleable.PropertyAnimator_propertyYName);

            if (valueType == VALUE_TYPE_PATH || valueType == VALUE_TYPE_UNDEFINED) {
                // When pathData is defined, we are in case #2 mentioned above. ValueType can only
                // be float type, or int type. Otherwise we fallback to default type.
                valueType = VALUE_TYPE_FLOAT;
            }
            if (propertyXName == null && propertyYName == null) {
                throw new InflateException(arrayObjectAnimator.getPositionDescription()
                        + " propertyXName or propertyYName is needed for PathData");
            } else {
                Path path = PathParser.createPathFromPathData(pathData);
                float error = 0.5f * pixelSize; // max half a pixel error
                PathKeyframes keyframeSet = KeyframeSet.ofPath(path, error);
                Keyframes xKeyframes;
                Keyframes yKeyframes;
                if (valueType == VALUE_TYPE_FLOAT) {
                    xKeyframes = keyframeSet.createXFloatKeyframes();
                    yKeyframes = keyframeSet.createYFloatKeyframes();
                } else {
                    xKeyframes = keyframeSet.createXIntKeyframes();
                    yKeyframes = keyframeSet.createYIntKeyframes();
                }
                PropertyValuesHolder x = null;
                PropertyValuesHolder y = null;
                if (propertyXName != null) {
                    x = PropertyValuesHolder.ofKeyframes(propertyXName, xKeyframes);
                }
                if (propertyYName != null) {
                    y = PropertyValuesHolder.ofKeyframes(propertyYName, yKeyframes);
                }
                if (x == null) {
                    oa.setValues(y);
                } else if (y == null) {
                    oa.setValues(x);
                } else {
                    oa.setValues(x, y);
                }
            }
        } else {
            String propertyName =
                    arrayObjectAnimator.getString(R.styleable.PropertyAnimator_propertyName);
            oa.setPropertyName(propertyName);
        }
    }

    /**
     * Setup ValueAnimator's values.
     * This will handle all of the integer, float and color types.
     *
     * @param anim The target Animator which will be updated.
     * @param arrayAnimator TypedArray for the ValueAnimator.
     * @param getFloats True if the value type is float.
     * @param hasFrom True if "valueFrom" exists.
     * @param fromType The type of "valueFrom".
     * @param hasTo True if "valueTo" exists.
     * @param toType The type of "valueTo".
     */
    private static void setupValues(ValueAnimator anim, TypedArray arrayAnimator,
            boolean getFloats, boolean hasFrom, int fromType, boolean hasTo, int toType) {
        int valueFromIndex = R.styleable.Animator_valueFrom;
        int valueToIndex = R.styleable.Animator_valueTo;
        if (getFloats) {
            float valueFrom;
            float valueTo;
            if (hasFrom) {
                if (fromType == TypedValue.TYPE_DIMENSION) {
                    valueFrom = arrayAnimator.getDimension(valueFromIndex, 0f);
                } else {
                    valueFrom = arrayAnimator.getFloat(valueFromIndex, 0f);
                }
                if (hasTo) {
                    if (toType == TypedValue.TYPE_DIMENSION) {
                        valueTo = arrayAnimator.getDimension(valueToIndex, 0f);
                    } else {
                        valueTo = arrayAnimator.getFloat(valueToIndex, 0f);
                    }
                    anim.setFloatValues(valueFrom, valueTo);
                } else {
                    anim.setFloatValues(valueFrom);
                }
            } else {
                if (toType == TypedValue.TYPE_DIMENSION) {
                    valueTo = arrayAnimator.getDimension(valueToIndex, 0f);
                } else {
                    valueTo = arrayAnimator.getFloat(valueToIndex, 0f);
                }
                anim.setFloatValues(valueTo);
            }
        } else {
            int valueFrom;
            int valueTo;
            if (hasFrom) {
                if (fromType == TypedValue.TYPE_DIMENSION) {
                    valueFrom = (int) arrayAnimator.getDimension(valueFromIndex, 0f);
                } else if (isColorType(fromType)) {
                    valueFrom = arrayAnimator.getColor(valueFromIndex, 0);
                } else {
                    valueFrom = arrayAnimator.getInt(valueFromIndex, 0);
                }
                if (hasTo) {
                    if (toType == TypedValue.TYPE_DIMENSION) {
                        valueTo = (int) arrayAnimator.getDimension(valueToIndex, 0f);
                    } else if (isColorType(toType)) {
                        valueTo = arrayAnimator.getColor(valueToIndex, 0);
                    } else {
                        valueTo = arrayAnimator.getInt(valueToIndex, 0);
                    }
                    anim.setIntValues(valueFrom, valueTo);
                } else {
                    anim.setIntValues(valueFrom);
                }
            } else {
                if (hasTo) {
                    if (toType == TypedValue.TYPE_DIMENSION) {
                        valueTo = (int) arrayAnimator.getDimension(valueToIndex, 0f);
                    } else if (isColorType(toType)) {
                        valueTo = arrayAnimator.getColor(valueToIndex, 0);
                    } else {
                        valueTo = arrayAnimator.getInt(valueToIndex, 0);
                    }
                    anim.setIntValues(valueTo);
                }
            }
        }
    }

    private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser,
            float pixelSize)
            throws XmlPullParserException, IOException {
        return createAnimatorFromXml(res, theme, parser, Xml.asAttributeSet(parser), null, 0,
                pixelSize);
    }

    private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser,
            AttributeSet attrs, AnimatorSet parent, int sequenceOrdering, float pixelSize)
            throws XmlPullParserException, IOException {
        Animator anim = null;
        ArrayList<Animator> childAnims = null;

        // Make sure we are on a start tag.
        int type;
        int depth = parser.getDepth();

        while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
                && type != XmlPullParser.END_DOCUMENT) {

            if (type != XmlPullParser.START_TAG) {
                continue;
            }

            String name = parser.getName();
            boolean gotValues = false;

            if (name.equals("objectAnimator")) {
                anim = loadObjectAnimator(res, theme, attrs, pixelSize);
            } else if (name.equals("animator")) {
                anim = loadAnimator(res, theme, attrs, null, pixelSize);
            } else if (name.equals("set")) {
                anim = new AnimatorSet();
                TypedArray a;
                if (theme != null) {
                    a = theme.obtainStyledAttributes(attrs, R.styleable.AnimatorSet, 0, 0);
                } else {
                    a = res.obtainAttributes(attrs, R.styleable.AnimatorSet);
                }
                anim.appendChangingConfigurations(a.getChangingConfigurations());
                int ordering = a.getInt(R.styleable.AnimatorSet_ordering, TOGETHER);
                createAnimatorFromXml(res, theme, parser, attrs, (AnimatorSet) anim, ordering,
                        pixelSize);
                a.recycle();
            } else if (name.equals("propertyValuesHolder")) {
                PropertyValuesHolder[] values = loadValues(res, theme, parser,
                        Xml.asAttributeSet(parser));
                if (values != null && anim != null && (anim instanceof ValueAnimator)) {
                    ((ValueAnimator) anim).setValues(values);
                }
                gotValues = true;
            } else {
                throw new RuntimeException("Unknown animator name: " + parser.getName());
            }

            if (parent != null && !gotValues) {
                if (childAnims == null) {
                    childAnims = new ArrayList<Animator>();
                }
                childAnims.add(anim);
            }
        }
        if (parent != null && childAnims != null) {
            Animator[] animsArray = new Animator[childAnims.size()];
            int index = 0;
            for (Animator a : childAnims) {
                animsArray[index++] = a;
            }
            if (sequenceOrdering == TOGETHER) {
                parent.playTogether(animsArray);
            } else {
                parent.playSequentially(animsArray);
            }
        }
        return anim;
    }

    private static PropertyValuesHolder[] loadValues(Resources res, Theme theme,
            XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException, IOException {
        ArrayList<PropertyValuesHolder> values = null;

        int type;
        while ((type = parser.getEventType()) != XmlPullParser.END_TAG &&
                type != XmlPullParser.END_DOCUMENT) {

            if (type != XmlPullParser.START_TAG) {
                parser.next();
                continue;
            }

            String name = parser.getName();

            if (name.equals("propertyValuesHolder")) {
                TypedArray a;
                if (theme != null) {
                    a = theme.obtainStyledAttributes(attrs, R.styleable.PropertyValuesHolder, 0, 0);
                } else {
                    a = res.obtainAttributes(attrs, R.styleable.PropertyValuesHolder);
                }
                String propertyName = a.getString(R.styleable.PropertyValuesHolder_propertyName);
                int valueType = a.getInt(R.styleable.PropertyValuesHolder_valueType,
                        VALUE_TYPE_UNDEFINED);

                PropertyValuesHolder pvh = loadPvh(res, theme, parser, propertyName, valueType);
                if (pvh == null) {
                    pvh = getPVH(a, valueType,
                            R.styleable.PropertyValuesHolder_valueFrom,
                            R.styleable.PropertyValuesHolder_valueTo, propertyName);
                }
                if (pvh != null) {
                    if (values == null) {
                        values = new ArrayList<PropertyValuesHolder>();
                    }
                    values.add(pvh);
                }
                a.recycle();
            }

            parser.next();
        }

        PropertyValuesHolder[] valuesArray = null;
        if (values != null) {
            int count = values.size();
            valuesArray = new PropertyValuesHolder[count];
            for (int i = 0; i < count; ++i) {
                valuesArray[i] = values.get(i);
            }
        }
        return valuesArray;
    }

    // When no value type is provided in keyframe, we need to infer the type from the value. i.e.
    // if value is defined in the style of a color value, then the color type is returned.
    // Otherwise, default float type is returned.
    private static int inferValueTypeOfKeyframe(Resources res, Theme theme, AttributeSet attrs) {
        int valueType;
        TypedArray a;
        if (theme != null) {
            a = theme.obtainStyledAttributes(attrs, R.styleable.Keyframe, 0, 0);
        } else {
            a = res.obtainAttributes(attrs, R.styleable.Keyframe);
        }

        TypedValue keyframeValue = a.peekValue(R.styleable.Keyframe_value);
        boolean hasValue = (keyframeValue != null);
        // When no value type is provided, check whether it's a color type first.
        // If not, fall back to default value type (i.e. float type).
        if (hasValue && isColorType(keyframeValue.type)) {
            valueType = VALUE_TYPE_COLOR;
        } else {
            valueType = VALUE_TYPE_FLOAT;
        }
        a.recycle();
        return valueType;
    }

    private static int inferValueTypeFromValues(TypedArray styledAttributes, int valueFromId,
            int valueToId) {
        TypedValue tvFrom = styledAttributes.peekValue(valueFromId);
        boolean hasFrom = (tvFrom != null);
        int fromType = hasFrom ? tvFrom.type : 0;
        TypedValue tvTo = styledAttributes.peekValue(valueToId);
        boolean hasTo = (tvTo != null);
        int toType = hasTo ? tvTo.type : 0;

        int valueType;
        // Check whether it's color type. If not, fall back to default type (i.e. float type)
        if ((hasFrom && isColorType(fromType)) || (hasTo && isColorType(toType))) {
            valueType = VALUE_TYPE_COLOR;
        } else {
            valueType = VALUE_TYPE_FLOAT;
        }
        return valueType;
    }

    private static void dumpKeyframes(Object[] keyframes, String header) {
        if (keyframes == null || keyframes.length == 0) {
            return;
        }
        Log.d(TAG, header);
        int count = keyframes.length;
        for (int i = 0; i < count; ++i) {
            Keyframe keyframe = (Keyframe) keyframes[i];
            Log.d(TAG, "Keyframe " + i + ": fraction " +
                    (keyframe.getFraction() < 0 ? "null" : keyframe.getFraction()) + ", " +
                    ", value : " + ((keyframe.hasValue()) ? keyframe.getValue() : "null"));
        }
    }

    // Load property values holder if there are keyframes defined in it. Otherwise return null.
    private static PropertyValuesHolder loadPvh(Resources res, Theme theme, XmlPullParser parser,
            String propertyName, int valueType)
            throws XmlPullParserException, IOException {

        PropertyValuesHolder value = null;
        ArrayList<Keyframe> keyframes = null;

        int type;
        while ((type = parser.next()) != XmlPullParser.END_TAG &&
                type != XmlPullParser.END_DOCUMENT) {
            String name = parser.getName();
            if (name.equals("keyframe")) {
                if (valueType == VALUE_TYPE_UNDEFINED) {
                    valueType = inferValueTypeOfKeyframe(res, theme, Xml.asAttributeSet(parser));
                }
                Keyframe keyframe = loadKeyframe(res, theme, Xml.asAttributeSet(parser), valueType);
                if (keyframe != null) {
                    if (keyframes == null) {
                        keyframes = new ArrayList<Keyframe>();
                    }
                    keyframes.add(keyframe);
                }
                parser.next();
            }
        }

        int count;
        if (keyframes != null && (count = keyframes.size()) > 0) {
            // make sure we have keyframes at 0 and 1
            // If we have keyframes with set fractions, add keyframes at start/end
            // appropriately. If start/end have no set fractions:
            // if there's only one keyframe, set its fraction to 1 and add one at 0
            // if >1 keyframe, set the last fraction to 1, the first fraction to 0
            Keyframe firstKeyframe = keyframes.get(0);
            Keyframe lastKeyframe = keyframes.get(count - 1);
            float endFraction = lastKeyframe.getFraction();
            if (endFraction < 1) {
                if (endFraction < 0) {
                    lastKeyframe.setFraction(1);
                } else {
                    keyframes.add(keyframes.size(), createNewKeyframe(lastKeyframe, 1));
                    ++count;
                }
            }
            float startFraction = firstKeyframe.getFraction();
            if (startFraction != 0) {
                if (startFraction < 0) {
                    firstKeyframe.setFraction(0);
                } else {
                    keyframes.add(0, createNewKeyframe(firstKeyframe, 0));
                    ++count;
                }
            }
            Keyframe[] keyframeArray = new Keyframe[count];
            keyframes.toArray(keyframeArray);
            for (int i = 0; i < count; ++i) {
                Keyframe keyframe = keyframeArray[i];
                if (keyframe.getFraction() < 0) {
                    if (i == 0) {
                        keyframe.setFraction(0);
                    } else if (i == count - 1) {
                        keyframe.setFraction(1);
                    } else {
                        // figure out the start/end parameters of the current gap
                        // in fractions and distribute the gap among those keyframes
                        int startIndex = i;
                        int endIndex = i;
                        for (int j = startIndex + 1; j < count - 1; ++j) {
                            if (keyframeArray[j].getFraction() >= 0) {
                                break;
                            }
                            endIndex = j;
                        }
                        float gap = keyframeArray[endIndex + 1].getFraction() -
                                keyframeArray[startIndex - 1].getFraction();
                        distributeKeyframes(keyframeArray, gap, startIndex, endIndex);
                    }
                }
            }
            value = PropertyValuesHolder.ofKeyframe(propertyName, keyframeArray);
            if (valueType == VALUE_TYPE_COLOR) {
                value.setEvaluator(ArgbEvaluator.getInstance());
            }
        }

        return value;
    }

    private static Keyframe createNewKeyframe(Keyframe sampleKeyframe, float fraction) {
        return sampleKeyframe.getType() == float.class ?
                            Keyframe.ofFloat(fraction) :
                            (sampleKeyframe.getType() == int.class) ?
                                    Keyframe.ofInt(fraction) :
                                    Keyframe.ofObject(fraction);
    }

    /**
     * Utility function to set fractions on keyframes to cover a gap in which the
     * fractions are not currently set. Keyframe fractions will be distributed evenly
     * in this gap. For example, a gap of 1 keyframe in the range 0-1 will be at .5, a gap
     * of .6 spread between two keyframes will be at .2 and .4 beyond the fraction at the
     * keyframe before startIndex.
     * Assumptions:
     * - First and last keyframe fractions (bounding this spread) are already set. So,
     * for example, if no fractions are set, we will already set first and last keyframe
     * fraction values to 0 and 1.
     * - startIndex must be >0 (which follows from first assumption).
     * - endIndex must be >= startIndex.
     *
     * @param keyframes the array of keyframes
     * @param gap The total gap we need to distribute
     * @param startIndex The index of the first keyframe whose fraction must be set
     * @param endIndex The index of the last keyframe whose fraction must be set
     */
    private static void distributeKeyframes(Keyframe[] keyframes, float gap,
            int startIndex, int endIndex) {
        int count = endIndex - startIndex + 2;
        float increment = gap / count;
        for (int i = startIndex; i <= endIndex; ++i) {
            keyframes[i].setFraction(keyframes[i-1].getFraction() + increment);
        }
    }

    private static Keyframe loadKeyframe(Resources res, Theme theme, AttributeSet attrs,
            int valueType)
            throws XmlPullParserException, IOException {

        TypedArray a;
        if (theme != null) {
            a = theme.obtainStyledAttributes(attrs, R.styleable.Keyframe, 0, 0);
        } else {
            a = res.obtainAttributes(attrs, R.styleable.Keyframe);
        }

        Keyframe keyframe = null;

        float fraction = a.getFloat(R.styleable.Keyframe_fraction, -1);

        TypedValue keyframeValue = a.peekValue(R.styleable.Keyframe_value);
        boolean hasValue = (keyframeValue != null);
        if (valueType == VALUE_TYPE_UNDEFINED) {
            // When no value type is provided, check whether it's a color type first.
            // If not, fall back to default value type (i.e. float type).
            if (hasValue && isColorType(keyframeValue.type)) {
                valueType = VALUE_TYPE_COLOR;
            } else {
                valueType = VALUE_TYPE_FLOAT;
            }
        }

        if (hasValue) {
            switch (valueType) {
                case VALUE_TYPE_FLOAT:
                    float value = a.getFloat(R.styleable.Keyframe_value, 0);
                    keyframe = Keyframe.ofFloat(fraction, value);
                    break;
                case VALUE_TYPE_COLOR:
                case VALUE_TYPE_INT:
                    int intValue = a.getInt(R.styleable.Keyframe_value, 0);
                    keyframe = Keyframe.ofInt(fraction, intValue);
                    break;
            }
        } else {
            keyframe = (valueType == VALUE_TYPE_FLOAT) ? Keyframe.ofFloat(fraction) :
                    Keyframe.ofInt(fraction);
        }

        final int resID = a.getResourceId(R.styleable.Keyframe_interpolator, 0);
        if (resID > 0) {
            final Interpolator interpolator = AnimationUtils.loadInterpolator(res, theme, resID);
            keyframe.setInterpolator(interpolator);
        }
        a.recycle();

        return keyframe;
    }

    private static ObjectAnimator loadObjectAnimator(Resources res, Theme theme, AttributeSet attrs,
            float pathErrorScale) throws NotFoundException {
        ObjectAnimator anim = new ObjectAnimator();

        loadAnimator(res, theme, attrs, anim, pathErrorScale);

        return anim;
    }

    /**
     * Creates a new animation whose parameters come from the specified context
     * and attributes set.
     *
     * @param res The resources
     * @param attrs The set of attributes holding the animation parameters
     * @param anim Null if this is a ValueAnimator, otherwise this is an
     *            ObjectAnimator
     */
    private static ValueAnimator loadAnimator(Resources res, Theme theme,
            AttributeSet attrs, ValueAnimator anim, float pathErrorScale)
            throws NotFoundException {
        TypedArray arrayAnimator = null;
        TypedArray arrayObjectAnimator = null;

        if (theme != null) {
            arrayAnimator = theme.obtainStyledAttributes(attrs, R.styleable.Animator, 0, 0);
        } else {
            arrayAnimator = res.obtainAttributes(attrs, R.styleable.Animator);
        }

        // If anim is not null, then it is an object animator.
        if (anim != null) {
            if (theme != null) {
                arrayObjectAnimator = theme.obtainStyledAttributes(attrs,
                        R.styleable.PropertyAnimator, 0, 0);
            } else {
                arrayObjectAnimator = res.obtainAttributes(attrs, R.styleable.PropertyAnimator);
            }
            anim.appendChangingConfigurations(arrayObjectAnimator.getChangingConfigurations());
        }

        if (anim == null) {
            anim = new ValueAnimator();
        }
        anim.appendChangingConfigurations(arrayAnimator.getChangingConfigurations());

        parseAnimatorFromTypeArray(anim, arrayAnimator, arrayObjectAnimator, pathErrorScale);

        final int resID = arrayAnimator.getResourceId(R.styleable.Animator_interpolator, 0);
        if (resID > 0) {
            final Interpolator interpolator = AnimationUtils.loadInterpolator(res, theme, resID);
            if (interpolator instanceof BaseInterpolator) {
                anim.appendChangingConfigurations(
                        ((BaseInterpolator) interpolator).getChangingConfiguration());
            }
            anim.setInterpolator(interpolator);
        }

        arrayAnimator.recycle();
        if (arrayObjectAnimator != null) {
            arrayObjectAnimator.recycle();
        }
        return anim;
    }

    private static @Config int getChangingConfigs(@NonNull Resources resources, @AnyRes int id) {
        synchronized (sTmpTypedValue) {
            resources.getValue(id, sTmpTypedValue, true);
            return sTmpTypedValue.changingConfigurations;
        }
    }

    private static boolean isColorType(int type) {
       return (type >= TypedValue.TYPE_FIRST_COLOR_INT) && (type <= TypedValue.TYPE_LAST_COLOR_INT);
    }
}
