13618d30f8ab6018025b11869676b309c3b4961cfDoris Liu/* 23618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * Copyright (C) 2015 The Android Open Source Project 33618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * 43618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * Licensed under the Apache License, Version 2.0 (the "License"); 53618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * you may not use this file except in compliance with the License. 63618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * You may obtain a copy of the License at 73618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * 83618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * http://www.apache.org/licenses/LICENSE-2.0 93618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * 103618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * Unless required by applicable law or agreed to in writing, software 113618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * distributed under the License is distributed on an "AS IS" BASIS, 123618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * See the License for the specific language governing permissions and 143618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * limitations under the License. 153618d30f8ab6018025b11869676b309c3b4961cfDoris Liu */ 163618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 173618d30f8ab6018025b11869676b309c3b4961cfDoris Liupackage android.animation; 183618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 193618d30f8ab6018025b11869676b309c3b4961cfDoris Liuimport android.os.SystemClock; 203618d30f8ab6018025b11869676b309c3b4961cfDoris Liuimport android.util.ArrayMap; 213618d30f8ab6018025b11869676b309c3b4961cfDoris Liuimport android.view.Choreographer; 223618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 233618d30f8ab6018025b11869676b309c3b4961cfDoris Liuimport java.util.ArrayList; 243618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 253618d30f8ab6018025b11869676b309c3b4961cfDoris Liu/** 263618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * This custom, static handler handles the timing pulse that is shared by all active 273618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * ValueAnimators. This approach ensures that the setting of animation values will happen on the 283618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * same thread that animations start on, and that all animations will share the same times for 293618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * calculating their values, which makes synchronizing animations possible. 303618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * 313618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * The handler uses the Choreographer by default for doing periodic callbacks. A custom 32f310e889392be5198004c6c6611b2b50ae3344b8Doris Liu * AnimationFrameCallbackProvider can be set on the handler to provide timing pulse that 333618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * may be independent of UI frame update. This could be useful in testing. 343618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * 353618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * @hide 363618d30f8ab6018025b11869676b309c3b4961cfDoris Liu */ 373618d30f8ab6018025b11869676b309c3b4961cfDoris Liupublic class AnimationHandler { 383618d30f8ab6018025b11869676b309c3b4961cfDoris Liu /** 393618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * Internal per-thread collections used to avoid set collisions as animations start and end 403618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * while being processed. 413618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * @hide 423618d30f8ab6018025b11869676b309c3b4961cfDoris Liu */ 433618d30f8ab6018025b11869676b309c3b4961cfDoris Liu private final ArrayMap<AnimationFrameCallback, Long> mDelayedCallbackStartTime = 443618d30f8ab6018025b11869676b309c3b4961cfDoris Liu new ArrayMap<>(); 453618d30f8ab6018025b11869676b309c3b4961cfDoris Liu private final ArrayList<AnimationFrameCallback> mAnimationCallbacks = 463618d30f8ab6018025b11869676b309c3b4961cfDoris Liu new ArrayList<>(); 473618d30f8ab6018025b11869676b309c3b4961cfDoris Liu private final ArrayList<AnimationFrameCallback> mCommitCallbacks = 483618d30f8ab6018025b11869676b309c3b4961cfDoris Liu new ArrayList<>(); 493618d30f8ab6018025b11869676b309c3b4961cfDoris Liu private AnimationFrameCallbackProvider mProvider; 503618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 513618d30f8ab6018025b11869676b309c3b4961cfDoris Liu private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() { 523618d30f8ab6018025b11869676b309c3b4961cfDoris Liu @Override 533618d30f8ab6018025b11869676b309c3b4961cfDoris Liu public void doFrame(long frameTimeNanos) { 543618d30f8ab6018025b11869676b309c3b4961cfDoris Liu doAnimationFrame(getProvider().getFrameTime()); 553618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (mAnimationCallbacks.size() > 0) { 563618d30f8ab6018025b11869676b309c3b4961cfDoris Liu getProvider().postFrameCallback(this); 573618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 583618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 593618d30f8ab6018025b11869676b309c3b4961cfDoris Liu }; 603618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 613618d30f8ab6018025b11869676b309c3b4961cfDoris Liu public final static ThreadLocal<AnimationHandler> sAnimatorHandler = new ThreadLocal<>(); 623618d30f8ab6018025b11869676b309c3b4961cfDoris Liu private boolean mListDirty = false; 633618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 643618d30f8ab6018025b11869676b309c3b4961cfDoris Liu public static AnimationHandler getInstance() { 653618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (sAnimatorHandler.get() == null) { 663618d30f8ab6018025b11869676b309c3b4961cfDoris Liu sAnimatorHandler.set(new AnimationHandler()); 673618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 683618d30f8ab6018025b11869676b309c3b4961cfDoris Liu return sAnimatorHandler.get(); 693618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 703618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 713618d30f8ab6018025b11869676b309c3b4961cfDoris Liu /** 723618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * By default, the Choreographer is used to provide timing for frame callbacks. A custom 733618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * provider can be used here to provide different timing pulse. 743618d30f8ab6018025b11869676b309c3b4961cfDoris Liu */ 753618d30f8ab6018025b11869676b309c3b4961cfDoris Liu public void setProvider(AnimationFrameCallbackProvider provider) { 763618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (provider == null) { 773618d30f8ab6018025b11869676b309c3b4961cfDoris Liu mProvider = new MyFrameCallbackProvider(); 783618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } else { 793618d30f8ab6018025b11869676b309c3b4961cfDoris Liu mProvider = provider; 803618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 813618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 823618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 833618d30f8ab6018025b11869676b309c3b4961cfDoris Liu private AnimationFrameCallbackProvider getProvider() { 843618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (mProvider == null) { 853618d30f8ab6018025b11869676b309c3b4961cfDoris Liu mProvider = new MyFrameCallbackProvider(); 863618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 873618d30f8ab6018025b11869676b309c3b4961cfDoris Liu return mProvider; 883618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 893618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 903618d30f8ab6018025b11869676b309c3b4961cfDoris Liu /** 913618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * Register to get a callback on the next frame after the delay. 923618d30f8ab6018025b11869676b309c3b4961cfDoris Liu */ 933618d30f8ab6018025b11869676b309c3b4961cfDoris Liu public void addAnimationFrameCallback(final AnimationFrameCallback callback, long delay) { 943618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (mAnimationCallbacks.size() == 0) { 953618d30f8ab6018025b11869676b309c3b4961cfDoris Liu getProvider().postFrameCallback(mFrameCallback); 963618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 973618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (!mAnimationCallbacks.contains(callback)) { 983618d30f8ab6018025b11869676b309c3b4961cfDoris Liu mAnimationCallbacks.add(callback); 993618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1003618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 1013618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (delay > 0) { 1023618d30f8ab6018025b11869676b309c3b4961cfDoris Liu mDelayedCallbackStartTime.put(callback, (SystemClock.uptimeMillis() + delay)); 1033618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1043618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1053618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 1063618d30f8ab6018025b11869676b309c3b4961cfDoris Liu /** 1073618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * Register to get a one shot callback for frame commit timing. Frame commit timing is the 1083618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * time *after* traversals are done, as opposed to the animation frame timing, which is 1093618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * before any traversals. This timing can be used to adjust the start time of an animation 1103618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * when expensive traversals create big delta between the animation frame timing and the time 1113618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * that animation is first shown on screen. 1123618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * 1133618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * Note this should only be called when the animation has already registered to receive 1143618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * animation frame callbacks. This callback will be guaranteed to happen *after* the next 1153618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * animation frame callback. 1163618d30f8ab6018025b11869676b309c3b4961cfDoris Liu */ 1173618d30f8ab6018025b11869676b309c3b4961cfDoris Liu public void addOneShotCommitCallback(final AnimationFrameCallback callback) { 1183618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (!mCommitCallbacks.contains(callback)) { 1193618d30f8ab6018025b11869676b309c3b4961cfDoris Liu mCommitCallbacks.add(callback); 1203618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1213618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1223618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 1233618d30f8ab6018025b11869676b309c3b4961cfDoris Liu /** 1243618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * Removes the given callback from the list, so it will no longer be called for frame related 1253618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * timing. 1263618d30f8ab6018025b11869676b309c3b4961cfDoris Liu */ 1273618d30f8ab6018025b11869676b309c3b4961cfDoris Liu public void removeCallback(AnimationFrameCallback callback) { 1283618d30f8ab6018025b11869676b309c3b4961cfDoris Liu mCommitCallbacks.remove(callback); 1293618d30f8ab6018025b11869676b309c3b4961cfDoris Liu mDelayedCallbackStartTime.remove(callback); 1303618d30f8ab6018025b11869676b309c3b4961cfDoris Liu int id = mAnimationCallbacks.indexOf(callback); 1313618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (id >= 0) { 1323618d30f8ab6018025b11869676b309c3b4961cfDoris Liu mAnimationCallbacks.set(id, null); 1333618d30f8ab6018025b11869676b309c3b4961cfDoris Liu mListDirty = true; 1343618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1353618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1363618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 1373618d30f8ab6018025b11869676b309c3b4961cfDoris Liu private void doAnimationFrame(long frameTime) { 1383618d30f8ab6018025b11869676b309c3b4961cfDoris Liu int size = mAnimationCallbacks.size(); 1393618d30f8ab6018025b11869676b309c3b4961cfDoris Liu long currentTime = SystemClock.uptimeMillis(); 1403618d30f8ab6018025b11869676b309c3b4961cfDoris Liu for (int i = 0; i < size; i++) { 1413618d30f8ab6018025b11869676b309c3b4961cfDoris Liu final AnimationFrameCallback callback = mAnimationCallbacks.get(i); 1423618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (callback == null) { 1433618d30f8ab6018025b11869676b309c3b4961cfDoris Liu continue; 1443618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1453618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (isCallbackDue(callback, currentTime)) { 1463618d30f8ab6018025b11869676b309c3b4961cfDoris Liu callback.doAnimationFrame(frameTime); 1473618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (mCommitCallbacks.contains(callback)) { 1483618d30f8ab6018025b11869676b309c3b4961cfDoris Liu getProvider().postCommitCallback(new Runnable() { 1493618d30f8ab6018025b11869676b309c3b4961cfDoris Liu @Override 1503618d30f8ab6018025b11869676b309c3b4961cfDoris Liu public void run() { 1513618d30f8ab6018025b11869676b309c3b4961cfDoris Liu commitAnimationFrame(callback, getProvider().getFrameTime()); 1523618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1533618d30f8ab6018025b11869676b309c3b4961cfDoris Liu }); 1543618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1553618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1563618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1573618d30f8ab6018025b11869676b309c3b4961cfDoris Liu cleanUpList(); 1583618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1593618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 1603618d30f8ab6018025b11869676b309c3b4961cfDoris Liu private void commitAnimationFrame(AnimationFrameCallback callback, long frameTime) { 1613618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (!mDelayedCallbackStartTime.containsKey(callback) && 1623618d30f8ab6018025b11869676b309c3b4961cfDoris Liu mCommitCallbacks.contains(callback)) { 1633618d30f8ab6018025b11869676b309c3b4961cfDoris Liu callback.commitAnimationFrame(frameTime); 1643618d30f8ab6018025b11869676b309c3b4961cfDoris Liu mCommitCallbacks.remove(callback); 1653618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1663618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1673618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 1683618d30f8ab6018025b11869676b309c3b4961cfDoris Liu /** 1693618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * Remove the callbacks from mDelayedCallbackStartTime once they have passed the initial delay 1703618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * so that they can start getting frame callbacks. 1713618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * 1723618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * @return true if they have passed the initial delay or have no delay, false otherwise. 1733618d30f8ab6018025b11869676b309c3b4961cfDoris Liu */ 1743618d30f8ab6018025b11869676b309c3b4961cfDoris Liu private boolean isCallbackDue(AnimationFrameCallback callback, long currentTime) { 1753618d30f8ab6018025b11869676b309c3b4961cfDoris Liu Long startTime = mDelayedCallbackStartTime.get(callback); 1763618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (startTime == null) { 1773618d30f8ab6018025b11869676b309c3b4961cfDoris Liu return true; 1783618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1793618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (startTime < currentTime) { 1803618d30f8ab6018025b11869676b309c3b4961cfDoris Liu mDelayedCallbackStartTime.remove(callback); 1813618d30f8ab6018025b11869676b309c3b4961cfDoris Liu return true; 1823618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1833618d30f8ab6018025b11869676b309c3b4961cfDoris Liu return false; 1843618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1853618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 1863618d30f8ab6018025b11869676b309c3b4961cfDoris Liu /** 1873618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * Return the number of callbacks that have registered for frame callbacks. 1883618d30f8ab6018025b11869676b309c3b4961cfDoris Liu */ 1893618d30f8ab6018025b11869676b309c3b4961cfDoris Liu public static int getAnimationCount() { 1903618d30f8ab6018025b11869676b309c3b4961cfDoris Liu AnimationHandler handler = sAnimatorHandler.get(); 1913618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (handler == null) { 1923618d30f8ab6018025b11869676b309c3b4961cfDoris Liu return 0; 1933618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1943618d30f8ab6018025b11869676b309c3b4961cfDoris Liu return handler.getCallbackSize(); 1953618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 1963618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 1973618d30f8ab6018025b11869676b309c3b4961cfDoris Liu public static void setFrameDelay(long delay) { 1983618d30f8ab6018025b11869676b309c3b4961cfDoris Liu getInstance().getProvider().setFrameDelay(delay); 1993618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 2003618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 2013618d30f8ab6018025b11869676b309c3b4961cfDoris Liu public static long getFrameDelay() { 2023618d30f8ab6018025b11869676b309c3b4961cfDoris Liu return getInstance().getProvider().getFrameDelay(); 2033618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 2043618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 2053618d30f8ab6018025b11869676b309c3b4961cfDoris Liu void autoCancelBasedOn(ObjectAnimator objectAnimator) { 2063618d30f8ab6018025b11869676b309c3b4961cfDoris Liu for (int i = mAnimationCallbacks.size() - 1; i >= 0; i--) { 2073618d30f8ab6018025b11869676b309c3b4961cfDoris Liu AnimationFrameCallback cb = mAnimationCallbacks.get(i); 2083618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (cb == null) { 2093618d30f8ab6018025b11869676b309c3b4961cfDoris Liu continue; 2103618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 2113618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (objectAnimator.shouldAutoCancel(cb)) { 2123618d30f8ab6018025b11869676b309c3b4961cfDoris Liu ((Animator) mAnimationCallbacks.get(i)).cancel(); 2133618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 2143618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 2153618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 2163618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 2173618d30f8ab6018025b11869676b309c3b4961cfDoris Liu private void cleanUpList() { 2183618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (mListDirty) { 2193618d30f8ab6018025b11869676b309c3b4961cfDoris Liu for (int i = mAnimationCallbacks.size() - 1; i >= 0; i--) { 2203618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (mAnimationCallbacks.get(i) == null) { 2213618d30f8ab6018025b11869676b309c3b4961cfDoris Liu mAnimationCallbacks.remove(i); 2223618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 2233618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 2243618d30f8ab6018025b11869676b309c3b4961cfDoris Liu mListDirty = false; 2253618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 2263618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 2273618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 2283618d30f8ab6018025b11869676b309c3b4961cfDoris Liu private int getCallbackSize() { 2293618d30f8ab6018025b11869676b309c3b4961cfDoris Liu int count = 0; 2303618d30f8ab6018025b11869676b309c3b4961cfDoris Liu int size = mAnimationCallbacks.size(); 2313618d30f8ab6018025b11869676b309c3b4961cfDoris Liu for (int i = size - 1; i >= 0; i--) { 2323618d30f8ab6018025b11869676b309c3b4961cfDoris Liu if (mAnimationCallbacks.get(i) != null) { 2333618d30f8ab6018025b11869676b309c3b4961cfDoris Liu count++; 2343618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 2353618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 2363618d30f8ab6018025b11869676b309c3b4961cfDoris Liu return count; 2373618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 2383618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 2393618d30f8ab6018025b11869676b309c3b4961cfDoris Liu /** 2403618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * Default provider of timing pulse that uses Choreographer for frame callbacks. 2413618d30f8ab6018025b11869676b309c3b4961cfDoris Liu */ 2423618d30f8ab6018025b11869676b309c3b4961cfDoris Liu private class MyFrameCallbackProvider implements AnimationFrameCallbackProvider { 2433618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 2443618d30f8ab6018025b11869676b309c3b4961cfDoris Liu final Choreographer mChoreographer = Choreographer.getInstance(); 2453618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 2463618d30f8ab6018025b11869676b309c3b4961cfDoris Liu @Override 2473618d30f8ab6018025b11869676b309c3b4961cfDoris Liu public void postFrameCallback(Choreographer.FrameCallback callback) { 2483618d30f8ab6018025b11869676b309c3b4961cfDoris Liu mChoreographer.postFrameCallback(callback); 2493618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 2503618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 2513618d30f8ab6018025b11869676b309c3b4961cfDoris Liu @Override 2523618d30f8ab6018025b11869676b309c3b4961cfDoris Liu public void postCommitCallback(Runnable runnable) { 2533618d30f8ab6018025b11869676b309c3b4961cfDoris Liu mChoreographer.postCallback(Choreographer.CALLBACK_COMMIT, runnable, null); 2543618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 2553618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 2563618d30f8ab6018025b11869676b309c3b4961cfDoris Liu @Override 2573618d30f8ab6018025b11869676b309c3b4961cfDoris Liu public long getFrameTime() { 2583618d30f8ab6018025b11869676b309c3b4961cfDoris Liu return mChoreographer.getFrameTime(); 2593618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 2603618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 2613618d30f8ab6018025b11869676b309c3b4961cfDoris Liu @Override 2623618d30f8ab6018025b11869676b309c3b4961cfDoris Liu public long getFrameDelay() { 2633618d30f8ab6018025b11869676b309c3b4961cfDoris Liu return Choreographer.getFrameDelay(); 2643618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 2653618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 2663618d30f8ab6018025b11869676b309c3b4961cfDoris Liu @Override 2673618d30f8ab6018025b11869676b309c3b4961cfDoris Liu public void setFrameDelay(long delay) { 2683618d30f8ab6018025b11869676b309c3b4961cfDoris Liu Choreographer.setFrameDelay(delay); 2693618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 2703618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 2713618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 2723618d30f8ab6018025b11869676b309c3b4961cfDoris Liu /** 2733618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * Callbacks that receives notifications for animation timing and frame commit timing. 2743618d30f8ab6018025b11869676b309c3b4961cfDoris Liu */ 2753618d30f8ab6018025b11869676b309c3b4961cfDoris Liu interface AnimationFrameCallback { 2763618d30f8ab6018025b11869676b309c3b4961cfDoris Liu /** 2773618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * Run animation based on the frame time. 2783618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * @param frameTime The frame start time, in the {@link SystemClock#uptimeMillis()} time 2793618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * base. 2803618d30f8ab6018025b11869676b309c3b4961cfDoris Liu */ 2813618d30f8ab6018025b11869676b309c3b4961cfDoris Liu void doAnimationFrame(long frameTime); 2823618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 2833618d30f8ab6018025b11869676b309c3b4961cfDoris Liu /** 2843618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * This notifies the callback of frame commit time. Frame commit time is the time after 2853618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * traversals happen, as opposed to the normal animation frame time that is before 2863618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * traversals. This is used to compensate expensive traversals that happen as the 2873618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * animation starts. When traversals take a long time to complete, the rendering of the 2883618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * initial frame will be delayed (by a long time). But since the startTime of the 2893618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * animation is set before the traversal, by the time of next frame, a lot of time would 2903618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * have passed since startTime was set, the animation will consequently skip a few frames 2913618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * to respect the new frameTime. By having the commit time, we can adjust the start time to 2923618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * when the first frame was drawn (after any expensive traversals) so that no frames 2933618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * will be skipped. 2943618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * 2953618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * @param frameTime The frame time after traversals happen, if any, in the 2963618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * {@link SystemClock#uptimeMillis()} time base. 2973618d30f8ab6018025b11869676b309c3b4961cfDoris Liu */ 2983618d30f8ab6018025b11869676b309c3b4961cfDoris Liu void commitAnimationFrame(long frameTime); 2993618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 3003618d30f8ab6018025b11869676b309c3b4961cfDoris Liu 3013618d30f8ab6018025b11869676b309c3b4961cfDoris Liu /** 3023618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * The intention for having this interface is to increase the testability of ValueAnimator. 3033618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * Specifically, we can have a custom implementation of the interface below and provide 3043618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * timing pulse without using Choreographer. That way we could use any arbitrary interval for 3053618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * our timing pulse in the tests. 3063618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * 3073618d30f8ab6018025b11869676b309c3b4961cfDoris Liu * @hide 3083618d30f8ab6018025b11869676b309c3b4961cfDoris Liu */ 3093618d30f8ab6018025b11869676b309c3b4961cfDoris Liu public interface AnimationFrameCallbackProvider { 3103618d30f8ab6018025b11869676b309c3b4961cfDoris Liu void postFrameCallback(Choreographer.FrameCallback callback); 3113618d30f8ab6018025b11869676b309c3b4961cfDoris Liu void postCommitCallback(Runnable runnable); 3123618d30f8ab6018025b11869676b309c3b4961cfDoris Liu long getFrameTime(); 3133618d30f8ab6018025b11869676b309c3b4961cfDoris Liu long getFrameDelay(); 3143618d30f8ab6018025b11869676b309c3b4961cfDoris Liu void setFrameDelay(long delay); 3153618d30f8ab6018025b11869676b309c3b4961cfDoris Liu } 3163618d30f8ab6018025b11869676b309c3b4961cfDoris Liu} 317