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