1c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner/* 2c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * Copyright (C) 2014 The Android Open Source Project 3c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * 4c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * Licensed under the Apache License, Version 2.0 (the "License"); 5c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * you may not use this file except in compliance with the License. 6c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * You may obtain a copy of the License at 7c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * 8c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * http://www.apache.org/licenses/LICENSE-2.0 9c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * 10c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * Unless required by applicable law or agreed to in writing, software 11c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * distributed under the License is distributed on an "AS IS" BASIS, 12c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * See the License for the specific language governing permissions and 14c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner * limitations under the License. 15c2c0a61cf5f779b4726f089f28d966c03ccbba54Craig Mautner */ 16594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 17594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautnerpackage com.android.server.wm; 18594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 198ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwaleimport static com.android.server.wm.WindowManagerService.DEBUG_ANIM; 208ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwaleimport static com.android.server.wm.WindowManagerService.DEBUG_LAYERS; 218ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwaleimport static com.android.server.wm.WindowManagerService.SHOW_TRANSACTIONS; 228ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwaleimport static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET; 238ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale 24594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautnerimport android.graphics.Matrix; 25594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautnerimport android.util.Slog; 26a57c695bf2c0f917517ecac8251043716b34f72dDianne Hackbornimport android.util.TimeUtils; 27c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggiimport android.view.Choreographer; 28a91f9e2959ee905f97977a88fe45bde6ffb874b0Craig Mautnerimport android.view.Display; 293866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopianimport android.view.SurfaceControl; 30594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautnerimport android.view.WindowManagerPolicy; 31594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautnerimport android.view.animation.Animation; 32594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautnerimport android.view.animation.Transformation; 33594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 34594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautnerimport java.io.PrintWriter; 35322e40315609acd5a608440bc469d873e09559caCraig Mautnerimport java.util.ArrayList; 36594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 37594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautnerpublic class AppWindowAnimator { 38fbf378c736a973b8edaf1fc4c187d11dc0f5e291Craig Mautner static final String TAG = "AppWindowAnimator"; 39594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 40594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner final AppWindowToken mAppToken; 41594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner final WindowManagerService mService; 42594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner final WindowAnimator mAnimator; 43594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 44594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner boolean animating; 45827e0facfefd0c0033dcfb1747b4fa6f80f9e0e2Jorim Jaggi boolean wasAnimating; 46594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner Animation animation; 47594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner boolean hasTransformation; 48594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner final Transformation transformation = new Transformation(); 49594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 50594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner // Have we been asked to have this token keep the screen frozen? 51594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner // Protect with mAnimator. 52594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner boolean freezingScreen; 53594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 54a57c695bf2c0f917517ecac8251043716b34f72dDianne Hackborn /** 55a57c695bf2c0f917517ecac8251043716b34f72dDianne Hackborn * How long we last kept the screen frozen. 56a57c695bf2c0f917517ecac8251043716b34f72dDianne Hackborn */ 57a57c695bf2c0f917517ecac8251043716b34f72dDianne Hackborn int lastFreezeDuration; 58a57c695bf2c0f917517ecac8251043716b34f72dDianne Hackborn 59594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner // Offset to the window of all layers in the token, for use by 60594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner // AppWindowToken animations. 61594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner int animLayerAdjustment; 62594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 636fbda63e68513ece4409dac845588711ab25c39dCraig Mautner // Propagated from AppWindowToken.allDrawn, to determine when 646fbda63e68513ece4409dac845588711ab25c39dCraig Mautner // the state changes. 656fbda63e68513ece4409dac845588711ab25c39dCraig Mautner boolean allDrawn; 666fbda63e68513ece4409dac845588711ab25c39dCraig Mautner 67ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung // Special surface for thumbnail animation. If deferThumbnailDestruction is enabled, then we 68ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung // will make sure that the thumbnail is destroyed after the other surface is completed. This 69ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung // requires that the duration of the two animations are the same. 703866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian SurfaceControl thumbnail; 71594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner int thumbnailTransactionSeq; 72594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner int thumbnailX; 73594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner int thumbnailY; 74594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner int thumbnailLayer; 75a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung int thumbnailForceAboveLayer; 76594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner Animation thumbnailAnimation; 77594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner final Transformation thumbnailTransformation = new Transformation(); 78a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung // This flag indicates that the destruction of the thumbnail surface is synchronized with 79ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung // another animation, so defer the destruction of this thumbnail surface for a single frame 80ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung // after the secondary animation completes. 81a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung boolean deferThumbnailDestruction; 82ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung // This flag is set if the animator has deferThumbnailDestruction set and has reached the final 83ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung // frame of animation. It will extend the animation by one frame and then clean up afterwards. 84ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung boolean deferFinalFrameCleanup; 85594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 86322e40315609acd5a608440bc469d873e09559caCraig Mautner /** WindowStateAnimator from mAppAnimator.allAppWindows as of last performLayout */ 878ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale ArrayList<WindowStateAnimator> mAllAppWinAnimators = new ArrayList<>(); 888ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale 898ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale /** True if the current animation was transferred from another AppWindowAnimator. 908ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale * See {@link #transferCurrentAnimation}*/ 918ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale boolean usingTransferredAnimation = false; 92322e40315609acd5a608440bc469d873e09559caCraig Mautner 93c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi private boolean mSkipFirstFrame = false; 94c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi 95fbf378c736a973b8edaf1fc4c187d11dc0f5e291Craig Mautner static final Animation sDummyAnimation = new DummyAnimation(); 96fbf378c736a973b8edaf1fc4c187d11dc0f5e291Craig Mautner 97322e40315609acd5a608440bc469d873e09559caCraig Mautner public AppWindowAnimator(final AppWindowToken atoken) { 98594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner mAppToken = atoken; 99322e40315609acd5a608440bc469d873e09559caCraig Mautner mService = atoken.service; 100322e40315609acd5a608440bc469d873e09559caCraig Mautner mAnimator = atoken.mAnimator; 101594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 102594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 103c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi public void setAnimation(Animation anim, int width, int height, boolean skipFirstFrame) { 10472669d18016446d874e4fa1005464e36375124e4Craig Mautner if (WindowManagerService.localLOGV) Slog.v(TAG, "Setting animation in " + mAppToken 10572669d18016446d874e4fa1005464e36375124e4Craig Mautner + ": " + anim + " wxh=" + width + "x" + height 10672669d18016446d874e4fa1005464e36375124e4Craig Mautner + " isVisible=" + mAppToken.isVisible()); 107594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner animation = anim; 108594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner animating = false; 1099339c401cf1a056a3a1caddc648334069e6bd267Craig Mautner if (!anim.isInitialized()) { 1109339c401cf1a056a3a1caddc648334069e6bd267Craig Mautner anim.initialize(width, height, width, height); 1119339c401cf1a056a3a1caddc648334069e6bd267Craig Mautner } 112594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION); 113eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn anim.scaleCurrentDuration(mService.getTransitionAnimationScaleLocked()); 114594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner int zorder = anim.getZAdjustment(); 115594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner int adj = 0; 116594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner if (zorder == Animation.ZORDER_TOP) { 1178ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale adj = TYPE_LAYER_OFFSET; 118594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } else if (zorder == Animation.ZORDER_BOTTOM) { 1198ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale adj = -TYPE_LAYER_OFFSET; 120594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 121594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 122594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner if (animLayerAdjustment != adj) { 123594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner animLayerAdjustment = adj; 124594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner updateLayers(); 125594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 126594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner // Start out animation gone if window is gone, or visible if window is visible. 127594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner transformation.clear(); 12872669d18016446d874e4fa1005464e36375124e4Craig Mautner transformation.setAlpha(mAppToken.isVisible() ? 1 : 0); 129594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner hasTransformation = true; 1301ad99155b37c0cb0b7d95f084a2bff0cbfc8e12dCraig Mautner 131c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi this.mSkipFirstFrame = skipFirstFrame; 132c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi 1331ad99155b37c0cb0b7d95f084a2bff0cbfc8e12dCraig Mautner if (!mAppToken.appFullscreen) { 1341ad99155b37c0cb0b7d95f084a2bff0cbfc8e12dCraig Mautner anim.setBackgroundColor(0); 1351ad99155b37c0cb0b7d95f084a2bff0cbfc8e12dCraig Mautner } 136594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 137594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 138594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner public void setDummyAnimation() { 13972669d18016446d874e4fa1005464e36375124e4Craig Mautner if (WindowManagerService.localLOGV) Slog.v(TAG, "Setting dummy animation in " + mAppToken 14072669d18016446d874e4fa1005464e36375124e4Craig Mautner + " isVisible=" + mAppToken.isVisible()); 1411d961d46d68eb3134e4bd6c3751f9730e9d32f17Craig Mautner animation = sDummyAnimation; 14294ef9df22c5960b74359e1a98e5c210787d382f2Craig Mautner hasTransformation = true; 14394ef9df22c5960b74359e1a98e5c210787d382f2Craig Mautner transformation.clear(); 14472669d18016446d874e4fa1005464e36375124e4Craig Mautner transformation.setAlpha(mAppToken.isVisible() ? 1 : 0); 145594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 146594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 147594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner public void clearAnimation() { 148594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner if (animation != null) { 149594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner animation = null; 150594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner animating = true; 151594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 152ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung clearThumbnail(); 1537636dfbc3331dec0cea374a9540a1f31fb7dbf77Craig Mautner if (mAppToken.deferClearAllDrawn) { 1547636dfbc3331dec0cea374a9540a1f31fb7dbf77Craig Mautner mAppToken.allDrawn = false; 1557636dfbc3331dec0cea374a9540a1f31fb7dbf77Craig Mautner mAppToken.deferClearAllDrawn = false; 1567636dfbc3331dec0cea374a9540a1f31fb7dbf77Craig Mautner } 1578ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale usingTransferredAnimation = false; 158594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 159594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 160378756154fce86b53e91746583bfe15996ef680bJorim Jaggi public boolean isAnimating() { 161378756154fce86b53e91746583bfe15996ef680bJorim Jaggi return animation != null || mAppToken.inPendingTransaction; 162378756154fce86b53e91746583bfe15996ef680bJorim Jaggi } 163378756154fce86b53e91746583bfe15996ef680bJorim Jaggi 164594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner public void clearThumbnail() { 165594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner if (thumbnail != null) { 166594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner thumbnail.destroy(); 167594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner thumbnail = null; 168594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 169ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung deferThumbnailDestruction = false; 170a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung } 171a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung 1728ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale void transferCurrentAnimation( 1738ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale AppWindowAnimator toAppAnimator, WindowStateAnimator transferWinAnimator) { 1748ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale 1758ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale if (animation != null) { 1768ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale toAppAnimator.animation = animation; 1778ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale animation = null; 1788ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale toAppAnimator.animating = animating; 1798ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale toAppAnimator.animLayerAdjustment = animLayerAdjustment; 1808ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale animLayerAdjustment = 0; 1818ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale toAppAnimator.updateLayers(); 1828ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale updateLayers(); 1838ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale toAppAnimator.usingTransferredAnimation = true; 1848ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale } 1858ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale if (transferWinAnimator != null) { 1868ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale mAllAppWinAnimators.remove(transferWinAnimator); 1878ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale toAppAnimator.mAllAppWinAnimators.add(transferWinAnimator); 1888ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale transferWinAnimator.mAppAnimator = toAppAnimator; 1898ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale } 1908ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale } 1918ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale 192594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner void updateLayers() { 1938ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale final int windowCount = mAppToken.allAppWindows.size(); 194594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner final int adj = animLayerAdjustment; 195594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner thumbnailLayer = -1; 1968ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale for (int i = 0; i < windowCount; i++) { 197594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner final WindowState w = mAppToken.allAppWindows.get(i); 198594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner final WindowStateAnimator winAnimator = w.mWinAnimator; 199594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner winAnimator.mAnimLayer = w.mLayer + adj; 200594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner if (winAnimator.mAnimLayer > thumbnailLayer) { 201594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner thumbnailLayer = winAnimator.mAnimLayer; 202594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 2038ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale if (DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": " + winAnimator.mAnimLayer); 204594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner if (w == mService.mInputMethodTarget && !mService.mInputMethodTargetWaitingAnim) { 205594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner mService.setInputMethodAnimLayerAdjustment(adj); 206594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 207968683335e17c06504a11bc2e38a2580f613ea16Craig Mautner if (w == mService.mWallpaperTarget && mService.mLowerWallpaperTarget == null) { 208594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner mService.setWallpaperAnimLayerAdjustmentLocked(adj); 209594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 210594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 211594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 212594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 213594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner private void stepThumbnailAnimation(long currentTime) { 214594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner thumbnailTransformation.clear(); 215594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner thumbnailAnimation.getTransformation(currentTime, thumbnailTransformation); 216594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner thumbnailTransformation.getMatrix().preTranslate(thumbnailX, thumbnailY); 217a91f9e2959ee905f97977a88fe45bde6ffb874b0Craig Mautner 218a91f9e2959ee905f97977a88fe45bde6ffb874b0Craig Mautner ScreenRotationAnimation screenRotationAnimation = 219a91f9e2959ee905f97977a88fe45bde6ffb874b0Craig Mautner mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 220a91f9e2959ee905f97977a88fe45bde6ffb874b0Craig Mautner final boolean screenAnimation = screenRotationAnimation != null 221a91f9e2959ee905f97977a88fe45bde6ffb874b0Craig Mautner && screenRotationAnimation.isAnimating(); 222594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner if (screenAnimation) { 223a91f9e2959ee905f97977a88fe45bde6ffb874b0Craig Mautner thumbnailTransformation.postCompose(screenRotationAnimation.getEnterTransformation()); 224594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 225594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner // cache often used attributes locally 226594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner final float tmpFloats[] = mService.mTmpFloats; 227594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner thumbnailTransformation.getMatrix().getValues(tmpFloats); 2288ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail, 229594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner "thumbnail", "POS " + tmpFloats[Matrix.MTRANS_X] 230594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner + ", " + tmpFloats[Matrix.MTRANS_Y], null); 231594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner thumbnail.setPosition(tmpFloats[Matrix.MTRANS_X], tmpFloats[Matrix.MTRANS_Y]); 2328ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail, 233594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner "thumbnail", "alpha=" + thumbnailTransformation.getAlpha() 234594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner + " layer=" + thumbnailLayer 235594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner + " matrix=[" + tmpFloats[Matrix.MSCALE_X] 236594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner + "," + tmpFloats[Matrix.MSKEW_Y] 237594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner + "][" + tmpFloats[Matrix.MSKEW_X] 238594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner + "," + tmpFloats[Matrix.MSCALE_Y] + "]", null); 239594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner thumbnail.setAlpha(thumbnailTransformation.getAlpha()); 240a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung if (thumbnailForceAboveLayer > 0) { 241a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung thumbnail.setLayer(thumbnailForceAboveLayer + 1); 242a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung } else { 243a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung // The thumbnail is layered below the window immediately above this 244a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung // token's anim layer. 245a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung thumbnail.setLayer(thumbnailLayer + WindowManagerService.WINDOW_LAYER_MULTIPLIER 246a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung - WindowManagerService.LAYER_OFFSET_THUMBNAIL); 247a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung } 248594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner thumbnail.setMatrix(tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y], 249594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]); 250594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 251594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 252594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner private boolean stepAnimation(long currentTime) { 253594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner if (animation == null) { 254594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner return false; 255594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 256594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner transformation.clear(); 257ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung boolean hasMoreFrames = animation.getTransformation(currentTime, transformation); 258ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung if (!hasMoreFrames) { 259ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung if (deferThumbnailDestruction && !deferFinalFrameCleanup) { 260ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung // We are deferring the thumbnail destruction, so extend the animation for one more 261ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung // (dummy) frame before we clean up 262ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung deferFinalFrameCleanup = true; 263ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung hasMoreFrames = true; 264ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung } else { 2658ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale if (false && DEBUG_ANIM) Slog.v(TAG, 2668ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale "Stepped animation in " + mAppToken + ": more=" + hasMoreFrames + 2678ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale ", xform=" + transformation); 268ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung deferFinalFrameCleanup = false; 269ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung animation = null; 270a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung clearThumbnail(); 2718ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale if (DEBUG_ANIM) Slog.v(TAG, 2728ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale "Finished animation in " + mAppToken + " @ " + currentTime); 273a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung } 274594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 275ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung hasTransformation = hasMoreFrames; 276ab79fce2e71b6816b2b88b826ca723b3591f1e26Winson Chung return hasMoreFrames; 277594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 278594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 279c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi private long getStartTimeCorrection() { 280c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi if (mSkipFirstFrame) { 281c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi 282c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi // If the transition is an animation in which the first frame doesn't change the screen 283c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi // contents at all, we can just skip it and start at the second frame. So we shift the 284c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi // start time of the animation forward by minus the frame duration. 285c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi return -Choreographer.getInstance().getFrameIntervalNanos() / TimeUtils.NANOS_PER_MS; 286c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi } else { 287c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi return 0; 288c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi } 289c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi } 290c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi 291594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner // This must be called while inside a transaction. 292f16a281066ed7b524676698f95642c0a550b0b62Wale Ogunwale boolean stepAnimationLocked(long currentTime, final int displayId) { 293594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner if (mService.okToDisplay()) { 294594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner // We will run animations as long as the display isn't frozen. 295594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 296fbf378c736a973b8edaf1fc4c187d11dc0f5e291Craig Mautner if (animation == sDummyAnimation) { 297594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner // This guy is going to animate, but not yet. For now count 298594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner // it as not animating for purposes of scheduling transactions; 299594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner // when it is really time to animate, this will be set to 300594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner // a real animation and the next call will execute normally. 301594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner return false; 302594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 303594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 304594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner if ((mAppToken.allDrawn || animating || mAppToken.startingDisplayed) 305594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner && animation != null) { 306594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner if (!animating) { 3078ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale if (DEBUG_ANIM) Slog.v(TAG, 3088ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale "Starting animation in " + mAppToken + 309eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn " @ " + currentTime + " scale=" 310eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn + mService.getTransitionAnimationScaleLocked() 311594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner + " allDrawn=" + mAppToken.allDrawn + " animating=" + animating); 312c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi long correction = getStartTimeCorrection(); 313c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi animation.setStartTime(currentTime + correction); 314594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner animating = true; 315594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner if (thumbnail != null) { 316594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner thumbnail.show(); 317c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi thumbnailAnimation.setStartTime(currentTime + correction); 318594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 319c554b77b7392b97e0f455d8276b739e16147d6dfJorim Jaggi mSkipFirstFrame = false; 320594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 321594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner if (stepAnimation(currentTime)) { 322594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner // animation isn't over, step any thumbnail and that's 323594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner // it for now. 324594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner if (thumbnail != null) { 325594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner stepThumbnailAnimation(currentTime); 326594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 327594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner return true; 328594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 329594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 330594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } else if (animation != null) { 331594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner // If the display is frozen, and there is a pending animation, 332594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner // clear it and make sure we run the cleanup code. 333594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner animating = true; 334594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner animation = null; 335594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 336594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 337594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner hasTransformation = false; 338594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 3393de422fe4fe903b1370f3f7ee9c7086966e15b28Craig Mautner if (!animating && animation == null) { 340594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner return false; 341594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 342594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 34376a7165719dc3ccce902953f6244e2c2668aa753Craig Mautner mAnimator.setAppLayoutChanges(this, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM, 344f16a281066ed7b524676698f95642c0a550b0b62Wale Ogunwale "AppWindowToken", displayId); 345594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 346594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner clearAnimation(); 347594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner animating = false; 348594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner if (animLayerAdjustment != 0) { 349594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner animLayerAdjustment = 0; 350594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner updateLayers(); 351594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 352594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner if (mService.mInputMethodTarget != null 353594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner && mService.mInputMethodTarget.mAppToken == mAppToken) { 354594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner mService.moveInputMethodWindowsIfNeededLocked(true); 355594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 356594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 3578ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale if (DEBUG_ANIM) Slog.v(TAG, 3588ebc82a63f7e4818bb615cf980b961757c8d6587Wale Ogunwale "Animation done in " + mAppToken 359594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner + ": reportedVisible=" + mAppToken.reportedVisible); 360594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 361594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner transformation.clear(); 362594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 363ec533f6a55cfe3b3fdc43f2cdd2305d952a2437bWale Ogunwale final int numAllAppWinAnimators = mAllAppWinAnimators.size(); 364ec533f6a55cfe3b3fdc43f2cdd2305d952a2437bWale Ogunwale for (int i = 0; i < numAllAppWinAnimators; i++) { 365ec533f6a55cfe3b3fdc43f2cdd2305d952a2437bWale Ogunwale mAllAppWinAnimators.get(i).finishExit(); 366bb742462781a73bb25516067c8fe6311c1c8a93eCraig Mautner } 367a48eadbeb6fa34f27d6db7de51d3c01972ea2ebfWale Ogunwale mService.mAppTransition.notifyAppTransitionFinishedLocked(mAppToken.token); 368594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner return false; 369594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 370594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner 371bec53f7066852c1c5877c51fcd8c55840891d866Craig Mautner boolean showAllWindowsLocked() { 372bec53f7066852c1c5877c51fcd8c55840891d866Craig Mautner boolean isAnimating = false; 373322e40315609acd5a608440bc469d873e09559caCraig Mautner final int NW = mAllAppWinAnimators.size(); 374bec53f7066852c1c5877c51fcd8c55840891d866Craig Mautner for (int i=0; i<NW; i++) { 375322e40315609acd5a608440bc469d873e09559caCraig Mautner WindowStateAnimator winAnimator = mAllAppWinAnimators.get(i); 376fbf378c736a973b8edaf1fc4c187d11dc0f5e291Craig Mautner if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, 377bec53f7066852c1c5877c51fcd8c55840891d866Craig Mautner "performing show on: " + winAnimator); 378bec53f7066852c1c5877c51fcd8c55840891d866Craig Mautner winAnimator.performShowLocked(); 379bec53f7066852c1c5877c51fcd8c55840891d866Craig Mautner isAnimating |= winAnimator.isAnimating(); 380bec53f7066852c1c5877c51fcd8c55840891d866Craig Mautner } 381bec53f7066852c1c5877c51fcd8c55840891d866Craig Mautner return isAnimating; 382bec53f7066852c1c5877c51fcd8c55840891d866Craig Mautner } 383bec53f7066852c1c5877c51fcd8c55840891d866Craig Mautner 384529e744d3131b9ebeb6b33c8030230c29a44ad12Dianne Hackborn void dump(PrintWriter pw, String prefix, boolean dumpAll) { 385529e744d3131b9ebeb6b33c8030230c29a44ad12Dianne Hackborn pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken); 386529e744d3131b9ebeb6b33c8030230c29a44ad12Dianne Hackborn pw.print(prefix); pw.print("mAnimator="); pw.println(mAnimator); 387529e744d3131b9ebeb6b33c8030230c29a44ad12Dianne Hackborn pw.print(prefix); pw.print("freezingScreen="); pw.print(freezingScreen); 388529e744d3131b9ebeb6b33c8030230c29a44ad12Dianne Hackborn pw.print(" allDrawn="); pw.print(allDrawn); 389529e744d3131b9ebeb6b33c8030230c29a44ad12Dianne Hackborn pw.print(" animLayerAdjustment="); pw.println(animLayerAdjustment); 390a57c695bf2c0f917517ecac8251043716b34f72dDianne Hackborn if (lastFreezeDuration != 0) { 391a57c695bf2c0f917517ecac8251043716b34f72dDianne Hackborn pw.print(prefix); pw.print("lastFreezeDuration="); 392a57c695bf2c0f917517ecac8251043716b34f72dDianne Hackborn TimeUtils.formatDuration(lastFreezeDuration, pw); pw.println(); 393a57c695bf2c0f917517ecac8251043716b34f72dDianne Hackborn } 394594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner if (animating || animation != null) { 3959339c401cf1a056a3a1caddc648334069e6bd267Craig Mautner pw.print(prefix); pw.print("animating="); pw.println(animating); 396529e744d3131b9ebeb6b33c8030230c29a44ad12Dianne Hackborn pw.print(prefix); pw.print("animation="); pw.println(animation); 397594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 398594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner if (hasTransformation) { 399594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner pw.print(prefix); pw.print("XForm: "); 400594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner transformation.printShortString(pw); 401594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner pw.println(); 402594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 403594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner if (thumbnail != null) { 404594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner pw.print(prefix); pw.print("thumbnail="); pw.print(thumbnail); 405594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner pw.print(" x="); pw.print(thumbnailX); 406594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner pw.print(" y="); pw.print(thumbnailY); 407594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner pw.print(" layer="); pw.println(thumbnailLayer); 408594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner pw.print(prefix); pw.print("thumbnailAnimation="); pw.println(thumbnailAnimation); 409594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner pw.print(prefix); pw.print("thumbnailTransformation="); 410594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner pw.println(thumbnailTransformation.toShortString()); 411594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 412529e744d3131b9ebeb6b33c8030230c29a44ad12Dianne Hackborn for (int i=0; i<mAllAppWinAnimators.size(); i++) { 413529e744d3131b9ebeb6b33c8030230c29a44ad12Dianne Hackborn WindowStateAnimator wanim = mAllAppWinAnimators.get(i); 414529e744d3131b9ebeb6b33c8030230c29a44ad12Dianne Hackborn pw.print(prefix); pw.print("App Win Anim #"); pw.print(i); 415529e744d3131b9ebeb6b33c8030230c29a44ad12Dianne Hackborn pw.print(": "); pw.println(wanim); 416529e744d3131b9ebeb6b33c8030230c29a44ad12Dianne Hackborn } 417594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner } 418fbf378c736a973b8edaf1fc4c187d11dc0f5e291Craig Mautner 419fbf378c736a973b8edaf1fc4c187d11dc0f5e291Craig Mautner // This is an animation that does nothing: it just immediately finishes 420fbf378c736a973b8edaf1fc4c187d11dc0f5e291Craig Mautner // itself every time it is called. It is used as a stub animation in cases 421fbf378c736a973b8edaf1fc4c187d11dc0f5e291Craig Mautner // where we want to synchronize multiple things that may be animating. 422fbf378c736a973b8edaf1fc4c187d11dc0f5e291Craig Mautner static final class DummyAnimation extends Animation { 423fbf378c736a973b8edaf1fc4c187d11dc0f5e291Craig Mautner @Override 424fbf378c736a973b8edaf1fc4c187d11dc0f5e291Craig Mautner public boolean getTransformation(long currentTime, Transformation outTransformation) { 425fbf378c736a973b8edaf1fc4c187d11dc0f5e291Craig Mautner return false; 426fbf378c736a973b8edaf1fc4c187d11dc0f5e291Craig Mautner } 427fbf378c736a973b8edaf1fc4c187d11dc0f5e291Craig Mautner } 428fbf378c736a973b8edaf1fc4c187d11dc0f5e291Craig Mautner 429594316361d38d88b53c85bd5c8d58a92345e8187Craig Mautner} 430