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