1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wm; 18 19 import android.content.Context; 20 import android.content.res.Configuration; 21 import android.graphics.Bitmap; 22 import android.graphics.Rect; 23 import android.os.Debug; 24 import android.os.Handler; 25 import android.os.IBinder; 26 import android.os.IRemoteCallback; 27 import android.util.Slog; 28 import android.view.WindowManager; 29 import android.view.animation.AlphaAnimation; 30 import android.view.animation.Animation; 31 import android.view.animation.AnimationSet; 32 import android.view.animation.AnimationUtils; 33 import android.view.animation.ClipRectAnimation; 34 import android.view.animation.ClipRectLRAnimation; 35 import android.view.animation.ClipRectTBAnimation; 36 import android.view.animation.Interpolator; 37 import android.view.animation.PathInterpolator; 38 import android.view.animation.ScaleAnimation; 39 import android.view.animation.TranslateAnimation; 40 import android.view.animation.TranslateYAnimation; 41 42 import com.android.internal.util.DumpUtils.Dump; 43 import com.android.server.AttributeCache; 44 import com.android.server.wm.WindowManagerService.H; 45 46 import java.io.PrintWriter; 47 import java.util.ArrayList; 48 49 import static android.view.WindowManagerInternal.AppTransitionListener; 50 import static com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation; 51 import static com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation; 52 import static com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation; 53 import static com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation; 54 import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindSourceAnimation; 55 import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindTargetAnimation; 56 import static com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation; 57 import static com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation; 58 import static com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation; 59 import static com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation; 60 import static com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation; 61 import static com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation; 62 import static com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation; 63 import static com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation; 64 import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation; 65 import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation; 66 import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation; 67 import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation; 68 import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation; 69 import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation; 70 import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation; 71 import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation; 72 73 // State management of app transitions. When we are preparing for a 74 // transition, mNextAppTransition will be the kind of transition to 75 // perform or TRANSIT_NONE if we are not waiting. If we are waiting, 76 // mOpeningApps and mClosingApps are the lists of tokens that will be 77 // made visible or hidden at the next transition. 78 public class AppTransition implements Dump { 79 private static final String TAG = "AppTransition"; 80 private static final boolean DEBUG_APP_TRANSITIONS = 81 WindowManagerService.DEBUG_APP_TRANSITIONS; 82 private static final boolean DEBUG_ANIM = WindowManagerService.DEBUG_ANIM; 83 private static final int CLIP_REVEAL_TRANSLATION_Y_DP = 8; 84 85 /** Not set up for a transition. */ 86 public static final int TRANSIT_UNSET = -1; 87 /** No animation for transition. */ 88 public static final int TRANSIT_NONE = 0; 89 /** A window in a new activity is being opened on top of an existing one in the same task. */ 90 public static final int TRANSIT_ACTIVITY_OPEN = 6; 91 /** The window in the top-most activity is being closed to reveal the 92 * previous activity in the same task. */ 93 public static final int TRANSIT_ACTIVITY_CLOSE = 7; 94 /** A window in a new task is being opened on top of an existing one 95 * in another activity's task. */ 96 public static final int TRANSIT_TASK_OPEN = 8; 97 /** A window in the top-most activity is being closed to reveal the 98 * previous activity in a different task. */ 99 public static final int TRANSIT_TASK_CLOSE = 9; 100 /** A window in an existing task is being displayed on top of an existing one 101 * in another activity's task. */ 102 public static final int TRANSIT_TASK_TO_FRONT = 10; 103 /** A window in an existing task is being put below all other tasks. */ 104 public static final int TRANSIT_TASK_TO_BACK = 11; 105 /** A window in a new activity that doesn't have a wallpaper is being opened on top of one that 106 * does, effectively closing the wallpaper. */ 107 public static final int TRANSIT_WALLPAPER_CLOSE = 12; 108 /** A window in a new activity that does have a wallpaper is being opened on one that didn't, 109 * effectively opening the wallpaper. */ 110 public static final int TRANSIT_WALLPAPER_OPEN = 13; 111 /** A window in a new activity is being opened on top of an existing one, and both are on top 112 * of the wallpaper. */ 113 public static final int TRANSIT_WALLPAPER_INTRA_OPEN = 14; 114 /** The window in the top-most activity is being closed to reveal the previous activity, and 115 * both are on top of the wallpaper. */ 116 public static final int TRANSIT_WALLPAPER_INTRA_CLOSE = 15; 117 /** A window in a new task is being opened behind an existing one in another activity's task. 118 * The new window will show briefly and then be gone. */ 119 public static final int TRANSIT_TASK_OPEN_BEHIND = 16; 120 /** A window in a task is being animated in-place. */ 121 public static final int TRANSIT_TASK_IN_PLACE = 17; 122 123 /** Fraction of animation at which the recents thumbnail stays completely transparent */ 124 private static final float RECENTS_THUMBNAIL_FADEIN_FRACTION = 0.5f; 125 /** Fraction of animation at which the recents thumbnail becomes completely transparent */ 126 private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.5f; 127 128 private static final int DEFAULT_APP_TRANSITION_DURATION = 336; 129 private static final int THUMBNAIL_APP_TRANSITION_DURATION = 336; 130 private static final int THUMBNAIL_APP_TRANSITION_ALPHA_DURATION = 336; 131 132 private final Context mContext; 133 private final Handler mH; 134 135 private int mNextAppTransition = TRANSIT_UNSET; 136 137 private static final int NEXT_TRANSIT_TYPE_NONE = 0; 138 private static final int NEXT_TRANSIT_TYPE_CUSTOM = 1; 139 private static final int NEXT_TRANSIT_TYPE_SCALE_UP = 2; 140 private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP = 3; 141 private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN = 4; 142 private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP = 5; 143 private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN = 6; 144 private static final int NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE = 7; 145 private static final int NEXT_TRANSIT_TYPE_CLIP_REVEAL = 8; 146 private int mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE; 147 148 // These are the possible states for the enter/exit activities during a thumbnail transition 149 private static final int THUMBNAIL_TRANSITION_ENTER_SCALE_UP = 0; 150 private static final int THUMBNAIL_TRANSITION_EXIT_SCALE_UP = 1; 151 private static final int THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN = 2; 152 private static final int THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN = 3; 153 154 private String mNextAppTransitionPackage; 155 private Bitmap mNextAppTransitionThumbnail; 156 // Used for thumbnail transitions. True if we're scaling up, false if scaling down 157 private boolean mNextAppTransitionScaleUp; 158 private IRemoteCallback mNextAppTransitionCallback; 159 private int mNextAppTransitionEnter; 160 private int mNextAppTransitionExit; 161 private int mNextAppTransitionInPlace; 162 private int mNextAppTransitionStartX; 163 private int mNextAppTransitionStartY; 164 private int mNextAppTransitionStartWidth; 165 private int mNextAppTransitionStartHeight; 166 private Rect mNextAppTransitionInsets = new Rect(); 167 168 private Rect mTmpFromClipRect = new Rect(); 169 private Rect mTmpToClipRect = new Rect(); 170 171 private final static int APP_STATE_IDLE = 0; 172 private final static int APP_STATE_READY = 1; 173 private final static int APP_STATE_RUNNING = 2; 174 private final static int APP_STATE_TIMEOUT = 3; 175 private int mAppTransitionState = APP_STATE_IDLE; 176 177 private final int mConfigShortAnimTime; 178 private final Interpolator mDecelerateInterpolator; 179 private final Interpolator mThumbnailFadeInInterpolator; 180 private final Interpolator mThumbnailFadeOutInterpolator; 181 private final Interpolator mLinearOutSlowInInterpolator; 182 private final Interpolator mFastOutLinearInInterpolator; 183 private final Interpolator mClipHorizontalInterpolator = new PathInterpolator(0, 0, 0.4f, 1f); 184 185 /** Interpolator to be used for animations that respond directly to a touch */ 186 private final Interpolator mTouchResponseInterpolator = 187 new PathInterpolator(0.3f, 0f, 0.1f, 1f); 188 189 private final int mClipRevealTranslationY; 190 191 private int mCurrentUserId = 0; 192 193 private final ArrayList<AppTransitionListener> mListeners = new ArrayList<>(); 194 AppTransition(Context context, Handler h)195 AppTransition(Context context, Handler h) { 196 mContext = context; 197 mH = h; 198 mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, 199 com.android.internal.R.interpolator.linear_out_slow_in); 200 mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context, 201 com.android.internal.R.interpolator.fast_out_linear_in); 202 mConfigShortAnimTime = context.getResources().getInteger( 203 com.android.internal.R.integer.config_shortAnimTime); 204 mDecelerateInterpolator = AnimationUtils.loadInterpolator(context, 205 com.android.internal.R.interpolator.decelerate_cubic); 206 mThumbnailFadeInInterpolator = new Interpolator() { 207 @Override 208 public float getInterpolation(float input) { 209 // Linear response for first fraction, then complete after that. 210 if (input < RECENTS_THUMBNAIL_FADEIN_FRACTION) { 211 return 0f; 212 } 213 float t = (input - RECENTS_THUMBNAIL_FADEIN_FRACTION) / 214 (1f - RECENTS_THUMBNAIL_FADEIN_FRACTION); 215 return mFastOutLinearInInterpolator.getInterpolation(t); 216 } 217 }; 218 mThumbnailFadeOutInterpolator = new Interpolator() { 219 @Override 220 public float getInterpolation(float input) { 221 // Linear response for first fraction, then complete after that. 222 if (input < RECENTS_THUMBNAIL_FADEOUT_FRACTION) { 223 float t = input / RECENTS_THUMBNAIL_FADEOUT_FRACTION; 224 return mLinearOutSlowInInterpolator.getInterpolation(t); 225 } 226 return 1f; 227 } 228 }; 229 mClipRevealTranslationY = (int) (CLIP_REVEAL_TRANSLATION_Y_DP 230 * mContext.getResources().getDisplayMetrics().density); 231 } 232 isTransitionSet()233 boolean isTransitionSet() { 234 return mNextAppTransition != TRANSIT_UNSET; 235 } 236 isTransitionNone()237 boolean isTransitionNone() { 238 return mNextAppTransition == TRANSIT_NONE; 239 } 240 isTransitionEqual(int transit)241 boolean isTransitionEqual(int transit) { 242 return mNextAppTransition == transit; 243 } 244 getAppTransition()245 int getAppTransition() { 246 return mNextAppTransition; 247 } 248 setAppTransition(int transit)249 void setAppTransition(int transit) { 250 mNextAppTransition = transit; 251 } 252 isReady()253 boolean isReady() { 254 return mAppTransitionState == APP_STATE_READY 255 || mAppTransitionState == APP_STATE_TIMEOUT; 256 } 257 setReady()258 void setReady() { 259 mAppTransitionState = APP_STATE_READY; 260 } 261 isRunning()262 boolean isRunning() { 263 return mAppTransitionState == APP_STATE_RUNNING; 264 } 265 setIdle()266 void setIdle() { 267 mAppTransitionState = APP_STATE_IDLE; 268 } 269 isTimeout()270 boolean isTimeout() { 271 return mAppTransitionState == APP_STATE_TIMEOUT; 272 } 273 setTimeout()274 void setTimeout() { 275 mAppTransitionState = APP_STATE_TIMEOUT; 276 } 277 getNextAppTransitionThumbnail()278 Bitmap getNextAppTransitionThumbnail() { 279 return mNextAppTransitionThumbnail; 280 } 281 282 /** Returns whether the next thumbnail transition is aspect scaled up. */ isNextThumbnailTransitionAspectScaled()283 boolean isNextThumbnailTransitionAspectScaled() { 284 return mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP || 285 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN; 286 } 287 288 /** Returns whether the next thumbnail transition is scaling up. */ isNextThumbnailTransitionScaleUp()289 boolean isNextThumbnailTransitionScaleUp() { 290 return mNextAppTransitionScaleUp; 291 } 292 getStartingX()293 int getStartingX() { 294 return mNextAppTransitionStartX; 295 } 296 getStartingY()297 int getStartingY() { 298 return mNextAppTransitionStartY; 299 } 300 prepare()301 boolean prepare() { 302 if (!isRunning()) { 303 mAppTransitionState = APP_STATE_IDLE; 304 notifyAppTransitionPendingLocked(); 305 return true; 306 } 307 return false; 308 } 309 goodToGo(AppWindowAnimator openingAppAnimator, AppWindowAnimator closingAppAnimator)310 void goodToGo(AppWindowAnimator openingAppAnimator, AppWindowAnimator closingAppAnimator) { 311 mNextAppTransition = TRANSIT_UNSET; 312 mAppTransitionState = APP_STATE_RUNNING; 313 notifyAppTransitionStartingLocked( 314 openingAppAnimator != null ? openingAppAnimator.mAppToken.token : null, 315 closingAppAnimator != null ? closingAppAnimator.mAppToken.token : null, 316 openingAppAnimator != null ? openingAppAnimator.animation : null, 317 closingAppAnimator != null ? closingAppAnimator.animation : null); 318 } 319 clear()320 void clear() { 321 mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE; 322 mNextAppTransitionPackage = null; 323 mNextAppTransitionThumbnail = null; 324 } 325 freeze()326 void freeze() { 327 setAppTransition(AppTransition.TRANSIT_UNSET); 328 clear(); 329 setReady(); 330 notifyAppTransitionCancelledLocked(); 331 } 332 registerListenerLocked(AppTransitionListener listener)333 void registerListenerLocked(AppTransitionListener listener) { 334 mListeners.add(listener); 335 } 336 notifyAppTransitionFinishedLocked(IBinder token)337 public void notifyAppTransitionFinishedLocked(IBinder token) { 338 for (int i = 0; i < mListeners.size(); i++) { 339 mListeners.get(i).onAppTransitionFinishedLocked(token); 340 } 341 } 342 notifyAppTransitionPendingLocked()343 private void notifyAppTransitionPendingLocked() { 344 for (int i = 0; i < mListeners.size(); i++) { 345 mListeners.get(i).onAppTransitionPendingLocked(); 346 } 347 } 348 notifyAppTransitionCancelledLocked()349 private void notifyAppTransitionCancelledLocked() { 350 for (int i = 0; i < mListeners.size(); i++) { 351 mListeners.get(i).onAppTransitionCancelledLocked(); 352 } 353 } 354 notifyAppTransitionStartingLocked(IBinder openToken, IBinder closeToken, Animation openAnimation, Animation closeAnimation)355 private void notifyAppTransitionStartingLocked(IBinder openToken, 356 IBinder closeToken, Animation openAnimation, Animation closeAnimation) { 357 for (int i = 0; i < mListeners.size(); i++) { 358 mListeners.get(i).onAppTransitionStartingLocked(openToken, closeToken, openAnimation, 359 closeAnimation); 360 } 361 } 362 getCachedAnimations(WindowManager.LayoutParams lp)363 private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) { 364 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: layout params pkg=" 365 + (lp != null ? lp.packageName : null) 366 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null)); 367 if (lp != null && lp.windowAnimations != 0) { 368 // If this is a system resource, don't try to load it from the 369 // application resources. It is nice to avoid loading application 370 // resources if we can. 371 String packageName = lp.packageName != null ? lp.packageName : "android"; 372 int resId = lp.windowAnimations; 373 if ((resId&0xFF000000) == 0x01000000) { 374 packageName = "android"; 375 } 376 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package=" 377 + packageName); 378 return AttributeCache.instance().get(packageName, resId, 379 com.android.internal.R.styleable.WindowAnimation, mCurrentUserId); 380 } 381 return null; 382 } 383 getCachedAnimations(String packageName, int resId)384 private AttributeCache.Entry getCachedAnimations(String packageName, int resId) { 385 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: package=" 386 + packageName + " resId=0x" + Integer.toHexString(resId)); 387 if (packageName != null) { 388 if ((resId&0xFF000000) == 0x01000000) { 389 packageName = "android"; 390 } 391 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package=" 392 + packageName); 393 return AttributeCache.instance().get(packageName, resId, 394 com.android.internal.R.styleable.WindowAnimation, mCurrentUserId); 395 } 396 return null; 397 } 398 loadAnimationAttr(WindowManager.LayoutParams lp, int animAttr)399 Animation loadAnimationAttr(WindowManager.LayoutParams lp, int animAttr) { 400 int anim = 0; 401 Context context = mContext; 402 if (animAttr >= 0) { 403 AttributeCache.Entry ent = getCachedAnimations(lp); 404 if (ent != null) { 405 context = ent.context; 406 anim = ent.array.getResourceId(animAttr, 0); 407 } 408 } 409 if (anim != 0) { 410 return AnimationUtils.loadAnimation(context, anim); 411 } 412 return null; 413 } 414 loadAnimationRes(WindowManager.LayoutParams lp, int resId)415 Animation loadAnimationRes(WindowManager.LayoutParams lp, int resId) { 416 Context context = mContext; 417 if (resId >= 0) { 418 AttributeCache.Entry ent = getCachedAnimations(lp); 419 if (ent != null) { 420 context = ent.context; 421 } 422 return AnimationUtils.loadAnimation(context, resId); 423 } 424 return null; 425 } 426 loadAnimationRes(String packageName, int resId)427 private Animation loadAnimationRes(String packageName, int resId) { 428 int anim = 0; 429 Context context = mContext; 430 if (resId >= 0) { 431 AttributeCache.Entry ent = getCachedAnimations(packageName, resId); 432 if (ent != null) { 433 context = ent.context; 434 anim = resId; 435 } 436 } 437 if (anim != 0) { 438 return AnimationUtils.loadAnimation(context, anim); 439 } 440 return null; 441 } 442 443 /** 444 * Compute the pivot point for an animation that is scaling from a small 445 * rect on screen to a larger rect. The pivot point varies depending on 446 * the distance between the inner and outer edges on both sides. This 447 * function computes the pivot point for one dimension. 448 * @param startPos Offset from left/top edge of outer rectangle to 449 * left/top edge of inner rectangle. 450 * @param finalScale The scaling factor between the size of the outer 451 * and inner rectangles. 452 */ computePivot(int startPos, float finalScale)453 private static float computePivot(int startPos, float finalScale) { 454 final float denom = finalScale-1; 455 if (Math.abs(denom) < .0001f) { 456 return startPos; 457 } 458 return -startPos / denom; 459 } 460 createScaleUpAnimationLocked(int transit, boolean enter, int appWidth, int appHeight)461 private Animation createScaleUpAnimationLocked(int transit, boolean enter, 462 int appWidth, int appHeight) { 463 Animation a = null; 464 if (enter) { 465 // Entering app zooms out from the center of the initial rect. 466 float scaleW = mNextAppTransitionStartWidth / (float) appWidth; 467 float scaleH = mNextAppTransitionStartHeight / (float) appHeight; 468 Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1, 469 computePivot(mNextAppTransitionStartX, scaleW), 470 computePivot(mNextAppTransitionStartY, scaleH)); 471 scale.setInterpolator(mDecelerateInterpolator); 472 473 Animation alpha = new AlphaAnimation(0, 1); 474 alpha.setInterpolator(mThumbnailFadeOutInterpolator); 475 476 AnimationSet set = new AnimationSet(false); 477 set.addAnimation(scale); 478 set.addAnimation(alpha); 479 set.setDetachWallpaper(true); 480 a = set; 481 } else if (transit == TRANSIT_WALLPAPER_INTRA_OPEN || 482 transit == TRANSIT_WALLPAPER_INTRA_CLOSE) { 483 // If we are on top of the wallpaper, we need an animation that 484 // correctly handles the wallpaper staying static behind all of 485 // the animated elements. To do this, will just have the existing 486 // element fade out. 487 a = new AlphaAnimation(1, 0); 488 a.setDetachWallpaper(true); 489 } else { 490 // For normal animations, the exiting element just holds in place. 491 a = new AlphaAnimation(1, 1); 492 } 493 494 // Pick the desired duration. If this is an inter-activity transition, 495 // it is the standard duration for that. Otherwise we use the longer 496 // task transition duration. 497 final long duration; 498 switch (transit) { 499 case TRANSIT_ACTIVITY_OPEN: 500 case TRANSIT_ACTIVITY_CLOSE: 501 duration = mConfigShortAnimTime; 502 break; 503 default: 504 duration = DEFAULT_APP_TRANSITION_DURATION; 505 break; 506 } 507 a.setDuration(duration); 508 a.setFillAfter(true); 509 a.setInterpolator(mDecelerateInterpolator); 510 a.initialize(appWidth, appHeight, appWidth, appHeight); 511 return a; 512 } 513 createClipRevealAnimationLocked(int transit, boolean enter, Rect appFrame)514 private Animation createClipRevealAnimationLocked(int transit, boolean enter, Rect appFrame) { 515 final Animation anim; 516 if (enter) { 517 // Reveal will expand and move faster in horizontal direction 518 519 final int appWidth = appFrame.width(); 520 final int appHeight = appFrame.height(); 521 522 float t = 0f; 523 if (appHeight > 0) { 524 t = (float) mNextAppTransitionStartY / appHeight; 525 } 526 int translationY = mClipRevealTranslationY 527 + (int)(appHeight / 7f * t); 528 529 int centerX = mNextAppTransitionStartX + mNextAppTransitionStartWidth / 2; 530 int centerY = mNextAppTransitionStartY + mNextAppTransitionStartHeight / 2; 531 532 // Clip third of the from size of launch icon, expand to full width/height 533 Animation clipAnimLR = new ClipRectLRAnimation( 534 centerX - mNextAppTransitionStartWidth / 2, 535 centerX + mNextAppTransitionStartWidth / 2, 536 0, appWidth); 537 clipAnimLR.setInterpolator(mClipHorizontalInterpolator); 538 clipAnimLR.setDuration((long) (DEFAULT_APP_TRANSITION_DURATION / 2.5f)); 539 Animation clipAnimTB = new ClipRectTBAnimation( 540 centerY - mNextAppTransitionStartHeight / 2 - translationY, 541 centerY + mNextAppTransitionStartHeight / 2 - translationY, 542 0, appHeight); 543 clipAnimTB.setInterpolator(mTouchResponseInterpolator); 544 clipAnimTB.setDuration(DEFAULT_APP_TRANSITION_DURATION); 545 546 TranslateYAnimation translateY = new TranslateYAnimation( 547 Animation.ABSOLUTE, translationY, Animation.ABSOLUTE, 0); 548 translateY.setInterpolator(mLinearOutSlowInInterpolator); 549 translateY.setDuration(DEFAULT_APP_TRANSITION_DURATION); 550 551 // Quick fade-in from icon to app window 552 final int alphaDuration = DEFAULT_APP_TRANSITION_DURATION / 4; 553 AlphaAnimation alpha = new AlphaAnimation(0.5f, 1); 554 alpha.setDuration(alphaDuration); 555 alpha.setInterpolator(mLinearOutSlowInInterpolator); 556 557 AnimationSet set = new AnimationSet(false); 558 set.addAnimation(clipAnimLR); 559 set.addAnimation(clipAnimTB); 560 set.addAnimation(translateY); 561 set.addAnimation(alpha); 562 set.setZAdjustment(Animation.ZORDER_TOP); 563 set.initialize(appWidth, appHeight, appWidth, appHeight); 564 anim = set; 565 } else { 566 final long duration; 567 switch (transit) { 568 case TRANSIT_ACTIVITY_OPEN: 569 case TRANSIT_ACTIVITY_CLOSE: 570 duration = mConfigShortAnimTime; 571 break; 572 default: 573 duration = DEFAULT_APP_TRANSITION_DURATION; 574 break; 575 } 576 if (transit == TRANSIT_WALLPAPER_INTRA_OPEN || 577 transit == TRANSIT_WALLPAPER_INTRA_CLOSE) { 578 // If we are on top of the wallpaper, we need an animation that 579 // correctly handles the wallpaper staying static behind all of 580 // the animated elements. To do this, will just have the existing 581 // element fade out. 582 anim = new AlphaAnimation(1, 0); 583 anim.setDetachWallpaper(true); 584 } else { 585 // For normal animations, the exiting element just holds in place. 586 anim = new AlphaAnimation(1, 1); 587 } 588 anim.setInterpolator(mDecelerateInterpolator); 589 anim.setDuration(duration); 590 anim.setFillAfter(true); 591 } 592 return anim; 593 } 594 595 /** 596 * Prepares the specified animation with a standard duration, interpolator, etc. 597 */ prepareThumbnailAnimationWithDuration(Animation a, int appWidth, int appHeight, int duration, Interpolator interpolator)598 Animation prepareThumbnailAnimationWithDuration(Animation a, int appWidth, int appHeight, 599 int duration, Interpolator interpolator) { 600 if (duration > 0) { 601 a.setDuration(duration); 602 } 603 a.setFillAfter(true); 604 a.setInterpolator(interpolator); 605 a.initialize(appWidth, appHeight, appWidth, appHeight); 606 return a; 607 } 608 609 /** 610 * Prepares the specified animation with a standard duration, interpolator, etc. 611 */ prepareThumbnailAnimation(Animation a, int appWidth, int appHeight, int transit)612 Animation prepareThumbnailAnimation(Animation a, int appWidth, int appHeight, int transit) { 613 // Pick the desired duration. If this is an inter-activity transition, 614 // it is the standard duration for that. Otherwise we use the longer 615 // task transition duration. 616 final int duration; 617 switch (transit) { 618 case TRANSIT_ACTIVITY_OPEN: 619 case TRANSIT_ACTIVITY_CLOSE: 620 duration = mConfigShortAnimTime; 621 break; 622 default: 623 duration = DEFAULT_APP_TRANSITION_DURATION; 624 break; 625 } 626 return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, duration, 627 mDecelerateInterpolator); 628 } 629 630 /** 631 * Return the current thumbnail transition state. 632 */ getThumbnailTransitionState(boolean enter)633 int getThumbnailTransitionState(boolean enter) { 634 if (enter) { 635 if (mNextAppTransitionScaleUp) { 636 return THUMBNAIL_TRANSITION_ENTER_SCALE_UP; 637 } else { 638 return THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN; 639 } 640 } else { 641 if (mNextAppTransitionScaleUp) { 642 return THUMBNAIL_TRANSITION_EXIT_SCALE_UP; 643 } else { 644 return THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN; 645 } 646 } 647 } 648 649 /** 650 * This animation runs for the thumbnail that gets cross faded with the enter/exit activity 651 * when a thumbnail is specified with the activity options. 652 */ createThumbnailAspectScaleAnimationLocked(int appWidth, int appHeight, int deviceWidth, int transit)653 Animation createThumbnailAspectScaleAnimationLocked(int appWidth, int appHeight, 654 int deviceWidth, int transit) { 655 Animation a; 656 final int thumbWidthI = mNextAppTransitionThumbnail.getWidth(); 657 final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1; 658 final int thumbHeightI = mNextAppTransitionThumbnail.getHeight(); 659 final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1; 660 661 float scaleW = deviceWidth / thumbWidth; 662 float unscaledWidth = deviceWidth; 663 float unscaledHeight = thumbHeight * scaleW; 664 float unscaledStartY = mNextAppTransitionStartY - (unscaledHeight - thumbHeight) / 2f; 665 if (mNextAppTransitionScaleUp) { 666 // Animation up from the thumbnail to the full screen 667 Animation scale = new ScaleAnimation(1f, scaleW, 1f, scaleW, 668 mNextAppTransitionStartX + (thumbWidth / 2f), 669 mNextAppTransitionStartY + (thumbHeight / 2f)); 670 scale.setInterpolator(mTouchResponseInterpolator); 671 scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION); 672 Animation alpha = new AlphaAnimation(1, 0); 673 alpha.setInterpolator(mThumbnailFadeOutInterpolator); 674 alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION); 675 Animation translate = new TranslateAnimation(0, 0, 0, -unscaledStartY + 676 mNextAppTransitionInsets.top); 677 translate.setInterpolator(mTouchResponseInterpolator); 678 translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION); 679 680 // This AnimationSet uses the Interpolators assigned above. 681 AnimationSet set = new AnimationSet(false); 682 set.addAnimation(scale); 683 set.addAnimation(alpha); 684 set.addAnimation(translate); 685 a = set; 686 } else { 687 // Animation down from the full screen to the thumbnail 688 Animation scale = new ScaleAnimation(scaleW, 1f, scaleW, 1f, 689 mNextAppTransitionStartX + (thumbWidth / 2f), 690 mNextAppTransitionStartY + (thumbHeight / 2f)); 691 scale.setInterpolator(mTouchResponseInterpolator); 692 scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION); 693 Animation alpha = new AlphaAnimation(0f, 1f); 694 alpha.setInterpolator(mThumbnailFadeInInterpolator); 695 alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION); 696 Animation translate = new TranslateAnimation(0, 0, -unscaledStartY + 697 mNextAppTransitionInsets.top, 0); 698 translate.setInterpolator(mTouchResponseInterpolator); 699 translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION); 700 701 // This AnimationSet uses the Interpolators assigned above. 702 AnimationSet set = new AnimationSet(false); 703 set.addAnimation(scale); 704 set.addAnimation(alpha); 705 set.addAnimation(translate); 706 a = set; 707 708 } 709 return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, 0, 710 mTouchResponseInterpolator); 711 } 712 713 /** 714 * This alternate animation is created when we are doing a thumbnail transition, for the 715 * activity that is leaving, and the activity that is entering. 716 */ createAspectScaledThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth, int appHeight, int orientation, int transit, Rect containingFrame, Rect contentInsets)717 Animation createAspectScaledThumbnailEnterExitAnimationLocked(int thumbTransitState, 718 int appWidth, int appHeight, int orientation, int transit, Rect containingFrame, 719 Rect contentInsets) { 720 Animation a; 721 final int thumbWidthI = mNextAppTransitionStartWidth; 722 final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1; 723 final int thumbHeightI = mNextAppTransitionStartHeight; 724 final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1; 725 726 // Used for the ENTER_SCALE_UP and EXIT_SCALE_DOWN transitions 727 float scale = 1f; 728 int scaledTopDecor = 0; 729 730 switch (thumbTransitState) { 731 case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: { 732 // App window scaling up to become full screen 733 if (orientation == Configuration.ORIENTATION_PORTRAIT) { 734 // In portrait, we scale the width and clip to the top/left square 735 scale = thumbWidth / appWidth; 736 scaledTopDecor = (int) (scale * contentInsets.top); 737 int unscaledThumbHeight = (int) (thumbHeight / scale); 738 mTmpFromClipRect.set(containingFrame); 739 mTmpFromClipRect.bottom = (mTmpFromClipRect.top + unscaledThumbHeight); 740 mTmpToClipRect.set(containingFrame); 741 } else { 742 // In landscape, we scale the height and clip to the top/left square 743 scale = thumbHeight / (appHeight - contentInsets.top); 744 scaledTopDecor = (int) (scale * contentInsets.top); 745 int unscaledThumbWidth = (int) (thumbWidth / scale); 746 mTmpFromClipRect.set(containingFrame); 747 mTmpFromClipRect.right = (mTmpFromClipRect.left + unscaledThumbWidth); 748 mTmpToClipRect.set(containingFrame); 749 } 750 // exclude top screen decor (status bar) region from the source clip. 751 mTmpFromClipRect.top = contentInsets.top; 752 753 mNextAppTransitionInsets.set(contentInsets); 754 755 Animation scaleAnim = new ScaleAnimation(scale, 1, scale, 1, 756 computePivot(mNextAppTransitionStartX, scale), 757 computePivot(mNextAppTransitionStartY, scale)); 758 Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect); 759 Animation translateAnim = new TranslateAnimation(0, 0, -scaledTopDecor, 0); 760 761 AnimationSet set = new AnimationSet(true); 762 set.addAnimation(clipAnim); 763 set.addAnimation(scaleAnim); 764 set.addAnimation(translateAnim); 765 a = set; 766 break; 767 } 768 case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: { 769 // Previous app window during the scale up 770 if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) { 771 // Fade out the source activity if we are animating to a wallpaper 772 // activity. 773 a = new AlphaAnimation(1, 0); 774 } else { 775 a = new AlphaAnimation(1, 1); 776 } 777 break; 778 } 779 case THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN: { 780 // Target app window during the scale down 781 if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) { 782 // Fade in the destination activity if we are animating from a wallpaper 783 // activity. 784 a = new AlphaAnimation(0, 1); 785 } else { 786 a = new AlphaAnimation(1, 1); 787 } 788 break; 789 } 790 case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: { 791 // App window scaling down from full screen 792 if (orientation == Configuration.ORIENTATION_PORTRAIT) { 793 // In portrait, we scale the width and clip to the top/left square 794 scale = thumbWidth / appWidth; 795 scaledTopDecor = (int) (scale * contentInsets.top); 796 int unscaledThumbHeight = (int) (thumbHeight / scale); 797 mTmpFromClipRect.set(containingFrame); 798 mTmpToClipRect.set(containingFrame); 799 mTmpToClipRect.bottom = (mTmpToClipRect.top + unscaledThumbHeight); 800 } else { 801 // In landscape, we scale the height and clip to the top/left square 802 scale = thumbHeight / (appHeight - contentInsets.top); 803 scaledTopDecor = (int) (scale * contentInsets.top); 804 int unscaledThumbWidth = (int) (thumbWidth / scale); 805 mTmpFromClipRect.set(containingFrame); 806 mTmpToClipRect.set(containingFrame); 807 mTmpToClipRect.right = (mTmpToClipRect.left + unscaledThumbWidth); 808 } 809 // exclude top screen decor (status bar) region from the destination clip. 810 mTmpToClipRect.top = contentInsets.top; 811 812 mNextAppTransitionInsets.set(contentInsets); 813 814 Animation scaleAnim = new ScaleAnimation(1, scale, 1, scale, 815 computePivot(mNextAppTransitionStartX, scale), 816 computePivot(mNextAppTransitionStartY, scale)); 817 Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect); 818 Animation translateAnim = new TranslateAnimation(0, 0, 0, -scaledTopDecor); 819 820 AnimationSet set = new AnimationSet(true); 821 set.addAnimation(clipAnim); 822 set.addAnimation(scaleAnim); 823 set.addAnimation(translateAnim); 824 825 a = set; 826 a.setZAdjustment(Animation.ZORDER_TOP); 827 break; 828 } 829 default: 830 throw new RuntimeException("Invalid thumbnail transition state"); 831 } 832 833 int duration = Math.max(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION, 834 THUMBNAIL_APP_TRANSITION_DURATION); 835 return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, duration, 836 mTouchResponseInterpolator); 837 } 838 839 /** 840 * This animation runs for the thumbnail that gets cross faded with the enter/exit activity 841 * when a thumbnail is specified with the activity options. 842 */ createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit)843 Animation createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit) { 844 Animation a; 845 final int thumbWidthI = mNextAppTransitionThumbnail.getWidth(); 846 final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1; 847 final int thumbHeightI = mNextAppTransitionThumbnail.getHeight(); 848 final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1; 849 850 if (mNextAppTransitionScaleUp) { 851 // Animation for the thumbnail zooming from its initial size to the full screen 852 float scaleW = appWidth / thumbWidth; 853 float scaleH = appHeight / thumbHeight; 854 Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH, 855 computePivot(mNextAppTransitionStartX, 1 / scaleW), 856 computePivot(mNextAppTransitionStartY, 1 / scaleH)); 857 scale.setInterpolator(mDecelerateInterpolator); 858 859 Animation alpha = new AlphaAnimation(1, 0); 860 alpha.setInterpolator(mThumbnailFadeOutInterpolator); 861 862 // This AnimationSet uses the Interpolators assigned above. 863 AnimationSet set = new AnimationSet(false); 864 set.addAnimation(scale); 865 set.addAnimation(alpha); 866 a = set; 867 } else { 868 // Animation for the thumbnail zooming down from the full screen to its final size 869 float scaleW = appWidth / thumbWidth; 870 float scaleH = appHeight / thumbHeight; 871 a = new ScaleAnimation(scaleW, 1, scaleH, 1, 872 computePivot(mNextAppTransitionStartX, 1 / scaleW), 873 computePivot(mNextAppTransitionStartY, 1 / scaleH)); 874 } 875 876 return prepareThumbnailAnimation(a, appWidth, appHeight, transit); 877 } 878 879 /** 880 * This animation is created when we are doing a thumbnail transition, for the activity that is 881 * leaving, and the activity that is entering. 882 */ createThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth, int appHeight, int transit)883 Animation createThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth, 884 int appHeight, int transit) { 885 Animation a; 886 final int thumbWidthI = mNextAppTransitionThumbnail.getWidth(); 887 final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1; 888 final int thumbHeightI = mNextAppTransitionThumbnail.getHeight(); 889 final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1; 890 891 switch (thumbTransitState) { 892 case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: { 893 // Entering app scales up with the thumbnail 894 float scaleW = thumbWidth / appWidth; 895 float scaleH = thumbHeight / appHeight; 896 a = new ScaleAnimation(scaleW, 1, scaleH, 1, 897 computePivot(mNextAppTransitionStartX, scaleW), 898 computePivot(mNextAppTransitionStartY, scaleH)); 899 break; 900 } 901 case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: { 902 // Exiting app while the thumbnail is scaling up should fade or stay in place 903 if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) { 904 // Fade out while bringing up selected activity. This keeps the 905 // current activity from showing through a launching wallpaper 906 // activity. 907 a = new AlphaAnimation(1, 0); 908 } else { 909 // noop animation 910 a = new AlphaAnimation(1, 1); 911 } 912 break; 913 } 914 case THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN: { 915 // Entering the other app, it should just be visible while we scale the thumbnail 916 // down above it 917 a = new AlphaAnimation(1, 1); 918 break; 919 } 920 case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: { 921 // Exiting the current app, the app should scale down with the thumbnail 922 float scaleW = thumbWidth / appWidth; 923 float scaleH = thumbHeight / appHeight; 924 Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH, 925 computePivot(mNextAppTransitionStartX, scaleW), 926 computePivot(mNextAppTransitionStartY, scaleH)); 927 928 Animation alpha = new AlphaAnimation(1, 0); 929 930 AnimationSet set = new AnimationSet(true); 931 set.addAnimation(scale); 932 set.addAnimation(alpha); 933 set.setZAdjustment(Animation.ZORDER_TOP); 934 a = set; 935 break; 936 } 937 default: 938 throw new RuntimeException("Invalid thumbnail transition state"); 939 } 940 941 return prepareThumbnailAnimation(a, appWidth, appHeight, transit); 942 } 943 944 /** 945 * @return true if and only if the first frame of the transition can be skipped, i.e. the first 946 * frame of the transition doesn't change the visuals on screen, so we can start 947 * directly with the second one 948 */ canSkipFirstFrame()949 boolean canSkipFirstFrame() { 950 return mNextAppTransitionType != NEXT_TRANSIT_TYPE_CUSTOM 951 && mNextAppTransitionType != NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE 952 && mNextAppTransitionType != NEXT_TRANSIT_TYPE_CLIP_REVEAL; 953 } 954 loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, int appWidth, int appHeight, int orientation, Rect containingFrame, Rect contentInsets, Rect appFrame, boolean isVoiceInteraction)955 Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, 956 int appWidth, int appHeight, int orientation, Rect containingFrame, Rect contentInsets, 957 Rect appFrame, boolean isVoiceInteraction) { 958 Animation a; 959 if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_OPEN 960 || transit == TRANSIT_TASK_OPEN 961 || transit == TRANSIT_TASK_TO_FRONT)) { 962 a = loadAnimationRes(lp, enter 963 ? com.android.internal.R.anim.voice_activity_open_enter 964 : com.android.internal.R.anim.voice_activity_open_exit); 965 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 966 "applyAnimation voice:" 967 + " anim=" + a + " transit=" + appTransitionToString(transit) 968 + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); 969 } else if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_CLOSE 970 || transit == TRANSIT_TASK_CLOSE 971 || transit == TRANSIT_TASK_TO_BACK)) { 972 a = loadAnimationRes(lp, enter 973 ? com.android.internal.R.anim.voice_activity_close_enter 974 : com.android.internal.R.anim.voice_activity_close_exit); 975 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 976 "applyAnimation voice:" 977 + " anim=" + a + " transit=" + appTransitionToString(transit) 978 + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); 979 } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) { 980 a = loadAnimationRes(mNextAppTransitionPackage, enter ? 981 mNextAppTransitionEnter : mNextAppTransitionExit); 982 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 983 "applyAnimation:" 984 + " anim=" + a + " nextAppTransition=ANIM_CUSTOM" 985 + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter 986 + " Callers=" + Debug.getCallers(3)); 987 } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE) { 988 a = loadAnimationRes(mNextAppTransitionPackage, mNextAppTransitionInPlace); 989 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 990 "applyAnimation:" 991 + " anim=" + a + " nextAppTransition=ANIM_CUSTOM_IN_PLACE" 992 + " transit=" + appTransitionToString(transit) 993 + " Callers=" + Debug.getCallers(3)); 994 } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL) { 995 a = createClipRevealAnimationLocked(transit, enter, appFrame); 996 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 997 "applyAnimation:" 998 + " anim=" + a + " nextAppTransition=ANIM_CLIP_REVEAL" 999 + " Callers=" + Debug.getCallers(3)); 1000 } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_SCALE_UP) { 1001 a = createScaleUpAnimationLocked(transit, enter, appWidth, appHeight); 1002 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 1003 "applyAnimation:" 1004 + " anim=" + a + " nextAppTransition=ANIM_SCALE_UP" 1005 + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter 1006 + " Callers=" + Debug.getCallers(3)); 1007 } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP || 1008 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) { 1009 mNextAppTransitionScaleUp = 1010 (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP); 1011 a = createThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter), 1012 appWidth, appHeight, transit); 1013 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) { 1014 String animName = mNextAppTransitionScaleUp ? 1015 "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN"; 1016 Slog.v(TAG, "applyAnimation:" 1017 + " anim=" + a + " nextAppTransition=" + animName 1018 + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter 1019 + " Callers=" + Debug.getCallers(3)); 1020 } 1021 } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP || 1022 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN) { 1023 mNextAppTransitionScaleUp = 1024 (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP); 1025 a = createAspectScaledThumbnailEnterExitAnimationLocked( 1026 getThumbnailTransitionState(enter), appWidth, appHeight, orientation, 1027 transit, containingFrame, contentInsets); 1028 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) { 1029 String animName = mNextAppTransitionScaleUp ? 1030 "ANIM_THUMBNAIL_ASPECT_SCALE_UP" : "ANIM_THUMBNAIL_ASPECT_SCALE_DOWN"; 1031 Slog.v(TAG, "applyAnimation:" 1032 + " anim=" + a + " nextAppTransition=" + animName 1033 + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter 1034 + " Callers=" + Debug.getCallers(3)); 1035 } 1036 } else { 1037 int animAttr = 0; 1038 switch (transit) { 1039 case TRANSIT_ACTIVITY_OPEN: 1040 animAttr = enter 1041 ? WindowAnimation_activityOpenEnterAnimation 1042 : WindowAnimation_activityOpenExitAnimation; 1043 break; 1044 case TRANSIT_ACTIVITY_CLOSE: 1045 animAttr = enter 1046 ? WindowAnimation_activityCloseEnterAnimation 1047 : WindowAnimation_activityCloseExitAnimation; 1048 break; 1049 case TRANSIT_TASK_OPEN: 1050 animAttr = enter 1051 ? WindowAnimation_taskOpenEnterAnimation 1052 : WindowAnimation_taskOpenExitAnimation; 1053 break; 1054 case TRANSIT_TASK_CLOSE: 1055 animAttr = enter 1056 ? WindowAnimation_taskCloseEnterAnimation 1057 : WindowAnimation_taskCloseExitAnimation; 1058 break; 1059 case TRANSIT_TASK_TO_FRONT: 1060 animAttr = enter 1061 ? WindowAnimation_taskToFrontEnterAnimation 1062 : WindowAnimation_taskToFrontExitAnimation; 1063 break; 1064 case TRANSIT_TASK_TO_BACK: 1065 animAttr = enter 1066 ? WindowAnimation_taskToBackEnterAnimation 1067 : WindowAnimation_taskToBackExitAnimation; 1068 break; 1069 case TRANSIT_WALLPAPER_OPEN: 1070 animAttr = enter 1071 ? WindowAnimation_wallpaperOpenEnterAnimation 1072 : WindowAnimation_wallpaperOpenExitAnimation; 1073 break; 1074 case TRANSIT_WALLPAPER_CLOSE: 1075 animAttr = enter 1076 ? WindowAnimation_wallpaperCloseEnterAnimation 1077 : WindowAnimation_wallpaperCloseExitAnimation; 1078 break; 1079 case TRANSIT_WALLPAPER_INTRA_OPEN: 1080 animAttr = enter 1081 ? WindowAnimation_wallpaperIntraOpenEnterAnimation 1082 : WindowAnimation_wallpaperIntraOpenExitAnimation; 1083 break; 1084 case TRANSIT_WALLPAPER_INTRA_CLOSE: 1085 animAttr = enter 1086 ? WindowAnimation_wallpaperIntraCloseEnterAnimation 1087 : WindowAnimation_wallpaperIntraCloseExitAnimation; 1088 break; 1089 case TRANSIT_TASK_OPEN_BEHIND: 1090 animAttr = enter 1091 ? WindowAnimation_launchTaskBehindSourceAnimation 1092 : WindowAnimation_launchTaskBehindTargetAnimation; 1093 } 1094 a = animAttr != 0 ? loadAnimationAttr(lp, animAttr) : null; 1095 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 1096 "applyAnimation:" 1097 + " anim=" + a 1098 + " animAttr=0x" + Integer.toHexString(animAttr) 1099 + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter 1100 + " Callers=" + Debug.getCallers(3)); 1101 } 1102 return a; 1103 } 1104 postAnimationCallback()1105 void postAnimationCallback() { 1106 if (mNextAppTransitionCallback != null) { 1107 mH.sendMessage(mH.obtainMessage(H.DO_ANIMATION_CALLBACK, mNextAppTransitionCallback)); 1108 mNextAppTransitionCallback = null; 1109 } 1110 } 1111 overridePendingAppTransition(String packageName, int enterAnim, int exitAnim, IRemoteCallback startedCallback)1112 void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim, 1113 IRemoteCallback startedCallback) { 1114 if (isTransitionSet()) { 1115 mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM; 1116 mNextAppTransitionPackage = packageName; 1117 mNextAppTransitionThumbnail = null; 1118 mNextAppTransitionEnter = enterAnim; 1119 mNextAppTransitionExit = exitAnim; 1120 postAnimationCallback(); 1121 mNextAppTransitionCallback = startedCallback; 1122 } else { 1123 postAnimationCallback(); 1124 } 1125 } 1126 overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, int startHeight)1127 void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, 1128 int startHeight) { 1129 if (isTransitionSet()) { 1130 mNextAppTransitionType = NEXT_TRANSIT_TYPE_SCALE_UP; 1131 mNextAppTransitionPackage = null; 1132 mNextAppTransitionThumbnail = null; 1133 mNextAppTransitionStartX = startX; 1134 mNextAppTransitionStartY = startY; 1135 mNextAppTransitionStartWidth = startWidth; 1136 mNextAppTransitionStartHeight = startHeight; 1137 postAnimationCallback(); 1138 mNextAppTransitionCallback = null; 1139 } 1140 } 1141 overridePendingAppTransitionClipReveal(int startX, int startY, int startWidth, int startHeight)1142 void overridePendingAppTransitionClipReveal(int startX, int startY, 1143 int startWidth, int startHeight) { 1144 if (isTransitionSet()) { 1145 mNextAppTransitionType = NEXT_TRANSIT_TYPE_CLIP_REVEAL; 1146 mNextAppTransitionStartX = startX; 1147 mNextAppTransitionStartY = startY; 1148 mNextAppTransitionStartWidth = startWidth; 1149 mNextAppTransitionStartHeight = startHeight; 1150 postAnimationCallback(); 1151 mNextAppTransitionCallback = null; 1152 } 1153 } 1154 overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY, IRemoteCallback startedCallback, boolean scaleUp)1155 void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY, 1156 IRemoteCallback startedCallback, boolean scaleUp) { 1157 if (isTransitionSet()) { 1158 mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP 1159 : NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN; 1160 mNextAppTransitionPackage = null; 1161 mNextAppTransitionThumbnail = srcThumb; 1162 mNextAppTransitionScaleUp = scaleUp; 1163 mNextAppTransitionStartX = startX; 1164 mNextAppTransitionStartY = startY; 1165 postAnimationCallback(); 1166 mNextAppTransitionCallback = startedCallback; 1167 } else { 1168 postAnimationCallback(); 1169 } 1170 } 1171 overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX, int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback, boolean scaleUp)1172 void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX, int startY, 1173 int targetWidth, int targetHeight, IRemoteCallback startedCallback, boolean scaleUp) { 1174 if (isTransitionSet()) { 1175 mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP 1176 : NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN; 1177 mNextAppTransitionPackage = null; 1178 mNextAppTransitionThumbnail = srcThumb; 1179 mNextAppTransitionScaleUp = scaleUp; 1180 mNextAppTransitionStartX = startX; 1181 mNextAppTransitionStartY = startY; 1182 mNextAppTransitionStartWidth = targetWidth; 1183 mNextAppTransitionStartHeight = targetHeight; 1184 postAnimationCallback(); 1185 mNextAppTransitionCallback = startedCallback; 1186 } else { 1187 postAnimationCallback(); 1188 } 1189 } 1190 overrideInPlaceAppTransition(String packageName, int anim)1191 void overrideInPlaceAppTransition(String packageName, int anim) { 1192 if (isTransitionSet()) { 1193 mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE; 1194 mNextAppTransitionPackage = packageName; 1195 mNextAppTransitionInPlace = anim; 1196 } else { 1197 postAnimationCallback(); 1198 } 1199 } 1200 1201 @Override toString()1202 public String toString() { 1203 return "mNextAppTransition=" + appTransitionToString(mNextAppTransition); 1204 } 1205 1206 /** 1207 * Returns the human readable name of a window transition. 1208 * 1209 * @param transition The window transition. 1210 * @return The transition symbolic name. 1211 */ appTransitionToString(int transition)1212 public static String appTransitionToString(int transition) { 1213 switch (transition) { 1214 case TRANSIT_UNSET: { 1215 return "TRANSIT_UNSET"; 1216 } 1217 case TRANSIT_NONE: { 1218 return "TRANSIT_NONE"; 1219 } 1220 case TRANSIT_ACTIVITY_OPEN: { 1221 return "TRANSIT_ACTIVITY_OPEN"; 1222 } 1223 case TRANSIT_ACTIVITY_CLOSE: { 1224 return "TRANSIT_ACTIVITY_CLOSE"; 1225 } 1226 case TRANSIT_TASK_OPEN: { 1227 return "TRANSIT_TASK_OPEN"; 1228 } 1229 case TRANSIT_TASK_CLOSE: { 1230 return "TRANSIT_TASK_CLOSE"; 1231 } 1232 case TRANSIT_TASK_TO_FRONT: { 1233 return "TRANSIT_TASK_TO_FRONT"; 1234 } 1235 case TRANSIT_TASK_TO_BACK: { 1236 return "TRANSIT_TASK_TO_BACK"; 1237 } 1238 case TRANSIT_WALLPAPER_CLOSE: { 1239 return "TRANSIT_WALLPAPER_CLOSE"; 1240 } 1241 case TRANSIT_WALLPAPER_OPEN: { 1242 return "TRANSIT_WALLPAPER_OPEN"; 1243 } 1244 case TRANSIT_WALLPAPER_INTRA_OPEN: { 1245 return "TRANSIT_WALLPAPER_INTRA_OPEN"; 1246 } 1247 case TRANSIT_WALLPAPER_INTRA_CLOSE: { 1248 return "TRANSIT_WALLPAPER_INTRA_CLOSE"; 1249 } 1250 case TRANSIT_TASK_OPEN_BEHIND: { 1251 return "TRANSIT_TASK_OPEN_BEHIND"; 1252 } 1253 default: { 1254 return "<UNKNOWN>"; 1255 } 1256 } 1257 } 1258 appStateToString()1259 private String appStateToString() { 1260 switch (mAppTransitionState) { 1261 case APP_STATE_IDLE: 1262 return "APP_STATE_IDLE"; 1263 case APP_STATE_READY: 1264 return "APP_STATE_READY"; 1265 case APP_STATE_RUNNING: 1266 return "APP_STATE_RUNNING"; 1267 case APP_STATE_TIMEOUT: 1268 return "APP_STATE_TIMEOUT"; 1269 default: 1270 return "unknown state=" + mAppTransitionState; 1271 } 1272 } 1273 transitTypeToString()1274 private String transitTypeToString() { 1275 switch (mNextAppTransitionType) { 1276 case NEXT_TRANSIT_TYPE_NONE: 1277 return "NEXT_TRANSIT_TYPE_NONE"; 1278 case NEXT_TRANSIT_TYPE_CUSTOM: 1279 return "NEXT_TRANSIT_TYPE_CUSTOM"; 1280 case NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE: 1281 return "NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE"; 1282 case NEXT_TRANSIT_TYPE_SCALE_UP: 1283 return "NEXT_TRANSIT_TYPE_SCALE_UP"; 1284 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP: 1285 return "NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP"; 1286 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN: 1287 return "NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN"; 1288 case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP: 1289 return "NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP"; 1290 case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN: 1291 return "NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN"; 1292 default: 1293 return "unknown type=" + mNextAppTransitionType; 1294 } 1295 } 1296 1297 @Override dump(PrintWriter pw, String prefix)1298 public void dump(PrintWriter pw, String prefix) { 1299 pw.print(prefix); pw.println(this); 1300 pw.print(prefix); pw.print("mAppTransitionState="); pw.println(appStateToString()); 1301 if (mNextAppTransitionType != NEXT_TRANSIT_TYPE_NONE) { 1302 pw.print(prefix); pw.print("mNextAppTransitionType="); 1303 pw.println(transitTypeToString()); 1304 } 1305 switch (mNextAppTransitionType) { 1306 case NEXT_TRANSIT_TYPE_CUSTOM: 1307 pw.print(prefix); pw.print("mNextAppTransitionPackage="); 1308 pw.println(mNextAppTransitionPackage); 1309 pw.print(prefix); pw.print("mNextAppTransitionEnter=0x"); 1310 pw.print(Integer.toHexString(mNextAppTransitionEnter)); 1311 pw.print(" mNextAppTransitionExit=0x"); 1312 pw.println(Integer.toHexString(mNextAppTransitionExit)); 1313 break; 1314 case NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE: 1315 pw.print(prefix); pw.print("mNextAppTransitionPackage="); 1316 pw.println(mNextAppTransitionPackage); 1317 pw.print(prefix); pw.print("mNextAppTransitionInPlace=0x"); 1318 pw.print(Integer.toHexString(mNextAppTransitionInPlace)); 1319 break; 1320 case NEXT_TRANSIT_TYPE_SCALE_UP: 1321 pw.print(prefix); pw.print("mNextAppTransitionStartX="); 1322 pw.print(mNextAppTransitionStartX); 1323 pw.print(" mNextAppTransitionStartY="); 1324 pw.println(mNextAppTransitionStartY); 1325 pw.print(prefix); pw.print("mNextAppTransitionStartWidth="); 1326 pw.print(mNextAppTransitionStartWidth); 1327 pw.print(" mNextAppTransitionStartHeight="); 1328 pw.println(mNextAppTransitionStartHeight); 1329 break; 1330 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP: 1331 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN: 1332 case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP: 1333 case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN: 1334 pw.print(prefix); pw.print("mNextAppTransitionThumbnail="); 1335 pw.print(mNextAppTransitionThumbnail); 1336 pw.print(" mNextAppTransitionStartX="); 1337 pw.print(mNextAppTransitionStartX); 1338 pw.print(" mNextAppTransitionStartY="); 1339 pw.println(mNextAppTransitionStartY); 1340 pw.print(prefix); pw.print("mNextAppTransitionStartWidth="); 1341 pw.print(mNextAppTransitionStartWidth); 1342 pw.print(" mNextAppTransitionStartHeight="); 1343 pw.println(mNextAppTransitionStartHeight); 1344 pw.print(prefix); pw.print("mNextAppTransitionScaleUp="); 1345 pw.println(mNextAppTransitionScaleUp); 1346 break; 1347 } 1348 if (mNextAppTransitionCallback != null) { 1349 pw.print(prefix); pw.print("mNextAppTransitionCallback="); 1350 pw.println(mNextAppTransitionCallback); 1351 } 1352 } 1353 setCurrentUser(int newUserId)1354 public void setCurrentUser(int newUserId) { 1355 mCurrentUserId = newUserId; 1356 } 1357 } 1358