blob: 7736c9364f64fe069ba7ff43a9f6a499c6a6c581 [file] [log] [blame]
Craig Mautner164d4bb2012-11-26 13:51:23 -08001/*
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.WindowManagerPolicy;
29import android.view.animation.AlphaAnimation;
30import android.view.animation.Animation;
31import android.view.animation.AnimationSet;
32import android.view.animation.AnimationUtils;
Craig Mautner164d4bb2012-11-26 13:51:23 -080033import android.view.animation.Interpolator;
34import android.view.animation.ScaleAnimation;
35
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 android.view.WindowManagerPolicy.TRANSIT_NONE;
43import static android.view.WindowManagerPolicy.TRANSIT_UNSET;
44
45// State management of app transitions. When we are preparing for a
46// transition, mNextAppTransition will be the kind of transition to
47// perform or TRANSIT_NONE if we are not waiting. If we are waiting,
48// mOpeningApps and mClosingApps are the lists of tokens that will be
49// made visible or hidden at the next transition.
50public class AppTransition implements Dump {
51 private static final String TAG = "AppTransition";
Craig Mautner321bdf52012-12-18 09:53:24 -080052 private static final boolean DEBUG_APP_TRANSITIONS =
53 WindowManagerService.DEBUG_APP_TRANSITIONS;
54 private static final boolean DEBUG_ANIM = WindowManagerService.DEBUG_ANIM;
55
56 /** Fraction of animation at which the recents thumbnail becomes completely transparent */
57 static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.25f;
58
59 static final long DEFAULT_APP_TRANSITION_DURATION = 250;
Craig Mautner164d4bb2012-11-26 13:51:23 -080060
61 final Context mContext;
62 final Handler mH;
63
64 int mNextAppTransition = TRANSIT_UNSET;
65 int mNextAppTransitionType = ActivityOptions.ANIM_NONE;
66 String mNextAppTransitionPackage;
67 Bitmap mNextAppTransitionThumbnail;
68 // Used for thumbnail transitions. True if we're scaling up, false if scaling down
69 boolean mNextAppTransitionScaleUp;
70 IRemoteCallback mNextAppTransitionCallback;
71 int mNextAppTransitionEnter;
72 int mNextAppTransitionExit;
73 int mNextAppTransitionStartX;
74 int mNextAppTransitionStartY;
75 int mNextAppTransitionStartWidth;
76 int mNextAppTransitionStartHeight;
77 boolean mAppTransitionReady = false;
78 boolean mAppTransitionRunning = false;
79 boolean mAppTransitionTimeout = false;
80
81 final int mConfigShortAnimTime;
Craig Mautner321bdf52012-12-18 09:53:24 -080082 private final Interpolator mDecelerateInterpolator;
83 private final Interpolator mThumbnailFadeoutInterpolator;
Craig Mautner164d4bb2012-11-26 13:51:23 -080084
85 AppTransition(Context context, Handler h) {
86 mContext = context;
87 mH = h;
88 mConfigShortAnimTime = context.getResources().getInteger(
89 com.android.internal.R.integer.config_shortAnimTime);
Craig Mautner321bdf52012-12-18 09:53:24 -080090 mDecelerateInterpolator = AnimationUtils.loadInterpolator(context,
91 com.android.internal.R.interpolator.decelerate_cubic);
92 mThumbnailFadeoutInterpolator = new Interpolator() {
93 @Override
94 public float getInterpolation(float input) {
95 // Linear response for first fraction, then complete after that.
96 if (input < RECENTS_THUMBNAIL_FADEOUT_FRACTION) {
97 return input / RECENTS_THUMBNAIL_FADEOUT_FRACTION;
98 }
99 return 1.0f;
100 }
101 };
Craig Mautner164d4bb2012-11-26 13:51:23 -0800102 }
103
104 boolean isTransitionSet() {
105 return mNextAppTransition != TRANSIT_UNSET;
106 }
107
108 boolean isTransitionNone() {
109 return mNextAppTransition == TRANSIT_NONE;
110 }
111
112 boolean isTransitionEqual(int transit) {
113 return mNextAppTransition == transit;
114 }
115
116 int getAppTransition() {
Craig Mautner321bdf52012-12-18 09:53:24 -0800117 return mNextAppTransition;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800118 }
119
120 void setAppTransition(int transit) {
121 mNextAppTransition = transit;
122 }
123
124 boolean isReady() {
125 return mAppTransitionReady;
126 }
127
Craig Mautnerae446592012-12-06 19:05:05 -0800128 void setReady() {
129 mAppTransitionReady = true;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800130 }
131
132 boolean isRunning() {
133 return mAppTransitionRunning;
134 }
135
136 void setRunning(boolean running) {
137 mAppTransitionRunning = running;
138 }
139
140 boolean isTimeout() {
141 return mAppTransitionTimeout;
142 }
143
144 void setTimeout(boolean timeout) {
145 mAppTransitionTimeout = timeout;
146 }
147
148 Bitmap getNextAppTransitionThumbnail() {
149 return mNextAppTransitionThumbnail;
150 }
151
152 void getStartingPoint(Point outPoint) {
153 outPoint.x = mNextAppTransitionStartX;
154 outPoint.y = mNextAppTransitionStartY;
155 }
156
157 int getType() {
158 return mNextAppTransitionType;
159 }
160
161 void prepare() {
162 mAppTransitionReady = false;
163 mAppTransitionTimeout = false;
164 }
165
166 void goodToGo() {
167 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
168 mAppTransitionReady = false;
169 mAppTransitionRunning = true;
170 mAppTransitionTimeout = false;
171 }
172
173 void clear() {
174 mNextAppTransitionType = ActivityOptions.ANIM_NONE;
175 mNextAppTransitionPackage = null;
176 mNextAppTransitionThumbnail = null;
177 }
178
179 private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
180 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: layout params pkg="
181 + (lp != null ? lp.packageName : null)
182 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null));
183 if (lp != null && lp.windowAnimations != 0) {
184 // If this is a system resource, don't try to load it from the
185 // application resources. It is nice to avoid loading application
186 // resources if we can.
187 String packageName = lp.packageName != null ? lp.packageName : "android";
188 int resId = lp.windowAnimations;
189 if ((resId&0xFF000000) == 0x01000000) {
190 packageName = "android";
191 }
192 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
193 + packageName);
194 return AttributeCache.instance().get(packageName, resId,
195 com.android.internal.R.styleable.WindowAnimation);
196 }
197 return null;
198 }
199
200 private AttributeCache.Entry getCachedAnimations(String packageName, int resId) {
201 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: package="
202 + packageName + " resId=0x" + Integer.toHexString(resId));
203 if (packageName != null) {
204 if ((resId&0xFF000000) == 0x01000000) {
205 packageName = "android";
206 }
207 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
208 + packageName);
209 return AttributeCache.instance().get(packageName, resId,
210 com.android.internal.R.styleable.WindowAnimation);
211 }
212 return null;
213 }
214
215 Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) {
216 int anim = 0;
217 Context context = mContext;
218 if (animAttr >= 0) {
219 AttributeCache.Entry ent = getCachedAnimations(lp);
220 if (ent != null) {
221 context = ent.context;
222 anim = ent.array.getResourceId(animAttr, 0);
223 }
224 }
225 if (anim != 0) {
226 return AnimationUtils.loadAnimation(context, anim);
227 }
228 return null;
229 }
230
231 private Animation loadAnimation(String packageName, int resId) {
232 int anim = 0;
233 Context context = mContext;
234 if (resId >= 0) {
235 AttributeCache.Entry ent = getCachedAnimations(packageName, resId);
236 if (ent != null) {
237 context = ent.context;
238 anim = resId;
239 }
240 }
241 if (anim != 0) {
242 return AnimationUtils.loadAnimation(context, anim);
243 }
244 return null;
245 }
246
Craig Mautner164d4bb2012-11-26 13:51:23 -0800247 /**
248 * Compute the pivot point for an animation that is scaling from a small
249 * rect on screen to a larger rect. The pivot point varies depending on
250 * the distance between the inner and outer edges on both sides. This
251 * function computes the pivot point for one dimension.
252 * @param startPos Offset from left/top edge of outer rectangle to
253 * left/top edge of inner rectangle.
254 * @param finalScale The scaling factor between the size of the outer
255 * and inner rectangles.
256 */
257 private static float computePivot(int startPos, float finalScale) {
258 final float denom = finalScale-1;
259 if (Math.abs(denom) < .0001f) {
260 return startPos;
261 }
262 return -startPos / denom;
263 }
264
265 private Animation createScaleUpAnimationLocked(int transit, boolean enter,
266 int appWidth, int appHeight) {
267 Animation a = null;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800268 if (enter) {
269 // Entering app zooms out from the center of the initial rect.
270 float scaleW = mNextAppTransitionStartWidth / (float) appWidth;
271 float scaleH = mNextAppTransitionStartHeight / (float) appHeight;
272 Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
273 computePivot(mNextAppTransitionStartX, scaleW),
274 computePivot(mNextAppTransitionStartY, scaleH));
Craig Mautner321bdf52012-12-18 09:53:24 -0800275 scale.setInterpolator(mDecelerateInterpolator);
276
Craig Mautner164d4bb2012-11-26 13:51:23 -0800277 Animation alpha = new AlphaAnimation(0, 1);
Craig Mautner321bdf52012-12-18 09:53:24 -0800278 alpha.setInterpolator(mThumbnailFadeoutInterpolator);
279
280 AnimationSet set = new AnimationSet(false);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800281 set.addAnimation(scale);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800282 set.addAnimation(alpha);
283 set.setDetachWallpaper(true);
284 a = set;
Craig Mautner321bdf52012-12-18 09:53:24 -0800285 } else if (transit == WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN ||
286 transit == WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE) {
287 // If we are on top of the wallpaper, we need an animation that
288 // correctly handles the wallpaper staying static behind all of
289 // the animated elements. To do this, will just have the existing
290 // element fade out.
291 a = new AlphaAnimation(1, 0);
292 a.setDetachWallpaper(true);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800293 } else {
Craig Mautner321bdf52012-12-18 09:53:24 -0800294 // For normal animations, the exiting element just holds in place.
295 a = new AlphaAnimation(1, 1);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800296 }
Craig Mautner321bdf52012-12-18 09:53:24 -0800297
298 // Pick the desired duration. If this is an inter-activity transition,
299 // it is the standard duration for that. Otherwise we use the longer
300 // task transition duration.
301 final long duration;
302 switch (transit) {
303 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
304 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
305 duration = mConfigShortAnimTime;
306 break;
307 default:
308 duration = DEFAULT_APP_TRANSITION_DURATION;
309 break;
310 }
311 a.setDuration(duration);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800312 a.setFillAfter(true);
Craig Mautner321bdf52012-12-18 09:53:24 -0800313 a.setInterpolator(mDecelerateInterpolator);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800314 a.initialize(appWidth, appHeight, appWidth, appHeight);
315 return a;
316 }
317
318 Animation createThumbnailAnimationLocked(int transit, boolean enter, boolean thumb,
319 int appWidth, int appHeight) {
320 Animation a;
321 final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
322 final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
323 final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
324 final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800325 if (thumb) {
326 // Animation for zooming thumbnail from its initial size to
327 // filling the screen.
328 if (mNextAppTransitionScaleUp) {
329 float scaleW = appWidth / thumbWidth;
330 float scaleH = appHeight / thumbHeight;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800331 Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
332 computePivot(mNextAppTransitionStartX, 1 / scaleW),
333 computePivot(mNextAppTransitionStartY, 1 / scaleH));
Craig Mautner321bdf52012-12-18 09:53:24 -0800334 scale.setInterpolator(mDecelerateInterpolator);
335
Craig Mautner164d4bb2012-11-26 13:51:23 -0800336 Animation alpha = new AlphaAnimation(1, 0);
Craig Mautner321bdf52012-12-18 09:53:24 -0800337 alpha.setInterpolator(mThumbnailFadeoutInterpolator);
338
339 // This AnimationSet uses the Interpolators assigned above.
340 AnimationSet set = new AnimationSet(false);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800341 set.addAnimation(scale);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800342 set.addAnimation(alpha);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800343 a = set;
344 } else {
345 float scaleW = appWidth / thumbWidth;
346 float scaleH = appHeight / thumbHeight;
Craig Mautner321bdf52012-12-18 09:53:24 -0800347 a = new ScaleAnimation(scaleW, 1, scaleH, 1,
Craig Mautner164d4bb2012-11-26 13:51:23 -0800348 computePivot(mNextAppTransitionStartX, 1 / scaleW),
349 computePivot(mNextAppTransitionStartY, 1 / scaleH));
Craig Mautner164d4bb2012-11-26 13:51:23 -0800350 }
351 } else if (enter) {
352 // Entering app zooms out from the center of the thumbnail.
353 if (mNextAppTransitionScaleUp) {
354 float scaleW = thumbWidth / appWidth;
355 float scaleH = thumbHeight / appHeight;
Craig Mautner321bdf52012-12-18 09:53:24 -0800356 a = new ScaleAnimation(scaleW, 1, scaleH, 1,
Craig Mautner164d4bb2012-11-26 13:51:23 -0800357 computePivot(mNextAppTransitionStartX, scaleW),
358 computePivot(mNextAppTransitionStartY, scaleH));
Craig Mautner164d4bb2012-11-26 13:51:23 -0800359 } else {
360 // noop animation
361 a = new AlphaAnimation(1, 1);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800362 }
363 } else {
364 // Exiting app
365 if (mNextAppTransitionScaleUp) {
366 if (transit == WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN) {
367 // Fade out while bringing up selected activity. This keeps the
368 // current activity from showing through a launching wallpaper
369 // activity.
370 a = new AlphaAnimation(1, 0);
371 } else {
372 // noop animation
373 a = new AlphaAnimation(1, 1);
374 }
Craig Mautner164d4bb2012-11-26 13:51:23 -0800375 } else {
376 float scaleW = thumbWidth / appWidth;
377 float scaleH = thumbHeight / appHeight;
378 Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
379 computePivot(mNextAppTransitionStartX, scaleW),
380 computePivot(mNextAppTransitionStartY, scaleH));
Craig Mautner321bdf52012-12-18 09:53:24 -0800381
Craig Mautner164d4bb2012-11-26 13:51:23 -0800382 Animation alpha = new AlphaAnimation(1, 0);
Craig Mautner321bdf52012-12-18 09:53:24 -0800383
384 AnimationSet set = new AnimationSet(true);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800385 set.addAnimation(scale);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800386 set.addAnimation(alpha);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800387 set.setZAdjustment(Animation.ZORDER_TOP);
388 a = set;
389 }
390 }
Craig Mautner321bdf52012-12-18 09:53:24 -0800391
392 // Pick the desired duration. If this is an inter-activity transition,
393 // it is the standard duration for that. Otherwise we use the longer
394 // task transition duration.
395 final long duration;
396 switch (transit) {
397 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
398 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
399 duration = mConfigShortAnimTime;
400 break;
401 default:
402 duration = DEFAULT_APP_TRANSITION_DURATION;
403 break;
404 }
405 a.setDuration(duration);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800406 a.setFillAfter(true);
Craig Mautner321bdf52012-12-18 09:53:24 -0800407 a.setInterpolator(mDecelerateInterpolator);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800408 a.initialize(appWidth, appHeight, appWidth, appHeight);
409 return a;
410 }
411
412
413 Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
414 int appWidth, int appHeight) {
415 Animation a;
416 if (mNextAppTransitionType == ActivityOptions.ANIM_CUSTOM) {
417 a = loadAnimation(mNextAppTransitionPackage, enter ?
418 mNextAppTransitionEnter : mNextAppTransitionExit);
419 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
420 "applyAnimation:"
421 + " anim=" + a + " nextAppTransition=ANIM_CUSTOM"
422 + " transit=" + transit + " isEntrance=" + enter
423 + " Callers=" + Debug.getCallers(3));
424 } else if (mNextAppTransitionType == ActivityOptions.ANIM_SCALE_UP) {
425 a = createScaleUpAnimationLocked(transit, enter, appWidth, appHeight);
426 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
427 "applyAnimation:"
428 + " anim=" + a + " nextAppTransition=ANIM_SCALE_UP"
429 + " transit=" + transit + " isEntrance=" + enter
430 + " Callers=" + Debug.getCallers(3));
431 } else if (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_SCALE_UP ||
432 mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN) {
433 mNextAppTransitionScaleUp =
434 (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_SCALE_UP);
435 a = createThumbnailAnimationLocked(transit, enter, false, appWidth, appHeight);
436 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
437 String animName = mNextAppTransitionScaleUp ?
438 "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
439 Slog.v(TAG, "applyAnimation:"
440 + " anim=" + a + " nextAppTransition=" + animName
441 + " transit=" + transit + " isEntrance=" + enter
442 + " Callers=" + Debug.getCallers(3));
443 }
444 } else {
445 int animAttr = 0;
446 switch (transit) {
447 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
448 animAttr = enter
449 ? com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation
450 : com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
451 break;
452 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
453 animAttr = enter
454 ? com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation
455 : com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
456 break;
457 case WindowManagerPolicy.TRANSIT_TASK_OPEN:
458 animAttr = enter
459 ? com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation
460 : com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
461 break;
462 case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
463 animAttr = enter
464 ? com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation
465 : com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
466 break;
467 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
468 animAttr = enter
469 ? com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation
470 : com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation;
471 break;
472 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
473 animAttr = enter
474 ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation
475 : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
476 break;
477 case WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN:
478 animAttr = enter
479 ? com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation
480 : com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
481 break;
482 case WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE:
483 animAttr = enter
484 ? com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation
485 : com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation;
486 break;
487 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN:
488 animAttr = enter
489 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation
490 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
491 break;
492 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE:
493 animAttr = enter
494 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation
495 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation;
496 break;
497 }
498 a = animAttr != 0 ? loadAnimation(lp, animAttr) : null;
499 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
500 "applyAnimation:"
501 + " anim=" + a
502 + " animAttr=0x" + Integer.toHexString(animAttr)
503 + " transit=" + transit + " isEntrance=" + enter
504 + " Callers=" + Debug.getCallers(3));
505 }
506 return a;
507 }
508
509 void postAnimationCallback() {
510 if (mNextAppTransitionCallback != null) {
511 mH.sendMessage(mH.obtainMessage(H.DO_ANIMATION_CALLBACK, mNextAppTransitionCallback));
512 mNextAppTransitionCallback = null;
513 }
514 }
515
516 void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim,
517 IRemoteCallback startedCallback) {
518 if (isTransitionSet()) {
519 mNextAppTransitionType = ActivityOptions.ANIM_CUSTOM;
520 mNextAppTransitionPackage = packageName;
521 mNextAppTransitionThumbnail = null;
522 mNextAppTransitionEnter = enterAnim;
523 mNextAppTransitionExit = exitAnim;
524 postAnimationCallback();
525 mNextAppTransitionCallback = startedCallback;
526 } else {
527 postAnimationCallback();
528 }
529 }
530
531 void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
532 int startHeight) {
533 if (isTransitionSet()) {
534 mNextAppTransitionType = ActivityOptions.ANIM_SCALE_UP;
535 mNextAppTransitionPackage = null;
536 mNextAppTransitionThumbnail = null;
537 mNextAppTransitionStartX = startX;
538 mNextAppTransitionStartY = startY;
539 mNextAppTransitionStartWidth = startWidth;
540 mNextAppTransitionStartHeight = startHeight;
541 postAnimationCallback();
542 mNextAppTransitionCallback = null;
543 }
544 }
545
546 void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY,
547 IRemoteCallback startedCallback, boolean scaleUp) {
548 if (isTransitionSet()) {
549 mNextAppTransitionType = scaleUp ? ActivityOptions.ANIM_THUMBNAIL_SCALE_UP
550 : ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
551 mNextAppTransitionPackage = null;
552 mNextAppTransitionThumbnail = srcThumb;
553 mNextAppTransitionScaleUp = scaleUp;
554 mNextAppTransitionStartX = startX;
555 mNextAppTransitionStartY = startY;
556 postAnimationCallback();
557 mNextAppTransitionCallback = startedCallback;
558 } else {
559 postAnimationCallback();
560 }
561 }
562
563 @Override
564 public String toString() {
565 return "mNextAppTransition=0x" + Integer.toHexString(mNextAppTransition);
566 }
567
568 @Override
569 public void dump(PrintWriter pw) {
570 pw.print(" " + this);
571 pw.print(" mAppTransitionReady="); pw.println(mAppTransitionReady);
572 pw.print(" mAppTransitionRunning="); pw.print(mAppTransitionRunning);
573 pw.print(" mAppTransitionTimeout="); pw.println(mAppTransitionTimeout);
574 if (mNextAppTransitionType != ActivityOptions.ANIM_NONE) {
575 pw.print(" mNextAppTransitionType="); pw.println(mNextAppTransitionType);
576 }
577 switch (mNextAppTransitionType) {
578 case ActivityOptions.ANIM_CUSTOM:
579 pw.print(" mNextAppTransitionPackage=");
580 pw.println(mNextAppTransitionPackage);
581 pw.print(" mNextAppTransitionEnter=0x");
582 pw.print(Integer.toHexString(mNextAppTransitionEnter));
583 pw.print(" mNextAppTransitionExit=0x");
584 pw.println(Integer.toHexString(mNextAppTransitionExit));
585 break;
586 case ActivityOptions.ANIM_SCALE_UP:
587 pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX);
588 pw.print(" mNextAppTransitionStartY=");
589 pw.println(mNextAppTransitionStartY);
590 pw.print(" mNextAppTransitionStartWidth=");
591 pw.print(mNextAppTransitionStartWidth);
592 pw.print(" mNextAppTransitionStartHeight=");
593 pw.println(mNextAppTransitionStartHeight);
594 break;
595 case ActivityOptions.ANIM_THUMBNAIL_SCALE_UP:
596 case ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN:
597 pw.print(" mNextAppTransitionThumbnail=");
598 pw.print(mNextAppTransitionThumbnail);
599 pw.print(" mNextAppTransitionStartX=");
600 pw.print(mNextAppTransitionStartX);
601 pw.print(" mNextAppTransitionStartY=");
602 pw.println(mNextAppTransitionStartY);
603 pw.print(" mNextAppTransitionScaleUp="); pw.println(mNextAppTransitionScaleUp);
604 break;
605 }
606 if (mNextAppTransitionCallback != null) {
607 pw.print(" mNextAppTransitionCallback=");
608 pw.println(mNextAppTransitionCallback);
609 }
610 }
611}