1e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui/*
2e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * Copyright (C) 2014 The Android Open Source Project
3e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui *
4e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * in compliance with the License. You may obtain a copy of the License at
6e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui *
7e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * http://www.apache.org/licenses/LICENSE-2.0
8e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui *
9e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * Unless required by applicable law or agreed to in writing, software distributed under the License
10e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * or implied. See the License for the specific language governing permissions and limitations under
12e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * the License.
13e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui */
14e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
15e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuipackage android.graphics.drawable;
16e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
17e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.animation.Animator;
1818ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhuimport android.animation.Animator.AnimatorListener;
19e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.animation.AnimatorInflater;
2083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghuiimport android.animation.AnimatorListenerAdapter;
211588f0ff54b88240b55eeaba97e67f0f1dee5f92ztenghuiimport android.animation.AnimatorSet;
2218ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhuimport android.animation.ObjectAnimator;
23766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.animation.PropertyValuesHolder;
24766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.animation.TimeInterpolator;
25766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.animation.ValueAnimator;
2606cd7dce24876b54870f9ef3831237f8298773a9Alan Viveretteimport android.annotation.NonNull;
27d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viveretteimport android.annotation.Nullable;
28ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liuimport android.app.ActivityThread;
29ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liuimport android.app.Application;
30ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viveretteimport android.content.pm.ActivityInfo.Config;
3106cd7dce24876b54870f9ef3831237f8298773a9Alan Viveretteimport android.content.res.ColorStateList;
32e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.content.res.Resources;
33e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.content.res.Resources.Theme;
34e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.content.res.TypedArray;
35e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.graphics.Canvas;
36e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.graphics.ColorFilter;
3787e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viveretteimport android.graphics.Insets;
3806cd7dce24876b54870f9ef3831237f8298773a9Alan Viveretteimport android.graphics.Outline;
39f10d08a3d4968d3dfb4324959e33ebb691899edaTeng-Hui Zhuimport android.graphics.PixelFormat;
4006cd7dce24876b54870f9ef3831237f8298773a9Alan Viveretteimport android.graphics.PorterDuff;
41e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.graphics.Rect;
42ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liuimport android.os.Build;
436f6578e81c1df207da47e2e1337382341f271206Chet Haaseimport android.util.ArrayMap;
44e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.util.AttributeSet;
4544027214d4f2154ebc9265912933bac282be3bb4Doris Liuimport android.util.IntArray;
46e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.util.Log;
47766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.util.LongArray;
48766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.util.PathParser;
49792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liuimport android.util.Property;
50766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.util.TimeUtils;
51766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.view.Choreographer;
52766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.view.DisplayListCanvas;
53766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.view.RenderNode;
54766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.view.RenderNodeAnimatorSetHelper;
55dfa4646eca54511a28f2c61e1f4b9c697e05a913Alan Viveretteimport android.view.View;
56e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
57e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport com.android.internal.R;
58766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport com.android.internal.util.VirtualRefBasePtr;
59299659ddb7e0c34ca094abe485bcd0989727fc07John Reck
60e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport org.xmlpull.v1.XmlPullParser;
61e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport org.xmlpull.v1.XmlPullParserException;
62e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
63e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport java.io.IOException;
64766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport java.lang.ref.WeakReference;
65e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport java.util.ArrayList;
66e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
6718ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhuimport dalvik.annotation.optimization.FastNative;
6818ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu
69e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui/**
707d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * This class animates properties of a {@link android.graphics.drawable.VectorDrawable} with
717d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * animations defined using {@link android.animation.ObjectAnimator} or
727d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * {@link android.animation.AnimatorSet}.
737e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <p>
747d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * Starting from API 25, AnimatedVectorDrawable runs on RenderThread (as opposed to on UI thread for
757d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * earlier APIs). This means animations in AnimatedVectorDrawable can remain smooth even when there
767d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * is heavy workload on the UI thread. Note: If the UI thread is unresponsive, RenderThread may
777d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * continue animating until the UI thread is capable of pushing another frame. Therefore, it is not
787d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * possible to precisely coordinate a RenderThread-enabled AnimatedVectorDrawable with UI thread
797d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * animations. Additionally,
807d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * {@link android.graphics.drawable.Animatable2.AnimationCallback#onAnimationEnd(Drawable)} will be
817d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * called the frame after the AnimatedVectorDrawable finishes on the RenderThread.
827e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * </p>
837e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <p>
847d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * AnimatedVectorDrawable can be defined in either <a href="#ThreeXML">three separate XML files</a>,
857d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * or <a href="#OneXML">one XML</a>.
867e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * </p>
877d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <a name="ThreeXML"></a>
887d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <h3>Define an AnimatedVectorDrawable in three separate XML files</h3>
897d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <ul>
907d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <a name="VDExample"></a>
917d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <li><h4>XML for the VectorDrawable containing properties to be animated</h4>
927d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <p>
9318ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * Animations can be performed on the animatable attributes in
9418ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * {@link android.graphics.drawable.VectorDrawable}. These attributes will be animated by
9518ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * {@link android.animation.ObjectAnimator}. The ObjectAnimator's target can be the root element,
9618ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * a group element or a path element. The targeted elements need to be named uniquely within
9718ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * the same VectorDrawable. Elements without animation do not need to be named.
9818ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </p>
9918ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <p>
10018ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * Here are all the animatable attributes in {@link android.graphics.drawable.VectorDrawable}:
10118ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <table border="2" align="center" cellpadding="5">
10218ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     <thead>
10318ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <tr>
10418ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *             <th>Element Name</th>
10518ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *             <th>Animatable attribute name</th>
10618ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         </tr>
10718ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     </thead>
10818ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     <tr>
10918ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td>&lt;vector&gt;</td>
11018ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td>alpha</td>
11118ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     </tr>
11218ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     <tr>
11318ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td rowspan="7">&lt;group&gt;</td>
11418ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td>rotation</td>
11518ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     </tr>
11618ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     <tr>
11718ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td>pivotX</td>
11818ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     </tr>
11918ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     <tr>
12018ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td>pivotY</td>
12118ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     </tr>
12218ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     <tr>
12318ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td>scaleX</td>
12418ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     </tr>
12518ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     <tr>
12618ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td>scaleY</td>
12718ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     </tr>
12818ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     <tr>
12918ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td>translateX</td>
13018ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     </tr>
13118ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     <tr>
13218ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td>translateY</td>
13318ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     </tr>
13418ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     <tr>
13518ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td rowspan="8">&lt;path&gt;</td>
13618ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td>pathData</td>
13718ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     </tr>
13818ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     <tr>
13918ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td>fillColor</td>
14018ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     </tr>
14118ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     <tr>
14218ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td>strokeColor</td>
14318ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     </tr>
14418ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     <tr>
14518ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td>strokeWidth</td>
14618ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     </tr>
14718ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     <tr>
14818ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td>strokeAlpha</td>
14918ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     </tr>
15018ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     <tr>
15118ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td>fillAlpha</td>
15218ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     </tr>
15318ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     <tr>
15418ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td>trimPathStart</td>
15518ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     </tr>
15618ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     <tr>
15718ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td>trimPathOffset</td>
15818ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     </tr>
15918ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     <tr>
16018ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td>&lt;clip-path&gt;</td>
16118ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *         <td>pathData</td>
16218ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *     </tr>
16318ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </table>
1647d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * </p>
1657d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * Below is an example of a VectorDrawable defined in vectordrawable.xml. This VectorDrawable is
1667d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * referred to by its file name (not including file suffix) in the
1677d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <a href="AVDExample">AnimatedVectorDrawable XML example</a>.
1687e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <pre>
169a95c8abb366d9c39450513335f550b56da13b30aztenghui * &lt;vector xmlns:android=&quot;http://schemas.android.com/apk/res/android";
170a95c8abb366d9c39450513335f550b56da13b30aztenghui *     android:height=&quot;64dp&quot;
171a95c8abb366d9c39450513335f550b56da13b30aztenghui *     android:width=&quot;64dp&quot;
172a95c8abb366d9c39450513335f550b56da13b30aztenghui *     android:viewportHeight=&quot;600&quot;
173a95c8abb366d9c39450513335f550b56da13b30aztenghui *     android:viewportWidth=&quot;600&quot; &gt;
1747e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *     &lt;group
1757e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *         android:name=&quot;rotationGroup&quot;
1767e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *         android:pivotX=&quot;300.0&quot;
1777e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *         android:pivotY=&quot;300.0&quot;
1787e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *         android:rotation=&quot;45.0&quot; &gt;
1797e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *         &lt;path
1807e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *             android:name=&quot;v&quot;
181a95c8abb366d9c39450513335f550b56da13b30aztenghui *             android:fillColor=&quot;#000000&quot;
1827e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *             android:pathData=&quot;M300,70 l 0,-70 70,70 0,0 -70,70z&quot; /&gt;
1837e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *     &lt;/group&gt;
1847e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * &lt;/vector&gt;
1857e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * </pre></li>
1867d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu *
1877d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <a name="AVDExample"></a>
1887d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <li><h4>XML for AnimatedVectorDrawable</h4>
1897e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <p>
1907d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * An AnimatedVectorDrawable element has a VectorDrawable attribute, and one or more target
19118ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * element(s). The target element can specify its target by android:name attribute, and link the
19218ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * target with the proper ObjectAnimator or AnimatorSet by android:animation attribute.
1937e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * </p>
1947d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * The following code sample defines an AnimatedVectorDrawable. Note that the names refer to the
1957d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * groups and paths in the <a href="#VDExample">VectorDrawable XML above</a>.
1967e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <pre>
1977e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * &lt;animated-vector xmlns:android=&quot;http://schemas.android.com/apk/res/android";
1987d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu *     android:drawable=&quot;@drawable/vectordrawable&quot; &gt;
1997e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *     &lt;target
2007e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *         android:name=&quot;rotationGroup&quot;
2017e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *         android:animation=&quot;@anim/rotation&quot; /&gt;
2027e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *     &lt;target
2037e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *         android:name=&quot;v&quot;
2047e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *         android:animation=&quot;@anim/path_morph&quot; /&gt;
2057e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * &lt;/animated-vector&gt;
2067d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * </pre>
2077d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * </li>
2087d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu *
2097d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <li><h4>XML for Animations defined using ObjectAnimator or AnimatorSet</h4>
2107e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <p>
2117d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * From the previous <a href="#AVDExample">example of AnimatedVectorDrawable</a>, two animations
2127d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * were used: rotation.xml and path_morph.xml.
2137e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * </p>
2147d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * rotation.xml rotates the target group from 0 degree to 360 degrees over 6000ms:
2157e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <pre>
2167e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * &lt;objectAnimator
2177e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *     android:duration=&quot;6000&quot;
2187e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *     android:propertyName=&quot;rotation&quot;
2197e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *     android:valueFrom=&quot;0&quot;
2207e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *     android:valueTo=&quot;360&quot; /&gt;
2217d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * </pre>
2227d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu *
2237d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * path_morph.xml morphs the path from one shape into the other. Note that the paths must be
2247d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * compatible for morphing. Specifically, the paths must have the same commands, in the same order,
2257d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * and must have the same number of parameters for each command. It is recommended to store path
2267d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * strings as string resources for reuse.
2277e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <pre>
2287e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * &lt;set xmlns:android=&quot;http://schemas.android.com/apk/res/android">;
2297e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *     &lt;objectAnimator
2307e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *         android:duration=&quot;3000&quot;
2317e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *         android:propertyName=&quot;pathData&quot;
2327d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu *         android:valueFrom=&quot;M300,70 l 0,-70 70,70 0,0 -70,70z&quot;
2337e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *         android:valueTo=&quot;M300,70 l 0,-70 70,0  0,140 -70,0 z&quot;
2347e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui *         android:valueType=&quot;pathType&quot;/&gt;
2357e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * &lt;/set&gt;
2367d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * </pre>
2377d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * </ul>
2387d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <a name="OneXML"></a>
2397d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <h3>Define an AnimatedVectorDrawable all in one XML file</h3>
240d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * <p>
2417d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * Since the AAPT tool supports a new format that bundles several related XML files together, we can
2427d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * merge the XML files from the previous examples into one XML file:
243d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * </p>
244d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * <pre>
24518ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * &lt;animated-vector xmlns:android=&quot;http://schemas.android.com/apk/res/android";
24618ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu *                  xmlns:aapt=&quothttp://schemas.android.com/aapt"; &gt;
247d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *     &lt;aapt:attr name="android:drawable"&gt;
248d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *         &lt;vector
249d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *             android:height=&quot;64dp&quot;
250d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *             android:width=&quot;64dp&quot;
251d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *             android:viewportHeight=&quot;600&quot;
252d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *             android:viewportWidth=&quot;600&quot; &gt;
253d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *             &lt;group
254d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *                 android:name=&quot;rotationGroup&quot;
255d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *                 android:pivotX=&quot;300.0&quot;
256d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *                 android:pivotY=&quot;300.0&quot;
257d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *                 android:rotation=&quot;45.0&quot; &gt;
258d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *                 &lt;path
259d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *                     android:name=&quot;v&quot;
260d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *                     android:fillColor=&quot;#000000&quot;
261d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *                     android:pathData=&quot;M300,70 l 0,-70 70,70 0,0 -70,70z&quot; /&gt;
262d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *             &lt;/group&gt;
263d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *         &lt;/vector&gt;
264d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *     &lt;/aapt:attr&gt;
265d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *
266d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *     &lt;target android:name=&quot;rotationGroup&quot;&gt; *
267d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *         &lt;aapt:attr name="android:animation"&gt;
268d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *             &lt;objectAnimator
269d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *             android:duration=&quot;6000&quot;
270d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *             android:propertyName=&quot;rotation&quot;
271d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *             android:valueFrom=&quot;0&quot;
272d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *             android:valueTo=&quot;360&quot; /&gt;
273d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *         &lt;/aapt:attr&gt;
274d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *     &lt;/target&gt;
275d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *
276d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *     &lt;target android:name=&quot;v&quot; &gt;
277d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *         &lt;aapt:attr name="android:animation"&gt;
278d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *             &lt;set&gt;
279d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *                 &lt;objectAnimator
280d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *                     android:duration=&quot;3000&quot;
281d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *                     android:propertyName=&quot;pathData&quot;
2827d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu *                     android:valueFrom=&quot;M300,70 l 0,-70 70,70 0,0 -70,70z&quot;
283d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *                     android:valueTo=&quot;M300,70 l 0,-70 70,0  0,140 -70,0 z&quot;
284d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *                     android:valueType=&quot;pathType&quot;/&gt;
285d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *             &lt;/set&gt;
286d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *         &lt;/aapt:attr&gt;
287d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu *      &lt;/target&gt;
288d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * &lt;/animated-vector&gt;
289d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * </pre>
290e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui *
2917e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * @attr ref android.R.styleable#AnimatedVectorDrawable_drawable
2927e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * @attr ref android.R.styleable#AnimatedVectorDrawableTarget_name
2937e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * @attr ref android.R.styleable#AnimatedVectorDrawableTarget_animation
294e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui */
29583a52031fd5c277d0c6e75da50bf8013e8a70399ztenghuipublic class AnimatedVectorDrawable extends Drawable implements Animatable2 {
296d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette    private static final String LOGTAG = "AnimatedVectorDrawable";
297e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
298e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    private static final String ANIMATED_VECTOR = "animated-vector";
299e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    private static final String TARGET = "target";
300e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
301e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false;
302e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
303d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette    /** Local, mutable animator set. */
304718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu    private VectorDrawableAnimator mAnimatorSet;
305d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
306d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette    /**
307d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette     * The resources against which this drawable was created. Used to attempt
308d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette     * to inflate animators if applyTheme() doesn't get called.
309d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette     */
310d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette    private Resources mRes;
311d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
3126f6578e81c1df207da47e2e1337382341f271206Chet Haase    private AnimatedVectorDrawableState mAnimatedVectorState;
3136f6578e81c1df207da47e2e1337382341f271206Chet Haase
31428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu    /** The animator set that is parsed from the xml. */
31528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu    private AnimatorSet mAnimatorSetFromXml = null;
316d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
3176f6578e81c1df207da47e2e1337382341f271206Chet Haase    private boolean mMutated;
318e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
31983a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui    /** Use a internal AnimatorListener to support callbacks during animation events. */
32083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui    private ArrayList<Animatable2.AnimationCallback> mAnimationCallbacks = null;
32183a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui    private AnimatorListener mAnimatorListener = null;
32283a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui
323e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public AnimatedVectorDrawable() {
32417cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        this(null, null);
325e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
326e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
32717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette    private AnimatedVectorDrawable(AnimatedVectorDrawableState state, Resources res) {
32817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        mAnimatedVectorState = new AnimatedVectorDrawableState(state, mCallback, res);
329718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu        mAnimatorSet = new VectorDrawableAnimatorRT(this);
330d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        mRes = res;
331e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
332e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
333e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    @Override
3346f6578e81c1df207da47e2e1337382341f271206Chet Haase    public Drawable mutate() {
3356f6578e81c1df207da47e2e1337382341f271206Chet Haase        if (!mMutated && super.mutate() == this) {
336d2f50c78c3c5205d6b28b7079d2f845c3d9dc0b3ztenghui            mAnimatedVectorState = new AnimatedVectorDrawableState(
33795080637db69ffa4f31f18f32878ddd2457e6857ztenghui                    mAnimatedVectorState, mCallback, mRes);
3386f6578e81c1df207da47e2e1337382341f271206Chet Haase            mMutated = true;
3396f6578e81c1df207da47e2e1337382341f271206Chet Haase        }
3406f6578e81c1df207da47e2e1337382341f271206Chet Haase        return this;
3416f6578e81c1df207da47e2e1337382341f271206Chet Haase    }
3426f6578e81c1df207da47e2e1337382341f271206Chet Haase
343727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    /**
344727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     * @hide
345727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     */
346727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    public void clearMutated() {
347727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        super.clearMutated();
348d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        if (mAnimatedVectorState.mVectorDrawable != null) {
349d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            mAnimatedVectorState.mVectorDrawable.clearMutated();
350d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        }
351727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        mMutated = false;
352727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    }
353727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette
354ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu    /**
355ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu     * In order to avoid breaking old apps, we only throw exception on invalid VectorDrawable
356b34cbedb4e36f184232d7f40b093bdc9fd0cd752Dianne Hackborn     * animations for apps targeting N and later. For older apps, we ignore (i.e. quietly skip)
357ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu     * these animations.
358ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu     *
359ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu     * @return whether invalid animations for vector drawable should be ignored.
360ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu     */
361ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu    private static boolean shouldIgnoreInvalidAnimation() {
362ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu        Application app = ActivityThread.currentApplication();
363ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu        if (app == null || app.getApplicationInfo() == null) {
364ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu            return true;
365ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu        }
366ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu        if (app.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) {
367ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu            return true;
368ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu        }
369ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu        return false;
370ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu    }
371ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu
3726f6578e81c1df207da47e2e1337382341f271206Chet Haase    @Override
373e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public ConstantState getConstantState() {
37498916d146afe2ff25a439603f7d9559e74a790caztenghui        mAnimatedVectorState.mChangingConfigurations = getChangingConfigurations();
3756f6578e81c1df207da47e2e1337382341f271206Chet Haase        return mAnimatedVectorState;
376e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
377e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
378e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    @Override
379ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette    public @Config int getChangingConfigurations() {
380e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        return super.getChangingConfigurations() | mAnimatedVectorState.getChangingConfigurations();
38198916d146afe2ff25a439603f7d9559e74a790caztenghui    }
38298916d146afe2ff25a439603f7d9559e74a790caztenghui
3837d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu    /**
3847d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu     * Draws the AnimatedVectorDrawable into the given canvas.
3857d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu     * <p>
3867d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu     * <strong>Note:</strong> Calling this method with a software canvas when the
3877d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu     * AnimatedVectorDrawable is being animated on RenderThread (for API 25 and later) may yield
3887d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu     * outdated result, as the UI thread is not guaranteed to be in sync with RenderThread on
3897d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu     * VectorDrawable's property changes during RenderThread animations.
3907d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu     * </p>
3917d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu     *
3927d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu     * @param canvas The canvas to draw into
3937d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu     */
39498916d146afe2ff25a439603f7d9559e74a790caztenghui    @Override
395e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public void draw(Canvas canvas) {
396126df850ce6b5f8a355534eb09235e22995f0116Doris Liu        if (!canvas.isHardwareAccelerated() && mAnimatorSet instanceof VectorDrawableAnimatorRT) {
397126df850ce6b5f8a355534eb09235e22995f0116Doris Liu            // If we have SW canvas and the RT animation is waiting to start, We need to fallback
398126df850ce6b5f8a355534eb09235e22995f0116Doris Liu            // to UI thread animation for AVD.
399126df850ce6b5f8a355534eb09235e22995f0116Doris Liu            if (!mAnimatorSet.isRunning() &&
400126df850ce6b5f8a355534eb09235e22995f0116Doris Liu                    ((VectorDrawableAnimatorRT) mAnimatorSet).mPendingAnimationActions.size() > 0) {
401853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu                fallbackOntoUI();
402126df850ce6b5f8a355534eb09235e22995f0116Doris Liu            }
403126df850ce6b5f8a355534eb09235e22995f0116Doris Liu        }
40428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        mAnimatorSet.onDraw(canvas);
405e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        mAnimatedVectorState.mVectorDrawable.draw(canvas);
406e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
407e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
408e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    @Override
409e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    protected void onBoundsChange(Rect bounds) {
410e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        mAnimatedVectorState.mVectorDrawable.setBounds(bounds);
411e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
412e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
413e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    @Override
41406cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    protected boolean onStateChange(int[] state) {
41506cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette        return mAnimatedVectorState.mVectorDrawable.setState(state);
41606cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    }
41706cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette
41806cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    @Override
4190b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette    protected boolean onLevelChange(int level) {
42006cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette        return mAnimatedVectorState.mVectorDrawable.setLevel(level);
42106cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    }
42206cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette
42306cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    @Override
424dfa4646eca54511a28f2c61e1f4b9c697e05a913Alan Viverette    public boolean onLayoutDirectionChanged(@View.ResolvedLayoutDir int layoutDirection) {
425a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette        return mAnimatedVectorState.mVectorDrawable.setLayoutDirection(layoutDirection);
426a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette    }
427a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette
4281af03b1d5319921c9f898103353f2646975ab0afTeng-Hui Zhu    /**
4297d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu     * For API 25 and later, AnimatedVectorDrawable runs on RenderThread. Therefore, when the
4307d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu     * root alpha is being animated, this getter does not guarantee to return an up-to-date alpha
4317d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu     * value.
4321af03b1d5319921c9f898103353f2646975ab0afTeng-Hui Zhu     *
4331af03b1d5319921c9f898103353f2646975ab0afTeng-Hui Zhu     * @return the containing vector drawable's root alpha value.
4341af03b1d5319921c9f898103353f2646975ab0afTeng-Hui Zhu     */
435a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette    @Override
436e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public int getAlpha() {
437e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        return mAnimatedVectorState.mVectorDrawable.getAlpha();
438e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
439e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
440e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    @Override
441e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public void setAlpha(int alpha) {
442e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        mAnimatedVectorState.mVectorDrawable.setAlpha(alpha);
443e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
444e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
445e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    @Override
446e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public void setColorFilter(ColorFilter colorFilter) {
447e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        mAnimatedVectorState.mVectorDrawable.setColorFilter(colorFilter);
448e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
449e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
450e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    @Override
4511af03b1d5319921c9f898103353f2646975ab0afTeng-Hui Zhu    public ColorFilter getColorFilter() {
4521af03b1d5319921c9f898103353f2646975ab0afTeng-Hui Zhu        return mAnimatedVectorState.mVectorDrawable.getColorFilter();
4531af03b1d5319921c9f898103353f2646975ab0afTeng-Hui Zhu    }
4541af03b1d5319921c9f898103353f2646975ab0afTeng-Hui Zhu
4551af03b1d5319921c9f898103353f2646975ab0afTeng-Hui Zhu    @Override
45606cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    public void setTintList(ColorStateList tint) {
45706cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette        mAnimatedVectorState.mVectorDrawable.setTintList(tint);
45806cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    }
45906cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette
46006cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    @Override
46106cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    public void setHotspot(float x, float y) {
46206cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette        mAnimatedVectorState.mVectorDrawable.setHotspot(x, y);
46306cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    }
46406cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette
46506cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    @Override
46606cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    public void setHotspotBounds(int left, int top, int right, int bottom) {
46706cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette        mAnimatedVectorState.mVectorDrawable.setHotspotBounds(left, top, right, bottom);
46806cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    }
46906cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette
47006cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    @Override
47106cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    public void setTintMode(PorterDuff.Mode tintMode) {
47206cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette        mAnimatedVectorState.mVectorDrawable.setTintMode(tintMode);
47306cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    }
47406cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette
47506cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    @Override
47606cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    public boolean setVisible(boolean visible, boolean restart) {
477d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        if (mAnimatorSet.isInfinite() && mAnimatorSet.isStarted()) {
478d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu            if (visible) {
479d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu                // Resume the infinite animation when the drawable becomes visible again.
480d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu                mAnimatorSet.resume();
481d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu            } else {
482d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu                // Pause the infinite animation once the drawable is no longer visible.
483d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu                mAnimatorSet.pause();
484d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu            }
485d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        }
48606cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette        mAnimatedVectorState.mVectorDrawable.setVisible(visible, restart);
48706cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette        return super.setVisible(visible, restart);
48806cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    }
48906cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette
49006cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    @Override
49106cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    public boolean isStateful() {
49206cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette        return mAnimatedVectorState.mVectorDrawable.isStateful();
49306cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    }
49406cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette
49506cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    @Override
496e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public int getOpacity() {
497f10d08a3d4968d3dfb4324959e33ebb691899edaTeng-Hui Zhu        return PixelFormat.TRANSLUCENT;
498e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
499e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
500e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    @Override
501e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public int getIntrinsicWidth() {
502e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        return mAnimatedVectorState.mVectorDrawable.getIntrinsicWidth();
503e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
504e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
505e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    @Override
506e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public int getIntrinsicHeight() {
507e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        return mAnimatedVectorState.mVectorDrawable.getIntrinsicHeight();
508e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
509e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
510e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    @Override
51106cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    public void getOutline(@NonNull Outline outline) {
51206cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette        mAnimatedVectorState.mVectorDrawable.getOutline(outline);
51306cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    }
51406cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette
51587e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette    /** @hide */
51687e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette    @Override
51787e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette    public Insets getOpticalInsets() {
51887e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        return mAnimatedVectorState.mVectorDrawable.getOpticalInsets();
51987e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette    }
52087e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette
52106cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette    @Override
522e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
523e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            throws XmlPullParserException, IOException {
524d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        final AnimatedVectorDrawableState state = mAnimatedVectorState;
525e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
526e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        int eventType = parser.getEventType();
527fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount        float pathErrorScale = 1;
5281f859716a8e4b8c12d69ca8b3db8344de577d5c7Doris Liu        final int innerDepth = parser.getDepth() + 1;
5291f859716a8e4b8c12d69ca8b3db8344de577d5c7Doris Liu
5301f859716a8e4b8c12d69ca8b3db8344de577d5c7Doris Liu        // Parse everything until the end of the animated-vector element.
5311f859716a8e4b8c12d69ca8b3db8344de577d5c7Doris Liu        while (eventType != XmlPullParser.END_DOCUMENT
5321f859716a8e4b8c12d69ca8b3db8344de577d5c7Doris Liu                && (parser.getDepth() >= innerDepth || eventType != XmlPullParser.END_TAG)) {
533e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (eventType == XmlPullParser.START_TAG) {
534e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                final String tagName = parser.getName();
535e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                if (ANIMATED_VECTOR.equals(tagName)) {
536e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    final TypedArray a = obtainAttributes(res, theme, attrs,
537e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                            R.styleable.AnimatedVectorDrawable);
538e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    int drawableRes = a.getResourceId(
539e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                            R.styleable.AnimatedVectorDrawable_drawable, 0);
540e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    if (drawableRes != 0) {
541fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount                        VectorDrawable vectorDrawable = (VectorDrawable) res.getDrawable(
54255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                                drawableRes, theme).mutate();
543fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount                        vectorDrawable.setAllowCaching(false);
54417cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                        vectorDrawable.setCallback(mCallback);
545fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount                        pathErrorScale = vectorDrawable.getPixelSize();
546d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                        if (state.mVectorDrawable != null) {
547d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                            state.mVectorDrawable.setCallback(null);
54817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                        }
549d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                        state.mVectorDrawable = vectorDrawable;
550e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    }
551e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    a.recycle();
552e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                } else if (TARGET.equals(tagName)) {
553e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    final TypedArray a = obtainAttributes(res, theme, attrs,
554e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                            R.styleable.AnimatedVectorDrawableTarget);
555e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    final String target = a.getString(
556e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                            R.styleable.AnimatedVectorDrawableTarget_name);
557d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                    final int animResId = a.getResourceId(
558e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                            R.styleable.AnimatedVectorDrawableTarget_animation, 0);
559d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                    if (animResId != 0) {
560d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                        if (theme != null) {
561792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu                            // The animator here could be ObjectAnimator or AnimatorSet.
562792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu                            final Animator animator = AnimatorInflater.loadAnimator(
563d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                                    res, theme, animResId, pathErrorScale);
564a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu                            updateAnimatorProperty(animator, target, state.mVectorDrawable,
565a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu                                    state.mShouldIgnoreInvalidAnim);
566792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu                            state.addTargetAnimator(target, animator);
567d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                        } else {
568d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                            // The animation may be theme-dependent. As a
569d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                            // workaround until Animator has full support for
570d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                            // applyTheme(), postpone loading the animator
571d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                            // until we have a theme in applyTheme().
572d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                            state.addPendingAnimator(animResId, pathErrorScale, target);
573d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
574d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                        }
575e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    }
576e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    a.recycle();
577e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                }
578e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
579e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
580e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            eventType = parser.next();
581e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
5821588f0ff54b88240b55eeaba97e67f0f1dee5f92ztenghui
583d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        // If we don't have any pending animations, we don't need to hold a
584d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        // reference to the resources.
585d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        mRes = state.mPendingAnims == null ? null : res;
586e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
587e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
588792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu    private static void updateAnimatorProperty(Animator animator, String targetName,
589a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu            VectorDrawable vectorDrawable, boolean ignoreInvalidAnim) {
590792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu        if (animator instanceof ObjectAnimator) {
591792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu            // Change the property of the Animator from using reflection based on the property
592792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu            // name to a Property object that wraps the setter and getter for modifying that
593792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu            // specific property for a given object. By replacing the reflection with a direct call,
594792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu            // we can largely reduce the time it takes for a animator to modify a VD property.
595792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu            PropertyValuesHolder[] holders = ((ObjectAnimator) animator).getValues();
596792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu            for (int i = 0; i < holders.length; i++) {
597792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu                PropertyValuesHolder pvh = holders[i];
598792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu                String propertyName = pvh.getPropertyName();
599792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu                Object targetNameObj = vectorDrawable.getTargetByName(targetName);
600792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu                Property property = null;
601792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu                if (targetNameObj instanceof VectorDrawable.VObject) {
602792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu                    property = ((VectorDrawable.VObject) targetNameObj).getProperty(propertyName);
603792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu                } else if (targetNameObj instanceof VectorDrawable.VectorDrawableState) {
604792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu                    property = ((VectorDrawable.VectorDrawableState) targetNameObj)
605792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu                            .getProperty(propertyName);
606792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu                }
607792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu                if (property != null) {
608a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu                    if (containsSameValueType(pvh, property)) {
609a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu                        pvh.setProperty(property);
610a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu                    } else if (!ignoreInvalidAnim) {
611a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu                        throw new RuntimeException("Wrong valueType for Property: " + propertyName
612a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu                                + ".  Expected type: " + property.getType().toString() + ". Actual "
613a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu                                + "type defined in resources: " + pvh.getValueType().toString());
614a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu
615a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu                    }
616792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu                }
617792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu            }
618792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu        } else if (animator instanceof AnimatorSet) {
619792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu            for (Animator anim : ((AnimatorSet) animator).getChildAnimations()) {
620a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu                updateAnimatorProperty(anim, targetName, vectorDrawable, ignoreInvalidAnim);
621792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu            }
622792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu        }
623792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu    }
624792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu
625a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu    private static boolean containsSameValueType(PropertyValuesHolder holder, Property property) {
626a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu        Class type1 = holder.getValueType();
627a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu        Class type2 = property.getType();
628a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu        if (type1 == float.class || type1 == Float.class) {
629a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu            return type2 == float.class || type2 == Float.class;
630a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu        } else if (type1 == int.class || type1 == Integer.class) {
631a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu            return type2 == int.class || type2 == Integer.class;
632a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu        } else {
633a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu            return type1 == type2;
634a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu        }
635a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu    }
636a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu
63728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu    /**
63828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu     * Force to animate on UI thread.
63928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu     * @hide
64028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu     */
64128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu    public void forceAnimationOnUI() {
64228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        if (mAnimatorSet instanceof VectorDrawableAnimatorRT) {
64328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            VectorDrawableAnimatorRT animator = (VectorDrawableAnimatorRT) mAnimatorSet;
64428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            if (animator.isRunning()) {
64528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu                throw new UnsupportedOperationException("Cannot force Animated Vector Drawable to" +
64628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu                        " run on UI thread when the animation has started on RenderThread.");
64728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            }
648853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu            fallbackOntoUI();
649853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu        }
650853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu    }
651853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu
652853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu    private void fallbackOntoUI() {
653853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu        if (mAnimatorSet instanceof VectorDrawableAnimatorRT) {
654853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu            VectorDrawableAnimatorRT oldAnim = (VectorDrawableAnimatorRT) mAnimatorSet;
65528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            mAnimatorSet = new VectorDrawableAnimatorUI(this);
65628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            if (mAnimatorSetFromXml != null) {
65728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu                mAnimatorSet.init(mAnimatorSetFromXml);
65828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            }
659853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu            // Transfer the listener from RT animator to UI animator
660853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu            if (oldAnim.mListener != null) {
661853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu                mAnimatorSet.setListener(oldAnim.mListener);
662853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu            }
663853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu            oldAnim.transferPendingActions(mAnimatorSet);
66428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        }
66528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu    }
66628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu
667e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    @Override
668e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public boolean canApplyTheme() {
669d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        return (mAnimatedVectorState != null && mAnimatedVectorState.canApplyTheme())
670d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette                || super.canApplyTheme();
671e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
672e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
673e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    @Override
674e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public void applyTheme(Theme t) {
675e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        super.applyTheme(t);
676e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
677e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        final VectorDrawable vectorDrawable = mAnimatedVectorState.mVectorDrawable;
678e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        if (vectorDrawable != null && vectorDrawable.canApplyTheme()) {
679e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            vectorDrawable.applyTheme(t);
680e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
681d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
682d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        if (t != null) {
683d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            mAnimatedVectorState.inflatePendingAnimators(t.getResources(), t);
684d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        }
685d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
686d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        // If we don't have any pending animations, we don't need to hold a
687d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        // reference to the resources.
688d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        if (mAnimatedVectorState.mPendingAnims == null) {
689d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            mRes = null;
690d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        }
691e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
692e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
693e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    private static class AnimatedVectorDrawableState extends ConstantState {
694ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        @Config int mChangingConfigurations;
695e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        VectorDrawable mVectorDrawable;
696d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
697a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu        private final boolean mShouldIgnoreInvalidAnim;
698a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu
699d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        /** Animators that require a theme before inflation. */
700d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        ArrayList<PendingAnimator> mPendingAnims;
701d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
702d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        /** Fully inflated animators awaiting cloning into an AnimatorSet. */
703d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        ArrayList<Animator> mAnimators;
704d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
705d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        /** Map of animators to their target object names */
7066f6578e81c1df207da47e2e1337382341f271206Chet Haase        ArrayMap<Animator, String> mTargetNameMap;
707e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
70817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        public AnimatedVectorDrawableState(AnimatedVectorDrawableState copy,
70917cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                Callback owner, Resources res) {
710a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu            mShouldIgnoreInvalidAnim = shouldIgnoreInvalidAnimation();
711e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (copy != null) {
712e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mChangingConfigurations = copy.mChangingConfigurations;
713d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
7146f6578e81c1df207da47e2e1337382341f271206Chet Haase                if (copy.mVectorDrawable != null) {
71517cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                    final ConstantState cs = copy.mVectorDrawable.getConstantState();
71617cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                    if (res != null) {
71717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                        mVectorDrawable = (VectorDrawable) cs.newDrawable(res);
71817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                    } else {
71917cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                        mVectorDrawable = (VectorDrawable) cs.newDrawable();
72017cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                    }
72117cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                    mVectorDrawable = (VectorDrawable) mVectorDrawable.mutate();
72217cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                    mVectorDrawable.setCallback(owner);
72317cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                    mVectorDrawable.setLayoutDirection(copy.mVectorDrawable.getLayoutDirection());
7246f6578e81c1df207da47e2e1337382341f271206Chet Haase                    mVectorDrawable.setBounds(copy.mVectorDrawable.getBounds());
72517cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                    mVectorDrawable.setAllowCaching(false);
7266f6578e81c1df207da47e2e1337382341f271206Chet Haase                }
727d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
728d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                if (copy.mAnimators != null) {
729d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                    mAnimators = new ArrayList<>(copy.mAnimators);
730d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                }
731d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
732d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                if (copy.mTargetNameMap != null) {
733d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                    mTargetNameMap = new ArrayMap<>(copy.mTargetNameMap);
734d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                }
735d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
736d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                if (copy.mPendingAnims != null) {
737d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                    mPendingAnims = new ArrayList<>(copy.mPendingAnims);
7386f6578e81c1df207da47e2e1337382341f271206Chet Haase                }
73998916d146afe2ff25a439603f7d9559e74a790caztenghui            } else {
74098916d146afe2ff25a439603f7d9559e74a790caztenghui                mVectorDrawable = new VectorDrawable();
741e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
742e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
743e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
744e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        @Override
745d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        public boolean canApplyTheme() {
746d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette            return (mVectorDrawable != null && mVectorDrawable.canApplyTheme())
747d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                    || mPendingAnims != null || super.canApplyTheme();
748d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        }
749d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette
750d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        @Override
751e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public Drawable newDrawable() {
75217cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette            return new AnimatedVectorDrawable(this, null);
753e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
754e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
755e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        @Override
756e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public Drawable newDrawable(Resources res) {
75717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette            return new AnimatedVectorDrawable(this, res);
758e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
759e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
760e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        @Override
761ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        public @Config int getChangingConfigurations() {
762e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mChangingConfigurations;
763e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
764e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
765d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        public void addPendingAnimator(int resId, float pathErrorScale, String target) {
766d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            if (mPendingAnims == null) {
767d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                mPendingAnims = new ArrayList<>(1);
768d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            }
769d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            mPendingAnims.add(new PendingAnimator(resId, pathErrorScale, target));
770d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        }
771d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
772d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        public void addTargetAnimator(String targetName, Animator animator) {
773d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            if (mAnimators == null) {
774d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                mAnimators = new ArrayList<>(1);
775d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                mTargetNameMap = new ArrayMap<>(1);
776d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            }
777d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            mAnimators.add(animator);
778d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            mTargetNameMap.put(animator, targetName);
779d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
780d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            if (DBG_ANIMATION_VECTOR_DRAWABLE) {
781d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                Log.v(LOGTAG, "add animator  for target " + targetName + " " + animator);
782d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            }
7836f6578e81c1df207da47e2e1337382341f271206Chet Haase        }
784d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
785d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        /**
786d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         * Prepares a local set of mutable animators based on the constant
787d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         * state.
788d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         * <p>
789d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         * If there are any pending uninflated animators, attempts to inflate
790d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         * them immediately against the provided resources object.
791d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         *
792d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         * @param animatorSet the animator set to which the animators should
793d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         *                    be added
794d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         * @param res the resources against which to inflate any pending
795d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         *            animators, or {@code null} if not available
796d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         */
797d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        public void prepareLocalAnimators(@NonNull AnimatorSet animatorSet,
798d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                @Nullable Resources res) {
799d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            // Check for uninflated animators. We can remove this after we add
800d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            // support for Animator.applyTheme(). See comments in inflate().
801d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            if (mPendingAnims != null) {
802d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                // Attempt to load animators without applying a theme.
803d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                if (res != null) {
804d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                    inflatePendingAnimators(res, null);
805d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                } else {
806d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                    Log.e(LOGTAG, "Failed to load animators. Either the AnimatedVectorDrawable"
807d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                            + " must be created using a Resources object or applyTheme() must be"
808d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                            + " called with a non-null Theme object.");
809d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                }
810d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
811d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                mPendingAnims = null;
812d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            }
813d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
814d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            // Perform a deep copy of the constant state's animators.
815d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            final int count = mAnimators == null ? 0 : mAnimators.size();
816d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            if (count > 0) {
817d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                final Animator firstAnim = prepareLocalAnimator(0);
818d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                final AnimatorSet.Builder builder = animatorSet.play(firstAnim);
819d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                for (int i = 1; i < count; ++i) {
820d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                    final Animator nextAnim = prepareLocalAnimator(i);
821d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                    builder.with(nextAnim);
822d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                }
823d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            }
824d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        }
825d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
826d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        /**
827d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         * Prepares a local animator for the given index within the constant
828d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         * state's list of animators.
829d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         *
830d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         * @param index the index of the animator within the constant state
831d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         */
832d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        private Animator prepareLocalAnimator(int index) {
833d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            final Animator animator = mAnimators.get(index);
834d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            final Animator localAnimator = animator.clone();
835d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            final String targetName = mTargetNameMap.get(animator);
836d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            final Object target = mVectorDrawable.getTargetByName(targetName);
83703f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu            if (!mShouldIgnoreInvalidAnim) {
83803f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu                if (target == null) {
83903f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu                    throw new IllegalStateException("Target with the name \"" + targetName
84003f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu                            + "\" cannot be found in the VectorDrawable to be animated.");
84103f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu                } else if (!(target instanceof VectorDrawable.VectorDrawableState)
84203f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu                        && !(target instanceof VectorDrawable.VObject)) {
84303f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu                    throw new UnsupportedOperationException("Target should be either VGroup, VPath,"
84403f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu                            + " or ConstantState, " + target.getClass() + " is not supported");
84503f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu                }
84603f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu            }
847d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            localAnimator.setTarget(target);
848d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            return localAnimator;
849d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        }
850d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
851d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        /**
852d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         * Inflates pending animators, if any, against a theme. Clears the list of
853d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         * pending animators.
854d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         *
855d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         * @param t the theme against which to inflate the animators
856d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         */
857d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        public void inflatePendingAnimators(@NonNull Resources res, @Nullable Theme t) {
858d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            final ArrayList<PendingAnimator> pendingAnims = mPendingAnims;
859d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            if (pendingAnims != null) {
860d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                mPendingAnims = null;
861d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
862d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                for (int i = 0, count = pendingAnims.size(); i < count; i++) {
863d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                    final PendingAnimator pendingAnimator = pendingAnims.get(i);
864792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu                    final Animator animator = pendingAnimator.newInstance(res, t);
865a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu                    updateAnimatorProperty(animator, pendingAnimator.target, mVectorDrawable,
866a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu                            mShouldIgnoreInvalidAnim);
867792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu                    addTargetAnimator(pendingAnimator.target, animator);
868d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                }
869d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            }
870d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        }
871d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
872d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        /**
873d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         * Basically a constant state for Animators until we actually implement
874d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         * constant states for Animators.
875d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette         */
876d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        private static class PendingAnimator {
877d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            public final int animResId;
878d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            public final float pathErrorScale;
879d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            public final String target;
880d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
881d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            public PendingAnimator(int animResId, float pathErrorScale, String target) {
882d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                this.animResId = animResId;
883d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                this.pathErrorScale = pathErrorScale;
884d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                this.target = target;
885d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            }
886d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
887d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            public Animator newInstance(Resources res, Theme theme) {
888d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette                return AnimatorInflater.loadAnimator(res, theme, animResId, pathErrorScale);
889d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            }
890e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
891e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
892e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
893e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    @Override
894e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public boolean isRunning() {
895d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        return mAnimatorSet.isRunning();
896e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
897e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
89896052718067e1645afd7c7ae93bab536711349acztenghui    /**
89996052718067e1645afd7c7ae93bab536711349acztenghui     * Resets the AnimatedVectorDrawable to the start state as specified in the animators.
90096052718067e1645afd7c7ae93bab536711349acztenghui     */
90196052718067e1645afd7c7ae93bab536711349acztenghui    public void reset() {
90228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        ensureAnimatorSet();
90344027214d4f2154ebc9265912933bac282be3bb4Doris Liu        if (DBG_ANIMATION_VECTOR_DRAWABLE) {
90444027214d4f2154ebc9265912933bac282be3bb4Doris Liu            Log.w(LOGTAG, "calling reset on AVD: " +
90544027214d4f2154ebc9265912933bac282be3bb4Doris Liu                    ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
90644027214d4f2154ebc9265912933bac282be3bb4Doris Liu                    getConstantState()).mVectorDrawable.getConstantState()).mRootName
90744027214d4f2154ebc9265912933bac282be3bb4Doris Liu                    + ", at: " + this);
90844027214d4f2154ebc9265912933bac282be3bb4Doris Liu        }
909766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        mAnimatorSet.reset();
91096052718067e1645afd7c7ae93bab536711349acztenghui    }
91196052718067e1645afd7c7ae93bab536711349acztenghui
912e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    @Override
913e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public void start() {
914d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        ensureAnimatorSet();
91544027214d4f2154ebc9265912933bac282be3bb4Doris Liu        if (DBG_ANIMATION_VECTOR_DRAWABLE) {
91644027214d4f2154ebc9265912933bac282be3bb4Doris Liu            Log.w(LOGTAG, "calling start on AVD: " +
91744027214d4f2154ebc9265912933bac282be3bb4Doris Liu                    ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
91844027214d4f2154ebc9265912933bac282be3bb4Doris Liu                    getConstantState()).mVectorDrawable.getConstantState()).mRootName
91944027214d4f2154ebc9265912933bac282be3bb4Doris Liu                    + ", at: " + this);
92044027214d4f2154ebc9265912933bac282be3bb4Doris Liu        }
921d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        mAnimatorSet.start();
922e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
923e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
924d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette    @NonNull
925d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette    private void ensureAnimatorSet() {
92628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        if (mAnimatorSetFromXml == null) {
927766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            // TODO: Skip the AnimatorSet creation and init the VectorDrawableAnimator directly
928766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            // with a list of LocalAnimators.
92928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            mAnimatorSetFromXml = new AnimatorSet();
93028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            mAnimatedVectorState.prepareLocalAnimators(mAnimatorSetFromXml, mRes);
93128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            mAnimatorSet.init(mAnimatorSetFromXml);
932d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette            mRes = null;
933d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        }
934d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette    }
935d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
936e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    @Override
937e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public void stop() {
93844027214d4f2154ebc9265912933bac282be3bb4Doris Liu        if (DBG_ANIMATION_VECTOR_DRAWABLE) {
93944027214d4f2154ebc9265912933bac282be3bb4Doris Liu            Log.w(LOGTAG, "calling stop on AVD: " +
94044027214d4f2154ebc9265912933bac282be3bb4Doris Liu                    ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
94144027214d4f2154ebc9265912933bac282be3bb4Doris Liu                            getConstantState()).mVectorDrawable.getConstantState())
94244027214d4f2154ebc9265912933bac282be3bb4Doris Liu                            .mRootName + ", at: " + this);
94344027214d4f2154ebc9265912933bac282be3bb4Doris Liu        }
944d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        mAnimatorSet.end();
945e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
9466e0a9fa6ed86e918bfed5310d2522b2c2a527ef0Alan Viverette
9476e0a9fa6ed86e918bfed5310d2522b2c2a527ef0Alan Viverette    /**
9486e0a9fa6ed86e918bfed5310d2522b2c2a527ef0Alan Viverette     * Reverses ongoing animations or starts pending animations in reverse.
9496e0a9fa6ed86e918bfed5310d2522b2c2a527ef0Alan Viverette     * <p>
9505b84eace6cb79c42fe43480f08c68b7dea4e074aztenghui     * NOTE: Only works if all animations support reverse. Otherwise, this will
9515b84eace6cb79c42fe43480f08c68b7dea4e074aztenghui     * do nothing.
9527bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui     * @hide
9536e0a9fa6ed86e918bfed5310d2522b2c2a527ef0Alan Viverette     */
9547bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui    public void reverse() {
955d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        ensureAnimatorSet();
956d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
957d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        // Only reverse when all the animators can be reversed.
9585b84eace6cb79c42fe43480f08c68b7dea4e074aztenghui        if (!canReverse()) {
9595b84eace6cb79c42fe43480f08c68b7dea4e074aztenghui            Log.w(LOGTAG, "AnimatedVectorDrawable can't reverse()");
9605b84eace6cb79c42fe43480f08c68b7dea4e074aztenghui            return;
9615b84eace6cb79c42fe43480f08c68b7dea4e074aztenghui        }
962d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette
963d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        mAnimatorSet.reverse();
9646e0a9fa6ed86e918bfed5310d2522b2c2a527ef0Alan Viverette    }
9657bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui
9667bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui    /**
9677bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui     * @hide
9687bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui     */
9697bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui    public boolean canReverse() {
970d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette        return mAnimatorSet.canReverse();
9717bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui    }
97217cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette
97317cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette    private final Callback mCallback = new Callback() {
97417cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        @Override
975f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette        public void invalidateDrawable(@NonNull Drawable who) {
97617cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette            invalidateSelf();
97717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        }
97817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette
97917cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        @Override
980f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette        public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
98117cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette            scheduleSelf(what, when);
98217cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        }
98317cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette
98417cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        @Override
985f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette        public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
98617cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette            unscheduleSelf(what);
98717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        }
98817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette    };
98983a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui
99083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui    @Override
99183a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui    public void registerAnimationCallback(@NonNull AnimationCallback callback) {
99283a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        if (callback == null) {
99383a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui            return;
99483a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        }
99583a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui
99683a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        // Add listener accordingly.
99783a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        if (mAnimationCallbacks == null) {
99883a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui            mAnimationCallbacks = new ArrayList<>();
99983a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        }
100083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui
100183a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        mAnimationCallbacks.add(callback);
100283a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui
100383a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        if (mAnimatorListener == null) {
100483a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui            // Create a animator listener and trigger the callback events when listener is
100583a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui            // triggered.
100683a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui            mAnimatorListener = new AnimatorListenerAdapter() {
100783a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui                @Override
100883a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui                public void onAnimationStart(Animator animation) {
100983a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui                    ArrayList<AnimationCallback> tmpCallbacks = new ArrayList<>(mAnimationCallbacks);
101083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui                    int size = tmpCallbacks.size();
101183a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui                    for (int i = 0; i < size; i ++) {
101283a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui                        tmpCallbacks.get(i).onAnimationStart(AnimatedVectorDrawable.this);
101383a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui                    }
101483a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui                }
101583a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui
101683a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui                @Override
101783a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui                public void onAnimationEnd(Animator animation) {
101883a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui                    ArrayList<AnimationCallback> tmpCallbacks = new ArrayList<>(mAnimationCallbacks);
101983a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui                    int size = tmpCallbacks.size();
102083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui                    for (int i = 0; i < size; i ++) {
102183a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui                        tmpCallbacks.get(i).onAnimationEnd(AnimatedVectorDrawable.this);
102283a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui                    }
102383a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui                }
102483a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui            };
102583a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        }
1026766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        mAnimatorSet.setListener(mAnimatorListener);
102783a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui    }
102883a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui
102983a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui    // A helper function to clean up the animator listener in the mAnimatorSet.
103083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui    private void removeAnimatorSetListener() {
103183a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        if (mAnimatorListener != null) {
103228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            mAnimatorSet.removeListener(mAnimatorListener);
103383a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui            mAnimatorListener = null;
103483a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        }
103583a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui    }
103683a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui
103783a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui    @Override
103883a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui    public boolean unregisterAnimationCallback(@NonNull AnimationCallback callback) {
103983a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        if (mAnimationCallbacks == null || callback == null) {
104083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui            // Nothing to be removed.
104183a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui            return false;
104283a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        }
104383a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        boolean removed = mAnimationCallbacks.remove(callback);
104483a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui
104583a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        //  When the last call back unregistered, remove the listener accordingly.
104683a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        if (mAnimationCallbacks.size() == 0) {
104783a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui            removeAnimatorSetListener();
104883a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        }
104983a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        return removed;
105083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui    }
105183a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui
105283a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui    @Override
105383a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui    public void clearAnimationCallbacks() {
105483a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        removeAnimatorSetListener();
105583a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        if (mAnimationCallbacks == null) {
105683a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui            return;
105783a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        }
105883a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui
105983a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui        mAnimationCallbacks.clear();
106083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui    }
1061766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
106228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu    private interface VectorDrawableAnimator {
1063988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu        void init(@NonNull AnimatorSet set);
106428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        void start();
106528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        void end();
106628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        void reset();
106728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        void reverse();
106828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        boolean canReverse();
106928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        void setListener(AnimatorListener listener);
107028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        void removeListener(AnimatorListener listener);
107128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        void onDraw(Canvas canvas);
107228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        boolean isStarted();
107328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        boolean isRunning();
1074d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        boolean isInfinite();
1075d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        void pause();
1076d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        void resume();
107728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu    }
107828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu
107928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu    private static class VectorDrawableAnimatorUI implements VectorDrawableAnimator {
1080988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu        // mSet is only initialized in init(). So we need to check whether it is null before any
1081988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu        // operation.
1082988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu        private AnimatorSet mSet = null;
108328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        private final Drawable mDrawable;
1084988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu        // Caching the listener in the case when listener operation is called before the mSet is
1085988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu        // setup by init().
1086988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu        private ArrayList<AnimatorListener> mListenerArray = null;
1087d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        private boolean mIsInfinite = false;
108828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu
1089988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu        VectorDrawableAnimatorUI(@NonNull AnimatedVectorDrawable drawable) {
109028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            mDrawable = drawable;
109128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        }
109228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu
109328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
1094988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu        public void init(@NonNull AnimatorSet set) {
1095988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            if (mSet != null) {
1096988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                // Already initialized
1097988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                throw new UnsupportedOperationException("VectorDrawableAnimator cannot be " +
1098988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                        "re-initialized");
1099988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            }
1100988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            // Keep a deep copy of the set, such that set can be still be constantly representing
1101988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            // the static content from XML file.
1102988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            mSet = set.clone();
1103d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu            mIsInfinite = mSet.getTotalDuration() == Animator.DURATION_INFINITE;
1104988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu
1105988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            // If there are listeners added before calling init(), now they should be setup.
1106988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            if (mListenerArray != null && !mListenerArray.isEmpty()) {
1107988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                for (int i = 0; i < mListenerArray.size(); i++) {
1108988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                    mSet.addListener(mListenerArray.get(i));
1109988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                }
1110988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                mListenerArray.clear();
1111988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                mListenerArray = null;
1112988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            }
111328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        }
111428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu
1115988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu        // Although start(), reset() and reverse() should call init() already, it is better to
1116988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu        // protect these functions from NPE in any situation.
111728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
111828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        public void start() {
1119988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            if (mSet == null || mSet.isStarted()) {
112028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu                return;
112128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            }
112228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            mSet.start();
112328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            invalidateOwningView();
112428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        }
112528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu
112628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
112728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        public void end() {
1128988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            if (mSet == null) {
1129988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                return;
1130988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            }
113128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            mSet.end();
113228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        }
113328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu
113428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
113528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        public void reset() {
1136988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            if (mSet == null) {
1137988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                return;
1138988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            }
113928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            start();
114028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            mSet.cancel();
114128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        }
114228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu
114328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
114428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        public void reverse() {
1145988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            if (mSet == null) {
1146988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                return;
1147988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            }
114828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            mSet.reverse();
114928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            invalidateOwningView();
115028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        }
115128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu
115228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
115328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        public boolean canReverse() {
1154988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            return mSet != null && mSet.canReverse();
115528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        }
115628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu
115728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
115828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        public void setListener(AnimatorListener listener) {
1159988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            if (mSet == null) {
1160988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                if (mListenerArray == null) {
1161988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                    mListenerArray = new ArrayList<AnimatorListener>();
1162988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                }
1163988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                mListenerArray.add(listener);
1164988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            } else {
1165988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                mSet.addListener(listener);
1166988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            }
116728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        }
116828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu
116928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
117028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        public void removeListener(AnimatorListener listener) {
1171988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            if (mSet == null) {
1172988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                if (mListenerArray == null) {
1173988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                    return;
1174988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                }
1175988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                mListenerArray.remove(listener);
1176988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            } else {
1177988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu                mSet.removeListener(listener);
1178988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            }
117928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        }
118028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu
118128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
118228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        public void onDraw(Canvas canvas) {
1183988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            if (mSet != null && mSet.isStarted()) {
118428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu                invalidateOwningView();
118528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            }
118628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        }
118728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu
118828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
118928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        public boolean isStarted() {
1190988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            return mSet != null && mSet.isStarted();
119128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        }
119228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu
119328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
119428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        public boolean isRunning() {
1195988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu            return mSet != null && mSet.isRunning();
119628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        }
119728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu
1198d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        @Override
1199d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        public boolean isInfinite() {
1200d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu            return mIsInfinite;
1201d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        }
1202d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu
1203d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        @Override
1204d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        public void pause() {
1205d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu            if (mSet == null) {
1206d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu                return;
1207d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu            }
1208d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu            mSet.pause();
1209d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        }
1210d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu
1211d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        @Override
1212d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        public void resume() {
1213d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu            if (mSet == null) {
1214d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu                return;
1215d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu            }
1216d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu            mSet.resume();
1217d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        }
1218d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu
121928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        private void invalidateOwningView() {
122028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            mDrawable.invalidateSelf();
122128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        }
122228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu    }
122328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu
1224766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    /**
1225766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu     * @hide
1226766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu     */
122728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu    public static class VectorDrawableAnimatorRT implements VectorDrawableAnimator {
1228c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu        private static final int START_ANIMATION = 1;
1229c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu        private static final int REVERSE_ANIMATION = 2;
123044027214d4f2154ebc9265912933bac282be3bb4Doris Liu        private static final int RESET_ANIMATION = 3;
123144027214d4f2154ebc9265912933bac282be3bb4Doris Liu        private static final int END_ANIMATION = 4;
1232c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu
1233c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu        // If the duration of an animation is more than 300 frames, we cap the sample size to 300.
1234c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu        private static final int MAX_SAMPLE_POINTS = 300;
1235766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        private AnimatorListener mListener = null;
1236766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        private final LongArray mStartDelays = new LongArray();
1237766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        private PropertyValuesHolder.PropertyValues mTmpValues =
1238766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                new PropertyValuesHolder.PropertyValues();
1239766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        private long mSetPtr = 0;
1240766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        private boolean mContainsSequentialAnimators = false;
1241766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        private boolean mStarted = false;
1242766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        private boolean mInitialized = false;
1243766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        private boolean mIsReversible = false;
1244d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        private boolean mIsInfinite = false;
1245766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        // TODO: Consider using NativeAllocationRegistery to track native allocation
1246766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        private final VirtualRefBasePtr mSetRefBasePtr;
1247766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        private WeakReference<RenderNode> mLastSeenTarget = null;
1248c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu        private int mLastListenerId = 0;
124944027214d4f2154ebc9265912933bac282be3bb4Doris Liu        private final IntArray mPendingAnimationActions = new IntArray();
1250718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu        private final AnimatedVectorDrawable mDrawable;
1251766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
125228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        VectorDrawableAnimatorRT(AnimatedVectorDrawable drawable) {
1253c21e8bcb013a6a562aa6288143368d9dba80fef4Doris Liu            mDrawable = drawable;
1254766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            mSetPtr = nCreateAnimatorSet();
1255766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            // Increment ref count on native AnimatorSet, so it doesn't get released before Java
1256766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            // side is done using it.
1257766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            mSetRefBasePtr = new VirtualRefBasePtr(mSetPtr);
1258766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1259766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
126028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
1261988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu        public void init(@NonNull AnimatorSet set) {
1262766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            if (mInitialized) {
1263766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                // Already initialized
1264766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                throw new UnsupportedOperationException("VectorDrawableAnimator cannot be " +
1265766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                        "re-initialized");
1266766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            }
1267766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            parseAnimatorSet(set, 0);
1268718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu            long vectorDrawableTreePtr = mDrawable.mAnimatedVectorState.mVectorDrawable
1269718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu                    .getNativeTree();
1270718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu            nSetVectorDrawableTarget(mSetPtr, vectorDrawableTreePtr);
1271766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            mInitialized = true;
1272d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu            mIsInfinite = set.getTotalDuration() == Animator.DURATION_INFINITE;
1273766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1274766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            // Check reversible.
1275c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu            mIsReversible = true;
1276766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            if (mContainsSequentialAnimators) {
1277766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                mIsReversible = false;
1278766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            } else {
1279766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                // Check if there's any start delay set on child
1280766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                for (int i = 0; i < mStartDelays.size(); i++) {
1281766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    if (mStartDelays.get(i) > 0) {
1282766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                        mIsReversible = false;
1283766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                        return;
1284766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    }
1285766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                }
1286766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            }
1287766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1288766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1289766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        private void parseAnimatorSet(AnimatorSet set, long startTime) {
1290766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            ArrayList<Animator> animators = set.getChildAnimations();
1291766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1292766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            boolean playTogether = set.shouldPlayTogether();
129328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            // Convert AnimatorSet to VectorDrawableAnimatorRT
1294766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            for (int i = 0; i < animators.size(); i++) {
1295766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                Animator animator = animators.get(i);
1296766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                // Here we only support ObjectAnimator
1297766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                if (animator instanceof AnimatorSet) {
1298766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    parseAnimatorSet((AnimatorSet) animator, startTime);
1299766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                } else if (animator instanceof ObjectAnimator) {
1300766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    createRTAnimator((ObjectAnimator) animator, startTime);
1301766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                } // ignore ValueAnimators and others because they don't directly modify VD
1302766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                  // therefore will be useless to AVD.
1303766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1304766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                if (!playTogether) {
1305766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    // Assume not play together means play sequentially
1306766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    startTime += animator.getTotalDuration();
1307766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    mContainsSequentialAnimators = true;
1308766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                }
1309766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            }
1310766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1311766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1312766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        // TODO: This method reads animation data from already parsed Animators. We need to move
1313766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        // this step further up the chain in the parser to avoid the detour.
1314766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        private void createRTAnimator(ObjectAnimator animator, long startTime) {
1315766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            PropertyValuesHolder[] values = animator.getValues();
1316766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            Object target = animator.getTarget();
1317766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            if (target instanceof VectorDrawable.VGroup) {
1318766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                createRTAnimatorForGroup(values, animator, (VectorDrawable.VGroup) target,
1319766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                        startTime);
1320766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            } else if (target instanceof VectorDrawable.VPath) {
1321766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                for (int i = 0; i < values.length; i++) {
1322766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    values[i].getPropertyValues(mTmpValues);
1323766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    if (mTmpValues.endValue instanceof PathParser.PathData &&
1324766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                            mTmpValues.propertyName.equals("pathData")) {
1325766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                        createRTAnimatorForPath(animator, (VectorDrawable.VPath) target,
1326766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                                startTime);
1327766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    }  else if (target instanceof VectorDrawable.VFullPath) {
1328766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                        createRTAnimatorForFullPath(animator, (VectorDrawable.VFullPath) target,
1329766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                                startTime);
1330a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu                    } else if (!mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) {
1331766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                        throw new IllegalArgumentException("ClipPath only supports PathData " +
1332766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                                "property");
1333766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    }
1334766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                }
1335766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            } else if (target instanceof VectorDrawable.VectorDrawableState) {
1336766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                createRTAnimatorForRootGroup(values, animator,
1337766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                        (VectorDrawable.VectorDrawableState) target, startTime);
1338766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            }
1339766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1340766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1341766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        private void createRTAnimatorForGroup(PropertyValuesHolder[] values,
1342766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                ObjectAnimator animator, VectorDrawable.VGroup target,
1343766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                long startTime) {
1344766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1345766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            long nativePtr = target.getNativePtr();
1346766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            int propertyId;
1347766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            for (int i = 0; i < values.length; i++) {
1348766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                // TODO: We need to support the rare case in AVD where no start value is provided
1349766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                values[i].getPropertyValues(mTmpValues);
1350766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                propertyId = VectorDrawable.VGroup.getPropertyIndex(mTmpValues.propertyName);
1351766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                if (mTmpValues.type != Float.class && mTmpValues.type != float.class) {
1352766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    if (DBG_ANIMATION_VECTOR_DRAWABLE) {
1353766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                        Log.e(LOGTAG, "Unsupported type: " +
1354766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                                mTmpValues.type + ". Only float value is supported for Groups.");
1355766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    }
1356766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    continue;
1357766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                }
1358766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                if (propertyId < 0) {
1359766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    if (DBG_ANIMATION_VECTOR_DRAWABLE) {
1360766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                        Log.e(LOGTAG, "Unsupported property: " +
1361766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                                mTmpValues.propertyName + " for Vector Drawable Group");
1362766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    }
1363766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    continue;
1364766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                }
1365766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                long propertyPtr = nCreateGroupPropertyHolder(nativePtr, propertyId,
1366766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                        (Float) mTmpValues.startValue, (Float) mTmpValues.endValue);
1367766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                if (mTmpValues.dataSource != null) {
1368c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                    float[] dataPoints = createFloatDataPoints(mTmpValues.dataSource,
1369c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                            animator.getDuration());
1370766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length);
1371766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                }
1372766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                createNativeChildAnimator(propertyPtr, startTime, animator);
1373766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            }
1374766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1375766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        private void createRTAnimatorForPath( ObjectAnimator animator, VectorDrawable.VPath target,
1376766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                long startTime) {
1377766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1378766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            long nativePtr = target.getNativePtr();
1379766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            long startPathDataPtr = ((PathParser.PathData) mTmpValues.startValue)
1380766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    .getNativePtr();
1381766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            long endPathDataPtr = ((PathParser.PathData) mTmpValues.endValue)
1382766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    .getNativePtr();
1383766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            long propertyPtr = nCreatePathDataPropertyHolder(nativePtr, startPathDataPtr,
1384766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    endPathDataPtr);
1385766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            createNativeChildAnimator(propertyPtr, startTime, animator);
1386766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1387766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1388766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        private void createRTAnimatorForFullPath(ObjectAnimator animator,
1389766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                VectorDrawable.VFullPath target, long startTime) {
1390766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1391766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            int propertyId = target.getPropertyIndex(mTmpValues.propertyName);
1392766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            long propertyPtr;
1393766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            long nativePtr = target.getNativePtr();
1394766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            if (mTmpValues.type == Float.class || mTmpValues.type == float.class) {
1395766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                if (propertyId < 0) {
1396a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu                    if (mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) {
1397ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu                        return;
1398ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu                    } else {
1399ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu                        throw new IllegalArgumentException("Property: " + mTmpValues.propertyName
1400ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu                                + " is not supported for FullPath");
1401ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu                    }
1402766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                }
1403766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                propertyPtr = nCreatePathPropertyHolder(nativePtr, propertyId,
1404766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                        (Float) mTmpValues.startValue, (Float) mTmpValues.endValue);
1405c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                if (mTmpValues.dataSource != null) {
1406c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                    // Pass keyframe data to native, if any.
1407c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                    float[] dataPoints = createFloatDataPoints(mTmpValues.dataSource,
1408c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                            animator.getDuration());
1409c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                    nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length);
1410c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                }
1411766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1412766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            } else if (mTmpValues.type == Integer.class || mTmpValues.type == int.class) {
1413766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                propertyPtr = nCreatePathColorPropertyHolder(nativePtr, propertyId,
1414766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                        (Integer) mTmpValues.startValue, (Integer) mTmpValues.endValue);
1415c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                if (mTmpValues.dataSource != null) {
1416c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                    // Pass keyframe data to native, if any.
1417c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                    int[] dataPoints = createIntDataPoints(mTmpValues.dataSource,
1418c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                            animator.getDuration());
1419c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                    nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length);
1420c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                }
1421766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            } else {
1422a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu                if (mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) {
1423ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu                    return;
1424ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu                } else {
1425ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu                    throw new UnsupportedOperationException("Unsupported type: " +
1426ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu                            mTmpValues.type + ". Only float, int or PathData value is " +
1427ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu                            "supported for Paths.");
1428ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu                }
1429766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            }
1430766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            createNativeChildAnimator(propertyPtr, startTime, animator);
1431766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1432766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1433766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        private void createRTAnimatorForRootGroup(PropertyValuesHolder[] values,
1434766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                ObjectAnimator animator, VectorDrawable.VectorDrawableState target,
1435766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                long startTime) {
1436c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            long nativePtr = target.getNativeRenderer();
1437c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            if (!animator.getPropertyName().equals("alpha")) {
1438c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                if (mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) {
1439c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                    return;
1440c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                } else {
1441c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                    throw new UnsupportedOperationException("Only alpha is supported for root "
1442c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                            + "group");
1443766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                }
1444c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            }
1445c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            Float startValue = null;
1446c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            Float endValue = null;
1447c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            for (int i = 0; i < values.length; i++) {
1448c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                values[i].getPropertyValues(mTmpValues);
1449c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                if (mTmpValues.propertyName.equals("alpha")) {
1450c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                    startValue = (Float) mTmpValues.startValue;
1451c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                    endValue = (Float) mTmpValues.endValue;
1452c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                    break;
1453766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                }
1454c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            }
1455c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            if (startValue == null && endValue == null) {
1456c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                if (mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) {
1457c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                    return;
1458c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                } else {
1459c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                    throw new UnsupportedOperationException("No alpha values are specified");
1460766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                }
1461c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            }
1462c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            long propertyPtr = nCreateRootAlphaPropertyHolder(nativePtr, startValue, endValue);
1463c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            if (mTmpValues.dataSource != null) {
1464c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                // Pass keyframe data to native, if any.
1465c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                float[] dataPoints = createFloatDataPoints(mTmpValues.dataSource,
1466c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                        animator.getDuration());
1467c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length);
1468c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            }
1469c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            createNativeChildAnimator(propertyPtr, startTime, animator);
1470c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu        }
1471c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu
1472c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu        /**
1473c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu         * Calculate the amount of frames an animation will run based on duration.
1474c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu         */
1475c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu        private static int getFrameCount(long duration) {
1476c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            long frameIntervalNanos = Choreographer.getInstance().getFrameIntervalNanos();
1477c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            int animIntervalMs = (int) (frameIntervalNanos / TimeUtils.NANOS_PER_MS);
1478c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            int numAnimFrames = (int) Math.ceil(((double) duration) / animIntervalMs);
1479c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            // We need 2 frames of data minimum.
1480c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            numAnimFrames = Math.max(2, numAnimFrames);
1481c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            if (numAnimFrames > MAX_SAMPLE_POINTS) {
1482c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                Log.w("AnimatedVectorDrawable", "Duration for the animation is too long :" +
1483c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                        duration + ", the animation will subsample the keyframe or path data.");
1484c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                numAnimFrames = MAX_SAMPLE_POINTS;
1485c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            }
1486c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            return numAnimFrames;
1487766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1488766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1489766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        // These are the data points that define the value of the animating properties.
1490766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        // e.g. translateX and translateY can animate along a Path, at any fraction in [0, 1]
1491766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        // a point on the path corresponds to the values of translateX and translateY.
1492766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        // TODO: (Optimization) We should pass the path down in native and chop it into segments
1493766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        // in native.
1494c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu        private static float[] createFloatDataPoints(
1495766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                PropertyValuesHolder.PropertyValues.DataSource dataSource, long duration) {
1496c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            int numAnimFrames = getFrameCount(duration);
1497766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            float values[] = new float[numAnimFrames];
1498766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            float lastFrame = numAnimFrames - 1;
1499766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            for (int i = 0; i < numAnimFrames; i++) {
1500766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                float fraction = i / lastFrame;
1501766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                values[i] = (Float) dataSource.getValueAtFraction(fraction);
1502766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            }
1503766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            return values;
1504766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1505766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1506c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu        private static int[] createIntDataPoints(
1507c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                PropertyValuesHolder.PropertyValues.DataSource dataSource, long duration) {
1508c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            int numAnimFrames = getFrameCount(duration);
1509c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            int values[] = new int[numAnimFrames];
1510c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            float lastFrame = numAnimFrames - 1;
1511c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            for (int i = 0; i < numAnimFrames; i++) {
1512c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                float fraction = i / lastFrame;
1513c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu                values[i] = (Integer) dataSource.getValueAtFraction(fraction);
1514c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            }
1515c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu            return values;
1516c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu        }
1517c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu
1518766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        private void createNativeChildAnimator(long propertyPtr, long extraDelay,
1519766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                                               ObjectAnimator animator) {
1520766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            long duration = animator.getDuration();
1521766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            int repeatCount = animator.getRepeatCount();
1522766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            long startDelay = extraDelay + animator.getStartDelay();
1523766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            TimeInterpolator interpolator = animator.getInterpolator();
1524766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            long nativeInterpolator =
1525766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                    RenderNodeAnimatorSetHelper.createNativeInterpolator(interpolator, duration);
1526766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1527766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            startDelay *= ValueAnimator.getDurationScale();
1528766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            duration *= ValueAnimator.getDurationScale();
1529766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1530766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            mStartDelays.add(startDelay);
1531766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            nAddAnimator(mSetPtr, propertyPtr, nativeInterpolator, startDelay, duration,
1532f7167e8f286cff91dec01fdf617bf568f1d100e6Doris Liu                    repeatCount, animator.getRepeatMode());
1533766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1534766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1535766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        /**
1536766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu         * Holds a weak reference to the target that was last seen (through the DisplayListCanvas
1537766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu         * in the last draw call), so that when animator set needs to start, we can add the animator
1538766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu         * to the last seen RenderNode target and start right away.
1539766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu         */
1540766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        protected void recordLastSeenTarget(DisplayListCanvas canvas) {
1541718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu            final RenderNode node = RenderNodeAnimatorSetHelper.getTarget(canvas);
1542718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu            mLastSeenTarget = new WeakReference<RenderNode>(node);
1543718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu            // Add the animator to the list of animators on every draw
1544718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu            if (mInitialized || mPendingAnimationActions.size() > 0) {
1545718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu                if (useTarget(node)) {
1546718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu                    if (DBG_ANIMATION_VECTOR_DRAWABLE) {
1547718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu                        Log.d(LOGTAG, "Target is set in the next frame");
1548718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu                    }
1549718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu                    for (int i = 0; i < mPendingAnimationActions.size(); i++) {
1550718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu                        handlePendingAction(mPendingAnimationActions.get(i));
1551718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu                    }
1552718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu                    mPendingAnimationActions.clear();
1553c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu                }
155444027214d4f2154ebc9265912933bac282be3bb4Doris Liu            }
155544027214d4f2154ebc9265912933bac282be3bb4Doris Liu        }
155644027214d4f2154ebc9265912933bac282be3bb4Doris Liu
155744027214d4f2154ebc9265912933bac282be3bb4Doris Liu        private void handlePendingAction(int pendingAnimationAction) {
155844027214d4f2154ebc9265912933bac282be3bb4Doris Liu            if (pendingAnimationAction == START_ANIMATION) {
155944027214d4f2154ebc9265912933bac282be3bb4Doris Liu                startAnimation();
156044027214d4f2154ebc9265912933bac282be3bb4Doris Liu            } else if (pendingAnimationAction == REVERSE_ANIMATION) {
156144027214d4f2154ebc9265912933bac282be3bb4Doris Liu                reverseAnimation();
156244027214d4f2154ebc9265912933bac282be3bb4Doris Liu            } else if (pendingAnimationAction == RESET_ANIMATION) {
156344027214d4f2154ebc9265912933bac282be3bb4Doris Liu                resetAnimation();
156444027214d4f2154ebc9265912933bac282be3bb4Doris Liu            } else if (pendingAnimationAction == END_ANIMATION) {
156544027214d4f2154ebc9265912933bac282be3bb4Doris Liu                endAnimation();
156644027214d4f2154ebc9265912933bac282be3bb4Doris Liu            } else {
156744027214d4f2154ebc9265912933bac282be3bb4Doris Liu                throw new UnsupportedOperationException("Animation action " +
156844027214d4f2154ebc9265912933bac282be3bb4Doris Liu                        pendingAnimationAction + "is not supported");
1569766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            }
1570766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1571766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1572766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        private boolean useLastSeenTarget() {
15738b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu            if (mLastSeenTarget != null) {
15748b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu                final RenderNode target = mLastSeenTarget.get();
1575718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu                return useTarget(target);
1576718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu            }
1577718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu            return false;
1578718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu        }
1579718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu
1580718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu        private boolean useTarget(RenderNode target) {
1581718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu            if (target != null && target.isAttached()) {
1582718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu                target.registerVectorDrawableAnimator(this);
1583718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu                return true;
1584766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            }
1585766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            return false;
1586766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1587766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1588c21e8bcb013a6a562aa6288143368d9dba80fef4Doris Liu        private void invalidateOwningView() {
1589c21e8bcb013a6a562aa6288143368d9dba80fef4Doris Liu            mDrawable.invalidateSelf();
1590c21e8bcb013a6a562aa6288143368d9dba80fef4Doris Liu        }
1591c21e8bcb013a6a562aa6288143368d9dba80fef4Doris Liu
159244027214d4f2154ebc9265912933bac282be3bb4Doris Liu        private void addPendingAction(int pendingAnimationAction) {
159344027214d4f2154ebc9265912933bac282be3bb4Doris Liu            invalidateOwningView();
159444027214d4f2154ebc9265912933bac282be3bb4Doris Liu            mPendingAnimationActions.add(pendingAnimationAction);
159544027214d4f2154ebc9265912933bac282be3bb4Doris Liu        }
159644027214d4f2154ebc9265912933bac282be3bb4Doris Liu
159728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
1598766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        public void start() {
1599766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            if (!mInitialized) {
1600766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                return;
1601766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            }
1602766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
160344027214d4f2154ebc9265912933bac282be3bb4Doris Liu            if (useLastSeenTarget()) {
160444027214d4f2154ebc9265912933bac282be3bb4Doris Liu                if (DBG_ANIMATION_VECTOR_DRAWABLE) {
160544027214d4f2154ebc9265912933bac282be3bb4Doris Liu                    Log.d(LOGTAG, "Target is set. Starting VDAnimatorSet from java");
160644027214d4f2154ebc9265912933bac282be3bb4Doris Liu                }
160744027214d4f2154ebc9265912933bac282be3bb4Doris Liu                startAnimation();
160844027214d4f2154ebc9265912933bac282be3bb4Doris Liu            } else {
160944027214d4f2154ebc9265912933bac282be3bb4Doris Liu                addPendingAction(START_ANIMATION);
1610766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            }
1611766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1612766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
161328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
1614766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        public void end() {
161544027214d4f2154ebc9265912933bac282be3bb4Doris Liu            if (!mInitialized) {
161644027214d4f2154ebc9265912933bac282be3bb4Doris Liu                return;
161744027214d4f2154ebc9265912933bac282be3bb4Doris Liu            }
161844027214d4f2154ebc9265912933bac282be3bb4Doris Liu
161944027214d4f2154ebc9265912933bac282be3bb4Doris Liu            if (useLastSeenTarget()) {
162044027214d4f2154ebc9265912933bac282be3bb4Doris Liu                endAnimation();
162144027214d4f2154ebc9265912933bac282be3bb4Doris Liu            } else {
162244027214d4f2154ebc9265912933bac282be3bb4Doris Liu                addPendingAction(END_ANIMATION);
1623766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            }
1624766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1625766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
162628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
1627c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu        public void reset() {
162844027214d4f2154ebc9265912933bac282be3bb4Doris Liu            if (!mInitialized) {
162944027214d4f2154ebc9265912933bac282be3bb4Doris Liu                return;
163044027214d4f2154ebc9265912933bac282be3bb4Doris Liu            }
163144027214d4f2154ebc9265912933bac282be3bb4Doris Liu
163244027214d4f2154ebc9265912933bac282be3bb4Doris Liu            if (useLastSeenTarget()) {
163344027214d4f2154ebc9265912933bac282be3bb4Doris Liu                resetAnimation();
163444027214d4f2154ebc9265912933bac282be3bb4Doris Liu            } else {
163544027214d4f2154ebc9265912933bac282be3bb4Doris Liu                addPendingAction(RESET_ANIMATION);
1636766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            }
1637766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1638766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1639766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        // Current (imperfect) Java AnimatorSet cannot be reversed when the set contains sequential
1640766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        // animators or when the animator set has a start delay
164128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
164228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        public void reverse() {
1643c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu            if (!mIsReversible || !mInitialized) {
1644c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu                return;
1645c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu            }
164644027214d4f2154ebc9265912933bac282be3bb4Doris Liu            if (useLastSeenTarget()) {
164744027214d4f2154ebc9265912933bac282be3bb4Doris Liu                if (DBG_ANIMATION_VECTOR_DRAWABLE) {
164844027214d4f2154ebc9265912933bac282be3bb4Doris Liu                    Log.d(LOGTAG, "Target is set. Reversing VDAnimatorSet from java");
164944027214d4f2154ebc9265912933bac282be3bb4Doris Liu                }
165044027214d4f2154ebc9265912933bac282be3bb4Doris Liu                reverseAnimation();
165144027214d4f2154ebc9265912933bac282be3bb4Doris Liu            } else {
165244027214d4f2154ebc9265912933bac282be3bb4Doris Liu                addPendingAction(REVERSE_ANIMATION);
1653766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            }
165444027214d4f2154ebc9265912933bac282be3bb4Doris Liu        }
165544027214d4f2154ebc9265912933bac282be3bb4Doris Liu
165644027214d4f2154ebc9265912933bac282be3bb4Doris Liu        // This should only be called after animator has been added to the RenderNode target.
165744027214d4f2154ebc9265912933bac282be3bb4Doris Liu        private void startAnimation() {
1658c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu            if (DBG_ANIMATION_VECTOR_DRAWABLE) {
165944027214d4f2154ebc9265912933bac282be3bb4Doris Liu                Log.w(LOGTAG, "starting animation on VD: " +
166044027214d4f2154ebc9265912933bac282be3bb4Doris Liu                        ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
166144027214d4f2154ebc9265912933bac282be3bb4Doris Liu                                mDrawable.getConstantState()).mVectorDrawable.getConstantState())
166244027214d4f2154ebc9265912933bac282be3bb4Doris Liu                                .mRootName);
1663c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu            }
1664c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu            mStarted = true;
166544027214d4f2154ebc9265912933bac282be3bb4Doris Liu            nStart(mSetPtr, this, ++mLastListenerId);
166644027214d4f2154ebc9265912933bac282be3bb4Doris Liu            invalidateOwningView();
166744027214d4f2154ebc9265912933bac282be3bb4Doris Liu            if (mListener != null) {
166844027214d4f2154ebc9265912933bac282be3bb4Doris Liu                mListener.onAnimationStart(null);
166944027214d4f2154ebc9265912933bac282be3bb4Doris Liu            }
167044027214d4f2154ebc9265912933bac282be3bb4Doris Liu        }
167144027214d4f2154ebc9265912933bac282be3bb4Doris Liu
167244027214d4f2154ebc9265912933bac282be3bb4Doris Liu        // This should only be called after animator has been added to the RenderNode target.
167344027214d4f2154ebc9265912933bac282be3bb4Doris Liu        private void endAnimation() {
167444027214d4f2154ebc9265912933bac282be3bb4Doris Liu            if (DBG_ANIMATION_VECTOR_DRAWABLE) {
167544027214d4f2154ebc9265912933bac282be3bb4Doris Liu                Log.w(LOGTAG, "ending animation on VD: " +
167644027214d4f2154ebc9265912933bac282be3bb4Doris Liu                        ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
167744027214d4f2154ebc9265912933bac282be3bb4Doris Liu                                mDrawable.getConstantState()).mVectorDrawable.getConstantState())
167844027214d4f2154ebc9265912933bac282be3bb4Doris Liu                                .mRootName);
167944027214d4f2154ebc9265912933bac282be3bb4Doris Liu            }
168044027214d4f2154ebc9265912933bac282be3bb4Doris Liu            nEnd(mSetPtr);
168144027214d4f2154ebc9265912933bac282be3bb4Doris Liu            invalidateOwningView();
168244027214d4f2154ebc9265912933bac282be3bb4Doris Liu        }
168344027214d4f2154ebc9265912933bac282be3bb4Doris Liu
168444027214d4f2154ebc9265912933bac282be3bb4Doris Liu        // This should only be called after animator has been added to the RenderNode target.
168544027214d4f2154ebc9265912933bac282be3bb4Doris Liu        private void resetAnimation() {
168644027214d4f2154ebc9265912933bac282be3bb4Doris Liu            nReset(mSetPtr);
168744027214d4f2154ebc9265912933bac282be3bb4Doris Liu            invalidateOwningView();
168844027214d4f2154ebc9265912933bac282be3bb4Doris Liu        }
168944027214d4f2154ebc9265912933bac282be3bb4Doris Liu
169044027214d4f2154ebc9265912933bac282be3bb4Doris Liu        // This should only be called after animator has been added to the RenderNode target.
169144027214d4f2154ebc9265912933bac282be3bb4Doris Liu        private void reverseAnimation() {
169244027214d4f2154ebc9265912933bac282be3bb4Doris Liu            mStarted = true;
1693c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu            nReverse(mSetPtr, this, ++mLastListenerId);
1694c21e8bcb013a6a562aa6288143368d9dba80fef4Doris Liu            invalidateOwningView();
1695c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu            if (mListener != null) {
1696c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu                mListener.onAnimationStart(null);
1697c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu            }
1698766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1699766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1700766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        public long getAnimatorNativePtr() {
1701766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            return mSetPtr;
1702766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1703766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
170428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
170528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        public boolean canReverse() {
1706766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            return mIsReversible;
1707766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1708766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
170928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
171028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        public boolean isStarted() {
1711766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            return mStarted;
1712766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1713766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
171428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
171528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        public boolean isRunning() {
1716766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            if (!mInitialized) {
1717766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                return false;
1718766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            }
1719766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            return mStarted;
1720766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1721766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
172228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
172328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        public void setListener(AnimatorListener listener) {
1724766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            mListener = listener;
1725766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1726766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
172728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
172828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        public void removeListener(AnimatorListener listener) {
1729766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            mListener = null;
1730766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1731766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
173228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        @Override
173328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        public void onDraw(Canvas canvas) {
173428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            if (canvas.isHardwareAccelerated()) {
173528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu                recordLastSeenTarget((DisplayListCanvas) canvas);
173628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu            }
173728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        }
173828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu
1739d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        @Override
1740d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        public boolean isInfinite() {
1741d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu            return mIsInfinite;
1742d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        }
1743d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu
1744d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        @Override
1745d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        public void pause() {
1746d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu            // TODO: Implement pause for Animator On RT.
1747d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        }
1748d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu
1749d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        @Override
1750d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        public void resume() {
1751d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu            // TODO: Implement resume for Animator On RT.
1752d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu        }
1753d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu
1754c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu        private void onAnimationEnd(int listenerId) {
1755c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu            if (listenerId != mLastListenerId) {
1756c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu                return;
1757c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu            }
1758c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu            if (DBG_ANIMATION_VECTOR_DRAWABLE) {
1759c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu                Log.d(LOGTAG, "on finished called from native");
1760c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu            }
1761766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            mStarted = false;
17621d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            // Invalidate in the end of the animation to make sure the data in
17631d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            // RT thread is synced back to UI thread.
17641d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            invalidateOwningView();
1765766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            if (mListener != null) {
1766766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu                mListener.onAnimationEnd(null);
1767766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            }
1768766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1769766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1770766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        // onFinished: should be called from native
177128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu        private static void callOnFinished(VectorDrawableAnimatorRT set, int id) {
1772c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu            set.onAnimationEnd(id);
1773766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        }
1774126df850ce6b5f8a355534eb09235e22995f0116Doris Liu
1775126df850ce6b5f8a355534eb09235e22995f0116Doris Liu        private void transferPendingActions(VectorDrawableAnimator animatorSet) {
1776126df850ce6b5f8a355534eb09235e22995f0116Doris Liu            for (int i = 0; i < mPendingAnimationActions.size(); i++) {
1777126df850ce6b5f8a355534eb09235e22995f0116Doris Liu                int pendingAction = mPendingAnimationActions.get(i);
1778126df850ce6b5f8a355534eb09235e22995f0116Doris Liu                if (pendingAction == START_ANIMATION) {
1779126df850ce6b5f8a355534eb09235e22995f0116Doris Liu                    animatorSet.start();
1780126df850ce6b5f8a355534eb09235e22995f0116Doris Liu                } else if (pendingAction == END_ANIMATION) {
1781126df850ce6b5f8a355534eb09235e22995f0116Doris Liu                    animatorSet.end();
1782126df850ce6b5f8a355534eb09235e22995f0116Doris Liu                } else if (pendingAction == REVERSE_ANIMATION) {
1783126df850ce6b5f8a355534eb09235e22995f0116Doris Liu                    animatorSet.reverse();
1784126df850ce6b5f8a355534eb09235e22995f0116Doris Liu                } else if (pendingAction == RESET_ANIMATION) {
1785126df850ce6b5f8a355534eb09235e22995f0116Doris Liu                    animatorSet.reset();
1786126df850ce6b5f8a355534eb09235e22995f0116Doris Liu                } else {
1787126df850ce6b5f8a355534eb09235e22995f0116Doris Liu                    throw new UnsupportedOperationException("Animation action " +
1788126df850ce6b5f8a355534eb09235e22995f0116Doris Liu                            pendingAction + "is not supported");
1789126df850ce6b5f8a355534eb09235e22995f0116Doris Liu                }
1790126df850ce6b5f8a355534eb09235e22995f0116Doris Liu            }
1791126df850ce6b5f8a355534eb09235e22995f0116Doris Liu            mPendingAnimationActions.clear();
1792126df850ce6b5f8a355534eb09235e22995f0116Doris Liu        }
1793766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    }
1794766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1795766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    private static native long nCreateAnimatorSet();
1796718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu    private static native void nSetVectorDrawableTarget(long animatorPtr, long vectorDrawablePtr);
1797766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    private static native void nAddAnimator(long setPtr, long propertyValuesHolder,
1798f7167e8f286cff91dec01fdf617bf568f1d100e6Doris Liu            long nativeInterpolator, long startDelay, long duration, int repeatCount,
1799f7167e8f286cff91dec01fdf617bf568f1d100e6Doris Liu            int repeatMode);
1800299659ddb7e0c34ca094abe485bcd0989727fc07John Reck    private static native void nSetPropertyHolderData(long nativePtr, float[] data, int length);
1801299659ddb7e0c34ca094abe485bcd0989727fc07John Reck    private static native void nSetPropertyHolderData(long nativePtr, int[] data, int length);
1802299659ddb7e0c34ca094abe485bcd0989727fc07John Reck    private static native void nStart(long animatorSetPtr, VectorDrawableAnimatorRT set, int id);
1803299659ddb7e0c34ca094abe485bcd0989727fc07John Reck    private static native void nReverse(long animatorSetPtr, VectorDrawableAnimatorRT set, int id);
1804766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
1805299659ddb7e0c34ca094abe485bcd0989727fc07John Reck    // ------------- @FastNative -------------------
1806299659ddb7e0c34ca094abe485bcd0989727fc07John Reck
1807299659ddb7e0c34ca094abe485bcd0989727fc07John Reck    @FastNative
1808766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    private static native long nCreateGroupPropertyHolder(long nativePtr, int propertyId,
1809766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            float startValue, float endValue);
1810299659ddb7e0c34ca094abe485bcd0989727fc07John Reck    @FastNative
1811766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    private static native long nCreatePathDataPropertyHolder(long nativePtr, long startValuePtr,
1812766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            long endValuePtr);
1813299659ddb7e0c34ca094abe485bcd0989727fc07John Reck    @FastNative
1814766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    private static native long nCreatePathColorPropertyHolder(long nativePtr, int propertyId,
1815766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            int startValue, int endValue);
1816299659ddb7e0c34ca094abe485bcd0989727fc07John Reck    @FastNative
1817766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    private static native long nCreatePathPropertyHolder(long nativePtr, int propertyId,
1818766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            float startValue, float endValue);
1819299659ddb7e0c34ca094abe485bcd0989727fc07John Reck    @FastNative
1820766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    private static native long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue,
1821766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu            float endValue);
1822299659ddb7e0c34ca094abe485bcd0989727fc07John Reck    @FastNative
1823766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    private static native void nEnd(long animatorSetPtr);
1824299659ddb7e0c34ca094abe485bcd0989727fc07John Reck    @FastNative
1825766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    private static native void nReset(long animatorSetPtr);
1826f276acd98457bcaabc9e79a17a736b3b484f005eDoris Liu}
1827