AppTransition.java revision ab79fce2e71b6816b2b88b826ca723b3591f1e26
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 17package com.android.server.wm; 18 19import android.content.Context; 20import android.content.res.Configuration; 21import android.graphics.Bitmap; 22import android.graphics.Rect; 23import android.os.Debug; 24import android.os.Handler; 25import android.os.IRemoteCallback; 26import android.util.Slog; 27import android.view.WindowManager; 28import android.view.animation.AlphaAnimation; 29import android.view.animation.Animation; 30import android.view.animation.AnimationSet; 31import android.view.animation.AnimationUtils; 32import android.view.animation.ClipRectAnimation; 33import android.view.animation.Interpolator; 34import android.view.animation.ScaleAnimation; 35import android.view.animation.TranslateAnimation; 36import com.android.internal.util.DumpUtils.Dump; 37import com.android.server.AttributeCache; 38import com.android.server.wm.WindowManagerService.H; 39 40import java.io.PrintWriter; 41 42import static com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation; 43import static com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation; 44import static com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation; 45import static com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation; 46import static com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation; 47import static com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation; 48import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindTargetAnimation; 49import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindSourceAnimation; 50import static com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation; 51import static com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation; 52import static com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation; 53import static com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation; 54import static com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation; 55import static com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation; 56import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation; 57import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation; 58import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation; 59import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation; 60import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation; 61import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation; 62import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation; 63import 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. 70public 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 int duration = Math.max(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION, 695 THUMBNAIL_APP_TRANSITION_DURATION); 696 return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, duration, 697 mThumbnailFastOutSlowInInterpolator); 698 } 699 700 /** 701 * This animation runs for the thumbnail that gets cross faded with the enter/exit activity 702 * when a thumbnail is specified with the activity options. 703 */ 704 Animation createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit) { 705 Animation a; 706 final int thumbWidthI = mNextAppTransitionThumbnail.getWidth(); 707 final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1; 708 final int thumbHeightI = mNextAppTransitionThumbnail.getHeight(); 709 final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1; 710 711 if (mNextAppTransitionScaleUp) { 712 // Animation for the thumbnail zooming from its initial size to the full screen 713 float scaleW = appWidth / thumbWidth; 714 float scaleH = appHeight / thumbHeight; 715 Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH, 716 computePivot(mNextAppTransitionStartX, 1 / scaleW), 717 computePivot(mNextAppTransitionStartY, 1 / scaleH)); 718 scale.setInterpolator(mDecelerateInterpolator); 719 720 Animation alpha = new AlphaAnimation(1, 0); 721 alpha.setInterpolator(mThumbnailFadeOutInterpolator); 722 723 // This AnimationSet uses the Interpolators assigned above. 724 AnimationSet set = new AnimationSet(false); 725 set.addAnimation(scale); 726 set.addAnimation(alpha); 727 a = set; 728 } else { 729 // Animation for the thumbnail zooming down from the full screen to its final size 730 float scaleW = appWidth / thumbWidth; 731 float scaleH = appHeight / thumbHeight; 732 a = new ScaleAnimation(scaleW, 1, scaleH, 1, 733 computePivot(mNextAppTransitionStartX, 1 / scaleW), 734 computePivot(mNextAppTransitionStartY, 1 / scaleH)); 735 } 736 737 return prepareThumbnailAnimation(a, appWidth, appHeight, transit); 738 } 739 740 /** 741 * This animation is created when we are doing a thumbnail transition, for the activity that is 742 * leaving, and the activity that is entering. 743 */ 744 Animation createThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth, 745 int appHeight, int transit) { 746 Animation a; 747 final int thumbWidthI = mNextAppTransitionThumbnail.getWidth(); 748 final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1; 749 final int thumbHeightI = mNextAppTransitionThumbnail.getHeight(); 750 final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1; 751 752 switch (thumbTransitState) { 753 case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: { 754 // Entering app scales up with the thumbnail 755 float scaleW = thumbWidth / appWidth; 756 float scaleH = thumbHeight / appHeight; 757 a = new ScaleAnimation(scaleW, 1, scaleH, 1, 758 computePivot(mNextAppTransitionStartX, scaleW), 759 computePivot(mNextAppTransitionStartY, scaleH)); 760 break; 761 } 762 case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: { 763 // Exiting app while the thumbnail is scaling up should fade or stay in place 764 if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) { 765 // Fade out while bringing up selected activity. This keeps the 766 // current activity from showing through a launching wallpaper 767 // activity. 768 a = new AlphaAnimation(1, 0); 769 } else { 770 // noop animation 771 a = new AlphaAnimation(1, 1); 772 } 773 break; 774 } 775 case THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN: { 776 // Entering the other app, it should just be visible while we scale the thumbnail 777 // down above it 778 a = new AlphaAnimation(1, 1); 779 break; 780 } 781 case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: { 782 // Exiting the current app, the app should scale down with the thumbnail 783 float scaleW = thumbWidth / appWidth; 784 float scaleH = thumbHeight / appHeight; 785 Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH, 786 computePivot(mNextAppTransitionStartX, scaleW), 787 computePivot(mNextAppTransitionStartY, scaleH)); 788 789 Animation alpha = new AlphaAnimation(1, 0); 790 791 AnimationSet set = new AnimationSet(true); 792 set.addAnimation(scale); 793 set.addAnimation(alpha); 794 set.setZAdjustment(Animation.ZORDER_TOP); 795 a = set; 796 break; 797 } 798 default: 799 throw new RuntimeException("Invalid thumbnail transition state"); 800 } 801 802 return prepareThumbnailAnimation(a, appWidth, appHeight, transit); 803 } 804 805 806 Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, 807 int appWidth, int appHeight, int orientation, Rect containingFrame, Rect contentInsets, 808 boolean isFullScreen, boolean isVoiceInteraction) { 809 Animation a; 810 if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_OPEN 811 || transit == TRANSIT_TASK_OPEN 812 || transit == TRANSIT_TASK_TO_FRONT)) { 813 a = loadAnimationRes(lp, enter 814 ? com.android.internal.R.anim.voice_activity_open_enter 815 : com.android.internal.R.anim.voice_activity_open_exit); 816 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 817 "applyAnimation voice:" 818 + " anim=" + a + " transit=" + transit + " isEntrance=" + enter 819 + " Callers=" + Debug.getCallers(3)); 820 } else if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_CLOSE 821 || transit == TRANSIT_TASK_CLOSE 822 || transit == TRANSIT_TASK_TO_BACK)) { 823 a = loadAnimationRes(lp, enter 824 ? com.android.internal.R.anim.voice_activity_close_enter 825 : com.android.internal.R.anim.voice_activity_close_exit); 826 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 827 "applyAnimation voice:" 828 + " anim=" + a + " transit=" + transit + " isEntrance=" + enter 829 + " Callers=" + Debug.getCallers(3)); 830 } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) { 831 a = loadAnimationRes(mNextAppTransitionPackage, enter ? 832 mNextAppTransitionEnter : mNextAppTransitionExit); 833 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 834 "applyAnimation:" 835 + " anim=" + a + " nextAppTransition=ANIM_CUSTOM" 836 + " transit=" + transit + " isEntrance=" + enter 837 + " Callers=" + Debug.getCallers(3)); 838 } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_SCALE_UP) { 839 a = createScaleUpAnimationLocked(transit, enter, appWidth, appHeight); 840 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 841 "applyAnimation:" 842 + " anim=" + a + " nextAppTransition=ANIM_SCALE_UP" 843 + " transit=" + transit + " isEntrance=" + enter 844 + " Callers=" + Debug.getCallers(3)); 845 } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP || 846 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) { 847 mNextAppTransitionScaleUp = 848 (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP); 849 a = createThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter), 850 appWidth, appHeight, transit); 851 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) { 852 String animName = mNextAppTransitionScaleUp ? 853 "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN"; 854 Slog.v(TAG, "applyAnimation:" 855 + " anim=" + a + " nextAppTransition=" + animName 856 + " transit=" + transit + " isEntrance=" + enter 857 + " Callers=" + Debug.getCallers(3)); 858 } 859 } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP || 860 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN) { 861 mNextAppTransitionScaleUp = 862 (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP); 863 a = createAspectScaledThumbnailEnterExitAnimationLocked( 864 getThumbnailTransitionState(enter), appWidth, appHeight, orientation, 865 transit, containingFrame, contentInsets, isFullScreen); 866 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) { 867 String animName = mNextAppTransitionScaleUp ? 868 "ANIM_THUMBNAIL_ASPECT_SCALE_UP" : "ANIM_THUMBNAIL_ASPECT_SCALE_DOWN"; 869 Slog.v(TAG, "applyAnimation:" 870 + " anim=" + a + " nextAppTransition=" + animName 871 + " transit=" + transit + " isEntrance=" + enter 872 + " Callers=" + Debug.getCallers(3)); 873 } 874 } else { 875 int animAttr = 0; 876 switch (transit) { 877 case TRANSIT_ACTIVITY_OPEN: 878 animAttr = enter 879 ? WindowAnimation_activityOpenEnterAnimation 880 : WindowAnimation_activityOpenExitAnimation; 881 break; 882 case TRANSIT_ACTIVITY_CLOSE: 883 animAttr = enter 884 ? WindowAnimation_activityCloseEnterAnimation 885 : WindowAnimation_activityCloseExitAnimation; 886 break; 887 case TRANSIT_TASK_OPEN: 888 animAttr = enter 889 ? WindowAnimation_taskOpenEnterAnimation 890 : WindowAnimation_taskOpenExitAnimation; 891 break; 892 case TRANSIT_TASK_CLOSE: 893 animAttr = enter 894 ? WindowAnimation_taskCloseEnterAnimation 895 : WindowAnimation_taskCloseExitAnimation; 896 break; 897 case TRANSIT_TASK_TO_FRONT: 898 animAttr = enter 899 ? WindowAnimation_taskToFrontEnterAnimation 900 : WindowAnimation_taskToFrontExitAnimation; 901 break; 902 case TRANSIT_TASK_TO_BACK: 903 animAttr = enter 904 ? WindowAnimation_taskToBackEnterAnimation 905 : WindowAnimation_taskToBackExitAnimation; 906 break; 907 case TRANSIT_WALLPAPER_OPEN: 908 animAttr = enter 909 ? WindowAnimation_wallpaperOpenEnterAnimation 910 : WindowAnimation_wallpaperOpenExitAnimation; 911 break; 912 case TRANSIT_WALLPAPER_CLOSE: 913 animAttr = enter 914 ? WindowAnimation_wallpaperCloseEnterAnimation 915 : WindowAnimation_wallpaperCloseExitAnimation; 916 break; 917 case TRANSIT_WALLPAPER_INTRA_OPEN: 918 animAttr = enter 919 ? WindowAnimation_wallpaperIntraOpenEnterAnimation 920 : WindowAnimation_wallpaperIntraOpenExitAnimation; 921 break; 922 case TRANSIT_WALLPAPER_INTRA_CLOSE: 923 animAttr = enter 924 ? WindowAnimation_wallpaperIntraCloseEnterAnimation 925 : WindowAnimation_wallpaperIntraCloseExitAnimation; 926 break; 927 case TRANSIT_TASK_OPEN_BEHIND: 928 animAttr = enter 929 ? WindowAnimation_launchTaskBehindSourceAnimation 930 : WindowAnimation_launchTaskBehindTargetAnimation; 931 } 932 a = animAttr != 0 ? loadAnimationAttr(lp, animAttr) : null; 933 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 934 "applyAnimation:" 935 + " anim=" + a 936 + " animAttr=0x" + Integer.toHexString(animAttr) 937 + " transit=" + transit + " isEntrance=" + enter 938 + " Callers=" + Debug.getCallers(3)); 939 } 940 return a; 941 } 942 943 void postAnimationCallback() { 944 if (mNextAppTransitionCallback != null) { 945 mH.sendMessage(mH.obtainMessage(H.DO_ANIMATION_CALLBACK, mNextAppTransitionCallback)); 946 mNextAppTransitionCallback = null; 947 } 948 } 949 950 void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim, 951 IRemoteCallback startedCallback) { 952 if (isTransitionSet()) { 953 mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM; 954 mNextAppTransitionPackage = packageName; 955 mNextAppTransitionThumbnail = null; 956 mNextAppTransitionEnter = enterAnim; 957 mNextAppTransitionExit = exitAnim; 958 postAnimationCallback(); 959 mNextAppTransitionCallback = startedCallback; 960 } else { 961 postAnimationCallback(); 962 } 963 } 964 965 void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, 966 int startHeight) { 967 if (isTransitionSet()) { 968 mNextAppTransitionType = NEXT_TRANSIT_TYPE_SCALE_UP; 969 mNextAppTransitionPackage = null; 970 mNextAppTransitionThumbnail = null; 971 mNextAppTransitionStartX = startX; 972 mNextAppTransitionStartY = startY; 973 mNextAppTransitionStartWidth = startWidth; 974 mNextAppTransitionStartHeight = startHeight; 975 postAnimationCallback(); 976 mNextAppTransitionCallback = null; 977 } 978 } 979 980 void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY, 981 IRemoteCallback startedCallback, boolean scaleUp) { 982 if (isTransitionSet()) { 983 mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP 984 : NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN; 985 mNextAppTransitionPackage = null; 986 mNextAppTransitionThumbnail = srcThumb; 987 mNextAppTransitionScaleUp = scaleUp; 988 mNextAppTransitionStartX = startX; 989 mNextAppTransitionStartY = startY; 990 postAnimationCallback(); 991 mNextAppTransitionCallback = startedCallback; 992 } else { 993 postAnimationCallback(); 994 } 995 } 996 997 void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX, int startY, 998 int targetWidth, int targetHeight, IRemoteCallback startedCallback, boolean scaleUp) { 999 if (isTransitionSet()) { 1000 mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP 1001 : NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN; 1002 mNextAppTransitionPackage = null; 1003 mNextAppTransitionThumbnail = srcThumb; 1004 mNextAppTransitionScaleUp = scaleUp; 1005 mNextAppTransitionStartX = startX; 1006 mNextAppTransitionStartY = startY; 1007 mNextAppTransitionStartWidth = targetWidth; 1008 mNextAppTransitionStartHeight = targetHeight; 1009 postAnimationCallback(); 1010 mNextAppTransitionCallback = startedCallback; 1011 } else { 1012 postAnimationCallback(); 1013 } 1014 } 1015 1016 @Override 1017 public String toString() { 1018 return "mNextAppTransition=0x" + Integer.toHexString(mNextAppTransition); 1019 } 1020 1021 /** 1022 * Returns the human readable name of a window transition. 1023 * 1024 * @param transition The window transition. 1025 * @return The transition symbolic name. 1026 */ 1027 public static String appTransitionToString(int transition) { 1028 switch (transition) { 1029 case TRANSIT_UNSET: { 1030 return "TRANSIT_UNSET"; 1031 } 1032 case TRANSIT_NONE: { 1033 return "TRANSIT_NONE"; 1034 } 1035 case TRANSIT_ACTIVITY_OPEN: { 1036 return "TRANSIT_ACTIVITY_OPEN"; 1037 } 1038 case TRANSIT_ACTIVITY_CLOSE: { 1039 return "TRANSIT_ACTIVITY_CLOSE"; 1040 } 1041 case TRANSIT_TASK_OPEN: { 1042 return "TRANSIT_TASK_OPEN"; 1043 } 1044 case TRANSIT_TASK_CLOSE: { 1045 return "TRANSIT_TASK_CLOSE"; 1046 } 1047 case TRANSIT_TASK_TO_FRONT: { 1048 return "TRANSIT_TASK_TO_FRONT"; 1049 } 1050 case TRANSIT_TASK_TO_BACK: { 1051 return "TRANSIT_TASK_TO_BACK"; 1052 } 1053 case TRANSIT_WALLPAPER_CLOSE: { 1054 return "TRANSIT_WALLPAPER_CLOSE"; 1055 } 1056 case TRANSIT_WALLPAPER_OPEN: { 1057 return "TRANSIT_WALLPAPER_OPEN"; 1058 } 1059 case TRANSIT_WALLPAPER_INTRA_OPEN: { 1060 return "TRANSIT_WALLPAPER_INTRA_OPEN"; 1061 } 1062 case TRANSIT_WALLPAPER_INTRA_CLOSE: { 1063 return "TRANSIT_WALLPAPER_INTRA_CLOSE"; 1064 } 1065 case TRANSIT_TASK_OPEN_BEHIND: { 1066 return "TRANSIT_TASK_OPEN_BEHIND"; 1067 } 1068 default: { 1069 return "<UNKNOWN>"; 1070 } 1071 } 1072 } 1073 1074 private String appStateToString() { 1075 switch (mAppTransitionState) { 1076 case APP_STATE_IDLE: 1077 return "APP_STATE_IDLE"; 1078 case APP_STATE_READY: 1079 return "APP_STATE_READY"; 1080 case APP_STATE_RUNNING: 1081 return "APP_STATE_RUNNING"; 1082 case APP_STATE_TIMEOUT: 1083 return "APP_STATE_TIMEOUT"; 1084 default: 1085 return "unknown state=" + mAppTransitionState; 1086 } 1087 } 1088 1089 private String transitTypeToString() { 1090 switch (mNextAppTransitionType) { 1091 case NEXT_TRANSIT_TYPE_NONE: 1092 return "NEXT_TRANSIT_TYPE_NONE"; 1093 case NEXT_TRANSIT_TYPE_CUSTOM: 1094 return "NEXT_TRANSIT_TYPE_CUSTOM"; 1095 case NEXT_TRANSIT_TYPE_SCALE_UP: 1096 return "NEXT_TRANSIT_TYPE_SCALE_UP"; 1097 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP: 1098 return "NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP"; 1099 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN: 1100 return "NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN"; 1101 case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP: 1102 return "NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP"; 1103 case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN: 1104 return "NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN"; 1105 default: 1106 return "unknown type=" + mNextAppTransitionType; 1107 } 1108 } 1109 1110 @Override 1111 public void dump(PrintWriter pw) { 1112 pw.print(" " + this); 1113 pw.print(" mAppTransitionState="); pw.println(appStateToString()); 1114 if (mNextAppTransitionType != NEXT_TRANSIT_TYPE_NONE) { 1115 pw.print(" mNextAppTransitionType="); pw.println(transitTypeToString()); 1116 } 1117 switch (mNextAppTransitionType) { 1118 case NEXT_TRANSIT_TYPE_CUSTOM: 1119 pw.print(" mNextAppTransitionPackage="); 1120 pw.println(mNextAppTransitionPackage); 1121 pw.print(" mNextAppTransitionEnter=0x"); 1122 pw.print(Integer.toHexString(mNextAppTransitionEnter)); 1123 pw.print(" mNextAppTransitionExit=0x"); 1124 pw.println(Integer.toHexString(mNextAppTransitionExit)); 1125 break; 1126 case NEXT_TRANSIT_TYPE_SCALE_UP: 1127 pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX); 1128 pw.print(" mNextAppTransitionStartY="); 1129 pw.println(mNextAppTransitionStartY); 1130 pw.print(" mNextAppTransitionStartWidth="); 1131 pw.print(mNextAppTransitionStartWidth); 1132 pw.print(" mNextAppTransitionStartHeight="); 1133 pw.println(mNextAppTransitionStartHeight); 1134 break; 1135 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP: 1136 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN: 1137 case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP: 1138 case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN: 1139 pw.print(" mNextAppTransitionThumbnail="); 1140 pw.print(mNextAppTransitionThumbnail); 1141 pw.print(" mNextAppTransitionStartX="); 1142 pw.print(mNextAppTransitionStartX); 1143 pw.print(" mNextAppTransitionStartY="); 1144 pw.println(mNextAppTransitionStartY); 1145 pw.print(" mNextAppTransitionStartWidth="); 1146 pw.print(mNextAppTransitionStartWidth); 1147 pw.print(" mNextAppTransitionStartHeight="); 1148 pw.println(mNextAppTransitionStartHeight); 1149 pw.print(" mNextAppTransitionScaleUp="); pw.println(mNextAppTransitionScaleUp); 1150 break; 1151 } 1152 if (mNextAppTransitionCallback != null) { 1153 pw.print(" mNextAppTransitionCallback="); 1154 pw.println(mNextAppTransitionCallback); 1155 } 1156 } 1157 1158 public void setCurrentUser(int newUserId) { 1159 mCurrentUserId = newUserId; 1160 } 1161} 1162