AppTransition.java revision 4b71aa1f8a1a3b7189fd29241ea7c594ce01623c
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.app.ActivityOptions; 20import android.content.Context; 21import android.graphics.Bitmap; 22import android.graphics.Point; 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.Interpolator; 33import android.view.animation.ScaleAnimation; 34 35import com.android.internal.util.DumpUtils.Dump; 36import com.android.server.AttributeCache; 37import com.android.server.wm.WindowManagerService.H; 38 39import java.io.PrintWriter; 40 41// State management of app transitions. When we are preparing for a 42// transition, mNextAppTransition will be the kind of transition to 43// perform or TRANSIT_NONE if we are not waiting. If we are waiting, 44// mOpeningApps and mClosingApps are the lists of tokens that will be 45// made visible or hidden at the next transition. 46public class AppTransition implements Dump { 47 private static final String TAG = "AppTransition"; 48 private static final boolean DEBUG_APP_TRANSITIONS = 49 WindowManagerService.DEBUG_APP_TRANSITIONS; 50 private static final boolean DEBUG_ANIM = WindowManagerService.DEBUG_ANIM; 51 52 /** 53 * Bit mask that is set for all enter transition. 54 */ 55 public static final int TRANSIT_ENTER_MASK = 0x1000; 56 57 /** 58 * Bit mask that is set for all exit transitions. 59 */ 60 public static final int TRANSIT_EXIT_MASK = 0x2000; 61 62 /** Not set up for a transition. */ 63 public static final int TRANSIT_UNSET = -1; 64 /** No animation for transition. */ 65 public static final int TRANSIT_NONE = 0; 66 /** A window in a new activity is being opened on top of an existing one in the same task. */ 67 public static final int TRANSIT_ACTIVITY_OPEN = 6 | TRANSIT_ENTER_MASK; 68 /** The window in the top-most activity is being closed to reveal the 69 * previous activity in the same task. */ 70 public static final int TRANSIT_ACTIVITY_CLOSE = 7 | TRANSIT_EXIT_MASK; 71 /** A window in a new task is being opened on top of an existing one 72 * in another activity's task. */ 73 public static final int TRANSIT_TASK_OPEN = 8 | TRANSIT_ENTER_MASK; 74 /** A window in the top-most activity is being closed to reveal the 75 * previous activity in a different task. */ 76 public static final int TRANSIT_TASK_CLOSE = 9 | TRANSIT_EXIT_MASK; 77 /** A window in an existing task is being displayed on top of an existing one 78 * in another activity's task. */ 79 public static final int TRANSIT_TASK_TO_FRONT = 10 | TRANSIT_ENTER_MASK; 80 /** A window in an existing task is being put below all other tasks. */ 81 public static final int TRANSIT_TASK_TO_BACK = 11 | TRANSIT_EXIT_MASK; 82 /** A window in a new activity that doesn't have a wallpaper is being 83 * opened on top of one that does, effectively closing the wallpaper. */ 84 public static final int TRANSIT_WALLPAPER_CLOSE = 12 | TRANSIT_EXIT_MASK; 85 /** A window in a new activity that does have a wallpaper is being 86 * opened on one that didn't, effectively opening the wallpaper. */ 87 public static final int TRANSIT_WALLPAPER_OPEN = 13 | TRANSIT_ENTER_MASK; 88 /** A window in a new activity is being opened on top of an existing one, 89 * and both are on top of the wallpaper. */ 90 public static final int TRANSIT_WALLPAPER_INTRA_OPEN = 14 | TRANSIT_ENTER_MASK; 91 /** The window in the top-most activity is being closed to reveal the 92 * previous activity, and both are on top of he wallpaper. */ 93 public static final int TRANSIT_WALLPAPER_INTRA_CLOSE = 15 | TRANSIT_EXIT_MASK; 94 95 96 /** Fraction of animation at which the recents thumbnail becomes completely transparent */ 97 static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.25f; 98 99 static final long DEFAULT_APP_TRANSITION_DURATION = 250; 100 101 final Context mContext; 102 final Handler mH; 103 104 int mNextAppTransition = TRANSIT_UNSET; 105 int mNextAppTransitionType = ActivityOptions.ANIM_NONE; 106 String mNextAppTransitionPackage; 107 Bitmap mNextAppTransitionThumbnail; 108 // Used for thumbnail transitions. True if we're scaling up, false if scaling down 109 boolean mNextAppTransitionScaleUp; 110 IRemoteCallback mNextAppTransitionCallback; 111 int mNextAppTransitionEnter; 112 int mNextAppTransitionExit; 113 int mNextAppTransitionStartX; 114 int mNextAppTransitionStartY; 115 int mNextAppTransitionStartWidth; 116 int mNextAppTransitionStartHeight; 117 boolean mAppTransitionReady = false; 118 boolean mAppTransitionRunning = false; 119 boolean mAppTransitionTimeout = false; 120 121 final int mConfigShortAnimTime; 122 private final Interpolator mDecelerateInterpolator; 123 private final Interpolator mThumbnailFadeoutInterpolator; 124 125 AppTransition(Context context, Handler h) { 126 mContext = context; 127 mH = h; 128 mConfigShortAnimTime = context.getResources().getInteger( 129 com.android.internal.R.integer.config_shortAnimTime); 130 mDecelerateInterpolator = AnimationUtils.loadInterpolator(context, 131 com.android.internal.R.interpolator.decelerate_cubic); 132 mThumbnailFadeoutInterpolator = new Interpolator() { 133 @Override 134 public float getInterpolation(float input) { 135 // Linear response for first fraction, then complete after that. 136 if (input < RECENTS_THUMBNAIL_FADEOUT_FRACTION) { 137 return input / RECENTS_THUMBNAIL_FADEOUT_FRACTION; 138 } 139 return 1.0f; 140 } 141 }; 142 } 143 144 boolean isTransitionSet() { 145 return mNextAppTransition != TRANSIT_UNSET; 146 } 147 148 boolean isTransitionNone() { 149 return mNextAppTransition == TRANSIT_NONE; 150 } 151 152 boolean isTransitionEqual(int transit) { 153 return mNextAppTransition == transit; 154 } 155 156 int getAppTransition() { 157 return mNextAppTransition; 158 } 159 160 void setAppTransition(int transit) { 161 mNextAppTransition = transit; 162 } 163 164 boolean isReady() { 165 return mAppTransitionReady; 166 } 167 168 void setReady() { 169 mAppTransitionReady = true; 170 } 171 172 boolean isRunning() { 173 return mAppTransitionRunning; 174 } 175 176 void setRunning(boolean running) { 177 mAppTransitionRunning = running; 178 } 179 180 boolean isTimeout() { 181 return mAppTransitionTimeout; 182 } 183 184 void setTimeout(boolean timeout) { 185 mAppTransitionTimeout = timeout; 186 } 187 188 Bitmap getNextAppTransitionThumbnail() { 189 return mNextAppTransitionThumbnail; 190 } 191 192 void getStartingPoint(Point outPoint) { 193 outPoint.x = mNextAppTransitionStartX; 194 outPoint.y = mNextAppTransitionStartY; 195 } 196 197 int getType() { 198 return mNextAppTransitionType; 199 } 200 201 void prepare() { 202 mAppTransitionReady = false; 203 mAppTransitionTimeout = false; 204 } 205 206 void goodToGo() { 207 mNextAppTransition = TRANSIT_UNSET; 208 mAppTransitionReady = false; 209 mAppTransitionRunning = true; 210 mAppTransitionTimeout = false; 211 } 212 213 void clear() { 214 mNextAppTransitionType = ActivityOptions.ANIM_NONE; 215 mNextAppTransitionPackage = null; 216 mNextAppTransitionThumbnail = null; 217 } 218 219 private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) { 220 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: layout params pkg=" 221 + (lp != null ? lp.packageName : null) 222 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null)); 223 if (lp != null && lp.windowAnimations != 0) { 224 // If this is a system resource, don't try to load it from the 225 // application resources. It is nice to avoid loading application 226 // resources if we can. 227 String packageName = lp.packageName != null ? lp.packageName : "android"; 228 int resId = lp.windowAnimations; 229 if ((resId&0xFF000000) == 0x01000000) { 230 packageName = "android"; 231 } 232 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package=" 233 + packageName); 234 return AttributeCache.instance().get(packageName, resId, 235 com.android.internal.R.styleable.WindowAnimation); 236 } 237 return null; 238 } 239 240 private AttributeCache.Entry getCachedAnimations(String packageName, int resId) { 241 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: package=" 242 + packageName + " resId=0x" + Integer.toHexString(resId)); 243 if (packageName != null) { 244 if ((resId&0xFF000000) == 0x01000000) { 245 packageName = "android"; 246 } 247 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package=" 248 + packageName); 249 return AttributeCache.instance().get(packageName, resId, 250 com.android.internal.R.styleable.WindowAnimation); 251 } 252 return null; 253 } 254 255 Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) { 256 int anim = 0; 257 Context context = mContext; 258 if (animAttr >= 0) { 259 AttributeCache.Entry ent = getCachedAnimations(lp); 260 if (ent != null) { 261 context = ent.context; 262 anim = ent.array.getResourceId(animAttr, 0); 263 } 264 } 265 if (anim != 0) { 266 return AnimationUtils.loadAnimation(context, anim); 267 } 268 return null; 269 } 270 271 private Animation loadAnimation(String packageName, int resId) { 272 int anim = 0; 273 Context context = mContext; 274 if (resId >= 0) { 275 AttributeCache.Entry ent = getCachedAnimations(packageName, resId); 276 if (ent != null) { 277 context = ent.context; 278 anim = resId; 279 } 280 } 281 if (anim != 0) { 282 return AnimationUtils.loadAnimation(context, anim); 283 } 284 return null; 285 } 286 287 /** 288 * Compute the pivot point for an animation that is scaling from a small 289 * rect on screen to a larger rect. The pivot point varies depending on 290 * the distance between the inner and outer edges on both sides. This 291 * function computes the pivot point for one dimension. 292 * @param startPos Offset from left/top edge of outer rectangle to 293 * left/top edge of inner rectangle. 294 * @param finalScale The scaling factor between the size of the outer 295 * and inner rectangles. 296 */ 297 private static float computePivot(int startPos, float finalScale) { 298 final float denom = finalScale-1; 299 if (Math.abs(denom) < .0001f) { 300 return startPos; 301 } 302 return -startPos / denom; 303 } 304 305 private Animation createScaleUpAnimationLocked(int transit, boolean enter, 306 int appWidth, int appHeight) { 307 Animation a = null; 308 if (enter) { 309 // Entering app zooms out from the center of the initial rect. 310 float scaleW = mNextAppTransitionStartWidth / (float) appWidth; 311 float scaleH = mNextAppTransitionStartHeight / (float) appHeight; 312 Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1, 313 computePivot(mNextAppTransitionStartX, scaleW), 314 computePivot(mNextAppTransitionStartY, scaleH)); 315 scale.setInterpolator(mDecelerateInterpolator); 316 317 Animation alpha = new AlphaAnimation(0, 1); 318 alpha.setInterpolator(mThumbnailFadeoutInterpolator); 319 320 AnimationSet set = new AnimationSet(false); 321 set.addAnimation(scale); 322 set.addAnimation(alpha); 323 set.setDetachWallpaper(true); 324 a = set; 325 } else if (transit == TRANSIT_WALLPAPER_INTRA_OPEN || 326 transit == TRANSIT_WALLPAPER_INTRA_CLOSE) { 327 // If we are on top of the wallpaper, we need an animation that 328 // correctly handles the wallpaper staying static behind all of 329 // the animated elements. To do this, will just have the existing 330 // element fade out. 331 a = new AlphaAnimation(1, 0); 332 a.setDetachWallpaper(true); 333 } else { 334 // For normal animations, the exiting element just holds in place. 335 a = new AlphaAnimation(1, 1); 336 } 337 338 // Pick the desired duration. If this is an inter-activity transition, 339 // it is the standard duration for that. Otherwise we use the longer 340 // task transition duration. 341 final long duration; 342 switch (transit) { 343 case TRANSIT_ACTIVITY_OPEN: 344 case TRANSIT_ACTIVITY_CLOSE: 345 duration = mConfigShortAnimTime; 346 break; 347 default: 348 duration = DEFAULT_APP_TRANSITION_DURATION; 349 break; 350 } 351 a.setDuration(duration); 352 a.setFillAfter(true); 353 a.setInterpolator(mDecelerateInterpolator); 354 a.initialize(appWidth, appHeight, appWidth, appHeight); 355 return a; 356 } 357 358 Animation createThumbnailAnimationLocked(int transit, boolean enter, boolean thumb, 359 int appWidth, int appHeight) { 360 Animation a; 361 final int thumbWidthI = mNextAppTransitionThumbnail.getWidth(); 362 final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1; 363 final int thumbHeightI = mNextAppTransitionThumbnail.getHeight(); 364 final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1; 365 if (thumb) { 366 // Animation for zooming thumbnail from its initial size to 367 // filling the screen. 368 if (mNextAppTransitionScaleUp) { 369 float scaleW = appWidth / thumbWidth; 370 float scaleH = appHeight / thumbHeight; 371 Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH, 372 computePivot(mNextAppTransitionStartX, 1 / scaleW), 373 computePivot(mNextAppTransitionStartY, 1 / scaleH)); 374 scale.setInterpolator(mDecelerateInterpolator); 375 376 Animation alpha = new AlphaAnimation(1, 0); 377 alpha.setInterpolator(mThumbnailFadeoutInterpolator); 378 379 // This AnimationSet uses the Interpolators assigned above. 380 AnimationSet set = new AnimationSet(false); 381 set.addAnimation(scale); 382 set.addAnimation(alpha); 383 a = set; 384 } else { 385 float scaleW = appWidth / thumbWidth; 386 float scaleH = appHeight / thumbHeight; 387 a = new ScaleAnimation(scaleW, 1, scaleH, 1, 388 computePivot(mNextAppTransitionStartX, 1 / scaleW), 389 computePivot(mNextAppTransitionStartY, 1 / scaleH)); 390 } 391 } else if (enter) { 392 // Entering app zooms out from the center of the thumbnail. 393 if (mNextAppTransitionScaleUp) { 394 float scaleW = thumbWidth / appWidth; 395 float scaleH = thumbHeight / appHeight; 396 a = new ScaleAnimation(scaleW, 1, scaleH, 1, 397 computePivot(mNextAppTransitionStartX, scaleW), 398 computePivot(mNextAppTransitionStartY, scaleH)); 399 } else { 400 // noop animation 401 a = new AlphaAnimation(1, 1); 402 } 403 } else { 404 // Exiting app 405 if (mNextAppTransitionScaleUp) { 406 if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) { 407 // Fade out while bringing up selected activity. This keeps the 408 // current activity from showing through a launching wallpaper 409 // activity. 410 a = new AlphaAnimation(1, 0); 411 } else { 412 // noop animation 413 a = new AlphaAnimation(1, 1); 414 } 415 } else { 416 float scaleW = thumbWidth / appWidth; 417 float scaleH = thumbHeight / appHeight; 418 Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH, 419 computePivot(mNextAppTransitionStartX, scaleW), 420 computePivot(mNextAppTransitionStartY, scaleH)); 421 422 Animation alpha = new AlphaAnimation(1, 0); 423 424 AnimationSet set = new AnimationSet(true); 425 set.addAnimation(scale); 426 set.addAnimation(alpha); 427 set.setZAdjustment(Animation.ZORDER_TOP); 428 a = set; 429 } 430 } 431 432 // Pick the desired duration. If this is an inter-activity transition, 433 // it is the standard duration for that. Otherwise we use the longer 434 // task transition duration. 435 final long duration; 436 switch (transit) { 437 case TRANSIT_ACTIVITY_OPEN: 438 case TRANSIT_ACTIVITY_CLOSE: 439 duration = mConfigShortAnimTime; 440 break; 441 default: 442 duration = DEFAULT_APP_TRANSITION_DURATION; 443 break; 444 } 445 a.setDuration(duration); 446 a.setFillAfter(true); 447 a.setInterpolator(mDecelerateInterpolator); 448 a.initialize(appWidth, appHeight, appWidth, appHeight); 449 return a; 450 } 451 452 453 Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, 454 int appWidth, int appHeight) { 455 Animation a; 456 if (mNextAppTransitionType == ActivityOptions.ANIM_CUSTOM) { 457 a = loadAnimation(mNextAppTransitionPackage, enter ? 458 mNextAppTransitionEnter : mNextAppTransitionExit); 459 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 460 "applyAnimation:" 461 + " anim=" + a + " nextAppTransition=ANIM_CUSTOM" 462 + " transit=" + transit + " isEntrance=" + enter 463 + " Callers=" + Debug.getCallers(3)); 464 } else if (mNextAppTransitionType == ActivityOptions.ANIM_SCALE_UP) { 465 a = createScaleUpAnimationLocked(transit, enter, appWidth, appHeight); 466 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 467 "applyAnimation:" 468 + " anim=" + a + " nextAppTransition=ANIM_SCALE_UP" 469 + " transit=" + transit + " isEntrance=" + enter 470 + " Callers=" + Debug.getCallers(3)); 471 } else if (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_SCALE_UP || 472 mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN) { 473 mNextAppTransitionScaleUp = 474 (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_SCALE_UP); 475 a = createThumbnailAnimationLocked(transit, enter, false, appWidth, appHeight); 476 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) { 477 String animName = mNextAppTransitionScaleUp ? 478 "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN"; 479 Slog.v(TAG, "applyAnimation:" 480 + " anim=" + a + " nextAppTransition=" + animName 481 + " transit=" + transit + " isEntrance=" + enter 482 + " Callers=" + Debug.getCallers(3)); 483 } 484 } else { 485 int animAttr = 0; 486 switch (transit) { 487 case TRANSIT_ACTIVITY_OPEN: 488 animAttr = enter 489 ? com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation 490 : com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation; 491 break; 492 case TRANSIT_ACTIVITY_CLOSE: 493 animAttr = enter 494 ? com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation 495 : com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation; 496 break; 497 case TRANSIT_TASK_OPEN: 498 animAttr = enter 499 ? com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation 500 : com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation; 501 break; 502 case TRANSIT_TASK_CLOSE: 503 animAttr = enter 504 ? com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation 505 : com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation; 506 break; 507 case TRANSIT_TASK_TO_FRONT: 508 animAttr = enter 509 ? com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation 510 : com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation; 511 break; 512 case TRANSIT_TASK_TO_BACK: 513 animAttr = enter 514 ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation 515 : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation; 516 break; 517 case TRANSIT_WALLPAPER_OPEN: 518 animAttr = enter 519 ? com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation 520 : com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation; 521 break; 522 case TRANSIT_WALLPAPER_CLOSE: 523 animAttr = enter 524 ? com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation 525 : com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation; 526 break; 527 case TRANSIT_WALLPAPER_INTRA_OPEN: 528 animAttr = enter 529 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation 530 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation; 531 break; 532 case TRANSIT_WALLPAPER_INTRA_CLOSE: 533 animAttr = enter 534 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation 535 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation; 536 break; 537 } 538 a = animAttr != 0 ? loadAnimation(lp, animAttr) : null; 539 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 540 "applyAnimation:" 541 + " anim=" + a 542 + " animAttr=0x" + Integer.toHexString(animAttr) 543 + " transit=" + transit + " isEntrance=" + enter 544 + " Callers=" + Debug.getCallers(3)); 545 } 546 return a; 547 } 548 549 void postAnimationCallback() { 550 if (mNextAppTransitionCallback != null) { 551 mH.sendMessage(mH.obtainMessage(H.DO_ANIMATION_CALLBACK, mNextAppTransitionCallback)); 552 mNextAppTransitionCallback = null; 553 } 554 } 555 556 void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim, 557 IRemoteCallback startedCallback) { 558 if (isTransitionSet()) { 559 mNextAppTransitionType = ActivityOptions.ANIM_CUSTOM; 560 mNextAppTransitionPackage = packageName; 561 mNextAppTransitionThumbnail = null; 562 mNextAppTransitionEnter = enterAnim; 563 mNextAppTransitionExit = exitAnim; 564 postAnimationCallback(); 565 mNextAppTransitionCallback = startedCallback; 566 } else { 567 postAnimationCallback(); 568 } 569 } 570 571 void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, 572 int startHeight) { 573 if (isTransitionSet()) { 574 mNextAppTransitionType = ActivityOptions.ANIM_SCALE_UP; 575 mNextAppTransitionPackage = null; 576 mNextAppTransitionThumbnail = null; 577 mNextAppTransitionStartX = startX; 578 mNextAppTransitionStartY = startY; 579 mNextAppTransitionStartWidth = startWidth; 580 mNextAppTransitionStartHeight = startHeight; 581 postAnimationCallback(); 582 mNextAppTransitionCallback = null; 583 } 584 } 585 586 void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY, 587 IRemoteCallback startedCallback, boolean scaleUp) { 588 if (isTransitionSet()) { 589 mNextAppTransitionType = scaleUp ? ActivityOptions.ANIM_THUMBNAIL_SCALE_UP 590 : ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN; 591 mNextAppTransitionPackage = null; 592 mNextAppTransitionThumbnail = srcThumb; 593 mNextAppTransitionScaleUp = scaleUp; 594 mNextAppTransitionStartX = startX; 595 mNextAppTransitionStartY = startY; 596 postAnimationCallback(); 597 mNextAppTransitionCallback = startedCallback; 598 } else { 599 postAnimationCallback(); 600 } 601 } 602 603 @Override 604 public String toString() { 605 return "mNextAppTransition=0x" + Integer.toHexString(mNextAppTransition); 606 } 607 608 /** 609 * Returns the human readable name of a window transition. 610 * 611 * @param transition The window transition. 612 * @return The transition symbolic name. 613 */ 614 public static String appTransitionToString(int transition) { 615 switch (transition) { 616 case TRANSIT_UNSET: { 617 return "TRANSIT_UNSET"; 618 } 619 case TRANSIT_NONE: { 620 return "TRANSIT_NONE"; 621 } 622 case TRANSIT_EXIT_MASK: { 623 return "TRANSIT_EXIT_MASK"; 624 } 625 case TRANSIT_ACTIVITY_OPEN: { 626 return "TRANSIT_ACTIVITY_OPEN"; 627 } 628 case TRANSIT_ACTIVITY_CLOSE: { 629 return "TRANSIT_ACTIVITY_CLOSE"; 630 } 631 case TRANSIT_TASK_OPEN: { 632 return "TRANSIT_TASK_OPEN"; 633 } 634 case TRANSIT_TASK_CLOSE: { 635 return "TRANSIT_TASK_CLOSE"; 636 } 637 case TRANSIT_TASK_TO_FRONT: { 638 return "TRANSIT_TASK_TO_FRONT"; 639 } 640 case TRANSIT_TASK_TO_BACK: { 641 return "TRANSIT_TASK_TO_BACK"; 642 } 643 case TRANSIT_WALLPAPER_CLOSE: { 644 return "TRANSIT_WALLPAPER_CLOSE"; 645 } 646 case TRANSIT_WALLPAPER_OPEN: { 647 return "TRANSIT_WALLPAPER_OPEN"; 648 } 649 case TRANSIT_WALLPAPER_INTRA_OPEN: { 650 return "TRANSIT_WALLPAPER_INTRA_OPEN"; 651 } 652 case TRANSIT_WALLPAPER_INTRA_CLOSE: { 653 return "TRANSIT_WALLPAPER_INTRA_CLOSE"; 654 } 655 default: { 656 return "<UNKNOWN>"; 657 } 658 } 659 } 660 661 @Override 662 public void dump(PrintWriter pw) { 663 pw.print(" " + this); 664 pw.print(" mAppTransitionReady="); pw.println(mAppTransitionReady); 665 pw.print(" mAppTransitionRunning="); pw.print(mAppTransitionRunning); 666 pw.print(" mAppTransitionTimeout="); pw.println(mAppTransitionTimeout); 667 if (mNextAppTransitionType != ActivityOptions.ANIM_NONE) { 668 pw.print(" mNextAppTransitionType="); pw.println(mNextAppTransitionType); 669 } 670 switch (mNextAppTransitionType) { 671 case ActivityOptions.ANIM_CUSTOM: 672 pw.print(" mNextAppTransitionPackage="); 673 pw.println(mNextAppTransitionPackage); 674 pw.print(" mNextAppTransitionEnter=0x"); 675 pw.print(Integer.toHexString(mNextAppTransitionEnter)); 676 pw.print(" mNextAppTransitionExit=0x"); 677 pw.println(Integer.toHexString(mNextAppTransitionExit)); 678 break; 679 case ActivityOptions.ANIM_SCALE_UP: 680 pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX); 681 pw.print(" mNextAppTransitionStartY="); 682 pw.println(mNextAppTransitionStartY); 683 pw.print(" mNextAppTransitionStartWidth="); 684 pw.print(mNextAppTransitionStartWidth); 685 pw.print(" mNextAppTransitionStartHeight="); 686 pw.println(mNextAppTransitionStartHeight); 687 break; 688 case ActivityOptions.ANIM_THUMBNAIL_SCALE_UP: 689 case ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN: 690 pw.print(" mNextAppTransitionThumbnail="); 691 pw.print(mNextAppTransitionThumbnail); 692 pw.print(" mNextAppTransitionStartX="); 693 pw.print(mNextAppTransitionStartX); 694 pw.print(" mNextAppTransitionStartY="); 695 pw.println(mNextAppTransitionStartY); 696 pw.print(" mNextAppTransitionScaleUp="); pw.println(mNextAppTransitionScaleUp); 697 break; 698 } 699 if (mNextAppTransitionCallback != null) { 700 pw.print(" mNextAppTransitionCallback="); 701 pw.println(mNextAppTransitionCallback); 702 } 703 } 704} 705