blob: 99ec242902cee3d32d41a89459f26bab13e45c2e [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
Craig Mautner164d4bb2012-11-26 13:51:23 -080019import android.content.Context;
Winson Chung2820c452014-04-15 15:34:44 -070020import android.content.res.Configuration;
Craig Mautner164d4bb2012-11-26 13:51:23 -080021import android.graphics.Bitmap;
22import android.graphics.Point;
Winson Chung399f6202014-03-19 10:47:20 -070023import android.graphics.Rect;
Craig Mautner164d4bb2012-11-26 13:51:23 -080024import android.os.Debug;
25import android.os.Handler;
26import android.os.IRemoteCallback;
Winson Chung399f6202014-03-19 10:47:20 -070027import android.os.SystemProperties;
Craig Mautner164d4bb2012-11-26 13:51:23 -080028import android.util.Slog;
29import android.view.WindowManager;
Craig Mautner164d4bb2012-11-26 13:51:23 -080030import android.view.animation.AlphaAnimation;
31import android.view.animation.Animation;
32import android.view.animation.AnimationSet;
33import android.view.animation.AnimationUtils;
Winson Chung399f6202014-03-19 10:47:20 -070034import android.view.animation.ClipRectAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -080035import android.view.animation.Interpolator;
36import android.view.animation.ScaleAnimation;
37
Winson Chung399f6202014-03-19 10:47:20 -070038import android.view.animation.TranslateAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -080039import com.android.internal.util.DumpUtils.Dump;
40import com.android.server.AttributeCache;
41import com.android.server.wm.WindowManagerService.H;
42
43import java.io.PrintWriter;
44
Craig Mautner9a29a5d2012-12-27 19:03:40 -080045import static com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation;
46import static com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
47import static com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation;
48import static com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
49import static com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation;
50import static com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
51import static com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation;
52import static com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
53import static com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation;
54import static com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation;
55import static com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation;
56import static com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
57import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation;
58import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
59import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation;
60import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation;
61import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation;
62import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
63import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation;
64import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation;
65
Craig Mautner164d4bb2012-11-26 13:51:23 -080066// State management of app transitions. When we are preparing for a
67// transition, mNextAppTransition will be the kind of transition to
68// perform or TRANSIT_NONE if we are not waiting. If we are waiting,
69// mOpeningApps and mClosingApps are the lists of tokens that will be
70// made visible or hidden at the next transition.
71public class AppTransition implements Dump {
72 private static final String TAG = "AppTransition";
Craig Mautner321bdf52012-12-18 09:53:24 -080073 private static final boolean DEBUG_APP_TRANSITIONS =
74 WindowManagerService.DEBUG_APP_TRANSITIONS;
75 private static final boolean DEBUG_ANIM = WindowManagerService.DEBUG_ANIM;
76
Craig Mautner9a29a5d2012-12-27 19:03:40 -080077 /** Bit mask that is set for all enter transition. */
Craig Mautner4b71aa12012-12-27 17:20:01 -080078 public static final int TRANSIT_ENTER_MASK = 0x1000;
Craig Mautner9a29a5d2012-12-27 19:03:40 -080079
80 /** Bit mask that is set for all exit transitions. */
Craig Mautner4b71aa12012-12-27 17:20:01 -080081 public static final int TRANSIT_EXIT_MASK = 0x2000;
Craig Mautner9a29a5d2012-12-27 19:03:40 -080082
Craig Mautner4b71aa12012-12-27 17:20:01 -080083 /** Not set up for a transition. */
84 public static final int TRANSIT_UNSET = -1;
85 /** No animation for transition. */
86 public static final int TRANSIT_NONE = 0;
87 /** A window in a new activity is being opened on top of an existing one in the same task. */
88 public static final int TRANSIT_ACTIVITY_OPEN = 6 | TRANSIT_ENTER_MASK;
89 /** The window in the top-most activity is being closed to reveal the
90 * previous activity in the same task. */
91 public static final int TRANSIT_ACTIVITY_CLOSE = 7 | TRANSIT_EXIT_MASK;
92 /** A window in a new task is being opened on top of an existing one
93 * in another activity's task. */
94 public static final int TRANSIT_TASK_OPEN = 8 | TRANSIT_ENTER_MASK;
95 /** A window in the top-most activity is being closed to reveal the
96 * previous activity in a different task. */
97 public static final int TRANSIT_TASK_CLOSE = 9 | TRANSIT_EXIT_MASK;
98 /** A window in an existing task is being displayed on top of an existing one
99 * in another activity's task. */
100 public static final int TRANSIT_TASK_TO_FRONT = 10 | TRANSIT_ENTER_MASK;
101 /** A window in an existing task is being put below all other tasks. */
102 public static final int TRANSIT_TASK_TO_BACK = 11 | TRANSIT_EXIT_MASK;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800103 /** A window in a new activity that doesn't have a wallpaper is being opened on top of one that
104 * does, effectively closing the wallpaper. */
Craig Mautner4b71aa12012-12-27 17:20:01 -0800105 public static final int TRANSIT_WALLPAPER_CLOSE = 12 | TRANSIT_EXIT_MASK;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800106 /** A window in a new activity that does have a wallpaper is being opened on one that didn't,
107 * effectively opening the wallpaper. */
Craig Mautner4b71aa12012-12-27 17:20:01 -0800108 public static final int TRANSIT_WALLPAPER_OPEN = 13 | TRANSIT_ENTER_MASK;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800109 /** A window in a new activity is being opened on top of an existing one, and both are on top
110 * of the wallpaper. */
Craig Mautner4b71aa12012-12-27 17:20:01 -0800111 public static final int TRANSIT_WALLPAPER_INTRA_OPEN = 14 | TRANSIT_ENTER_MASK;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800112 /** The window in the top-most activity is being closed to reveal the previous activity, and
113 * both are on top of the wallpaper. */
Craig Mautner4b71aa12012-12-27 17:20:01 -0800114 public static final int TRANSIT_WALLPAPER_INTRA_CLOSE = 15 | TRANSIT_EXIT_MASK;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800115
Craig Mautner321bdf52012-12-18 09:53:24 -0800116 /** Fraction of animation at which the recents thumbnail becomes completely transparent */
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800117 private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.25f;
Craig Mautner321bdf52012-12-18 09:53:24 -0800118
Winson Chung5393dff2014-05-08 14:25:43 -0700119 private static final int DEFAULT_APP_TRANSITION_DURATION = 250;
120 private static final int THUMBNAIL_APP_TRANSITION_DURATION = 225;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800121
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800122 private final Context mContext;
123 private final Handler mH;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800124
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800125 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 int mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
133
Winson Chung399f6202014-03-19 10:47:20 -0700134 // These are the possible states for the enter/exit activities during a thumbnail transition
135 private static final int THUMBNAIL_TRANSITION_ENTER_SCALE_UP = 0;
136 private static final int THUMBNAIL_TRANSITION_EXIT_SCALE_UP = 1;
137 private static final int THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN = 2;
138 private static final int THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN = 3;
139
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800140 private String mNextAppTransitionPackage;
141 private Bitmap mNextAppTransitionThumbnail;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800142 // Used for thumbnail transitions. True if we're scaling up, false if scaling down
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800143 private boolean mNextAppTransitionScaleUp;
144 private IRemoteCallback mNextAppTransitionCallback;
145 private int mNextAppTransitionEnter;
146 private int mNextAppTransitionExit;
147 private int mNextAppTransitionStartX;
148 private int mNextAppTransitionStartY;
149 private int mNextAppTransitionStartWidth;
150 private int mNextAppTransitionStartHeight;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800151
Winson Chung2820c452014-04-15 15:34:44 -0700152 private Rect mTmpFromClipRect = new Rect();
153 private Rect mTmpToClipRect = new Rect();
154
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800155 private final static int APP_STATE_IDLE = 0;
156 private final static int APP_STATE_READY = 1;
157 private final static int APP_STATE_RUNNING = 2;
158 private final static int APP_STATE_TIMEOUT = 3;
159 private int mAppTransitionState = APP_STATE_IDLE;
160
161 private final int mConfigShortAnimTime;
Craig Mautner321bdf52012-12-18 09:53:24 -0800162 private final Interpolator mDecelerateInterpolator;
163 private final Interpolator mThumbnailFadeoutInterpolator;
Winson Chung5393dff2014-05-08 14:25:43 -0700164 private final Interpolator mThumbnailCubicInterpolator;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800165
Amith Yamasani4befbec2013-07-10 16:18:01 -0700166 private int mCurrentUserId = 0;
167
Craig Mautner164d4bb2012-11-26 13:51:23 -0800168 AppTransition(Context context, Handler h) {
169 mContext = context;
170 mH = h;
171 mConfigShortAnimTime = context.getResources().getInteger(
172 com.android.internal.R.integer.config_shortAnimTime);
Craig Mautner321bdf52012-12-18 09:53:24 -0800173 mDecelerateInterpolator = AnimationUtils.loadInterpolator(context,
174 com.android.internal.R.interpolator.decelerate_cubic);
Winson Chung5393dff2014-05-08 14:25:43 -0700175 mThumbnailCubicInterpolator = AnimationUtils.loadInterpolator(context,
176 com.android.internal.R.interpolator.fast_out_slow_in);
Craig Mautner321bdf52012-12-18 09:53:24 -0800177 mThumbnailFadeoutInterpolator = new Interpolator() {
178 @Override
179 public float getInterpolation(float input) {
180 // Linear response for first fraction, then complete after that.
181 if (input < RECENTS_THUMBNAIL_FADEOUT_FRACTION) {
182 return input / RECENTS_THUMBNAIL_FADEOUT_FRACTION;
183 }
184 return 1.0f;
185 }
186 };
Craig Mautner164d4bb2012-11-26 13:51:23 -0800187 }
188
189 boolean isTransitionSet() {
190 return mNextAppTransition != TRANSIT_UNSET;
191 }
192
193 boolean isTransitionNone() {
194 return mNextAppTransition == TRANSIT_NONE;
195 }
196
197 boolean isTransitionEqual(int transit) {
198 return mNextAppTransition == transit;
199 }
200
201 int getAppTransition() {
Craig Mautner321bdf52012-12-18 09:53:24 -0800202 return mNextAppTransition;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800203 }
204
205 void setAppTransition(int transit) {
206 mNextAppTransition = transit;
207 }
208
209 boolean isReady() {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800210 return mAppTransitionState == APP_STATE_READY
211 || mAppTransitionState == APP_STATE_TIMEOUT;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800212 }
213
Craig Mautnerae446592012-12-06 19:05:05 -0800214 void setReady() {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800215 mAppTransitionState = APP_STATE_READY;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800216 }
217
218 boolean isRunning() {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800219 return mAppTransitionState == APP_STATE_RUNNING;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800220 }
221
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800222 void setIdle() {
223 mAppTransitionState = APP_STATE_IDLE;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800224 }
225
226 boolean isTimeout() {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800227 return mAppTransitionState == APP_STATE_TIMEOUT;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800228 }
229
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800230 void setTimeout() {
231 mAppTransitionState = APP_STATE_TIMEOUT;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800232 }
233
234 Bitmap getNextAppTransitionThumbnail() {
235 return mNextAppTransitionThumbnail;
236 }
237
238 void getStartingPoint(Point outPoint) {
239 outPoint.x = mNextAppTransitionStartX;
240 outPoint.y = mNextAppTransitionStartY;
241 }
242
Craig Mautner164d4bb2012-11-26 13:51:23 -0800243 void prepare() {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800244 if (!isRunning()) {
245 mAppTransitionState = APP_STATE_IDLE;
246 }
Craig Mautner164d4bb2012-11-26 13:51:23 -0800247 }
248
249 void goodToGo() {
Craig Mautner4b71aa12012-12-27 17:20:01 -0800250 mNextAppTransition = TRANSIT_UNSET;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800251 mAppTransitionState = APP_STATE_RUNNING;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800252 }
253
254 void clear() {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800255 mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800256 mNextAppTransitionPackage = null;
257 mNextAppTransitionThumbnail = null;
258 }
259
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800260 void freeze() {
261 setAppTransition(AppTransition.TRANSIT_UNSET);
262 clear();
263 setReady();
264 }
265
Craig Mautner164d4bb2012-11-26 13:51:23 -0800266 private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
267 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: layout params pkg="
268 + (lp != null ? lp.packageName : null)
269 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null));
270 if (lp != null && lp.windowAnimations != 0) {
271 // If this is a system resource, don't try to load it from the
272 // application resources. It is nice to avoid loading application
273 // resources if we can.
274 String packageName = lp.packageName != null ? lp.packageName : "android";
275 int resId = lp.windowAnimations;
276 if ((resId&0xFF000000) == 0x01000000) {
277 packageName = "android";
278 }
279 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
280 + packageName);
281 return AttributeCache.instance().get(packageName, resId,
Amith Yamasani4befbec2013-07-10 16:18:01 -0700282 com.android.internal.R.styleable.WindowAnimation, mCurrentUserId);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800283 }
284 return null;
285 }
286
287 private AttributeCache.Entry getCachedAnimations(String packageName, int resId) {
288 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: package="
289 + packageName + " resId=0x" + Integer.toHexString(resId));
290 if (packageName != null) {
291 if ((resId&0xFF000000) == 0x01000000) {
292 packageName = "android";
293 }
294 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
295 + packageName);
296 return AttributeCache.instance().get(packageName, resId,
Amith Yamasani4befbec2013-07-10 16:18:01 -0700297 com.android.internal.R.styleable.WindowAnimation, mCurrentUserId);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800298 }
299 return null;
300 }
301
302 Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) {
303 int anim = 0;
304 Context context = mContext;
305 if (animAttr >= 0) {
306 AttributeCache.Entry ent = getCachedAnimations(lp);
307 if (ent != null) {
308 context = ent.context;
309 anim = ent.array.getResourceId(animAttr, 0);
310 }
311 }
312 if (anim != 0) {
313 return AnimationUtils.loadAnimation(context, anim);
314 }
315 return null;
316 }
317
318 private Animation loadAnimation(String packageName, int resId) {
319 int anim = 0;
320 Context context = mContext;
321 if (resId >= 0) {
322 AttributeCache.Entry ent = getCachedAnimations(packageName, resId);
323 if (ent != null) {
324 context = ent.context;
325 anim = resId;
326 }
327 }
328 if (anim != 0) {
329 return AnimationUtils.loadAnimation(context, anim);
330 }
331 return null;
332 }
333
Craig Mautner164d4bb2012-11-26 13:51:23 -0800334 /**
335 * Compute the pivot point for an animation that is scaling from a small
336 * rect on screen to a larger rect. The pivot point varies depending on
337 * the distance between the inner and outer edges on both sides. This
338 * function computes the pivot point for one dimension.
339 * @param startPos Offset from left/top edge of outer rectangle to
340 * left/top edge of inner rectangle.
341 * @param finalScale The scaling factor between the size of the outer
342 * and inner rectangles.
343 */
344 private static float computePivot(int startPos, float finalScale) {
345 final float denom = finalScale-1;
346 if (Math.abs(denom) < .0001f) {
347 return startPos;
348 }
349 return -startPos / denom;
350 }
351
352 private Animation createScaleUpAnimationLocked(int transit, boolean enter,
353 int appWidth, int appHeight) {
354 Animation a = null;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800355 if (enter) {
356 // Entering app zooms out from the center of the initial rect.
357 float scaleW = mNextAppTransitionStartWidth / (float) appWidth;
358 float scaleH = mNextAppTransitionStartHeight / (float) appHeight;
359 Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
360 computePivot(mNextAppTransitionStartX, scaleW),
361 computePivot(mNextAppTransitionStartY, scaleH));
Craig Mautner321bdf52012-12-18 09:53:24 -0800362 scale.setInterpolator(mDecelerateInterpolator);
363
Craig Mautner164d4bb2012-11-26 13:51:23 -0800364 Animation alpha = new AlphaAnimation(0, 1);
Craig Mautner321bdf52012-12-18 09:53:24 -0800365 alpha.setInterpolator(mThumbnailFadeoutInterpolator);
366
367 AnimationSet set = new AnimationSet(false);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800368 set.addAnimation(scale);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800369 set.addAnimation(alpha);
370 set.setDetachWallpaper(true);
371 a = set;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800372 } else if (transit == TRANSIT_WALLPAPER_INTRA_OPEN ||
373 transit == TRANSIT_WALLPAPER_INTRA_CLOSE) {
Craig Mautner321bdf52012-12-18 09:53:24 -0800374 // If we are on top of the wallpaper, we need an animation that
375 // correctly handles the wallpaper staying static behind all of
376 // the animated elements. To do this, will just have the existing
377 // element fade out.
378 a = new AlphaAnimation(1, 0);
379 a.setDetachWallpaper(true);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800380 } else {
Craig Mautner321bdf52012-12-18 09:53:24 -0800381 // For normal animations, the exiting element just holds in place.
382 a = new AlphaAnimation(1, 1);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800383 }
Craig Mautner321bdf52012-12-18 09:53:24 -0800384
385 // Pick the desired duration. If this is an inter-activity transition,
386 // it is the standard duration for that. Otherwise we use the longer
387 // task transition duration.
388 final long duration;
389 switch (transit) {
Craig Mautner4b71aa12012-12-27 17:20:01 -0800390 case TRANSIT_ACTIVITY_OPEN:
391 case TRANSIT_ACTIVITY_CLOSE:
Craig Mautner321bdf52012-12-18 09:53:24 -0800392 duration = mConfigShortAnimTime;
393 break;
394 default:
395 duration = DEFAULT_APP_TRANSITION_DURATION;
396 break;
397 }
398 a.setDuration(duration);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800399 a.setFillAfter(true);
Craig Mautner321bdf52012-12-18 09:53:24 -0800400 a.setInterpolator(mDecelerateInterpolator);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800401 a.initialize(appWidth, appHeight, appWidth, appHeight);
402 return a;
403 }
404
Winson Chung399f6202014-03-19 10:47:20 -0700405 /**
406 * Prepares the specified animation with a standard duration, interpolator, etc.
407 */
Winson Chung5393dff2014-05-08 14:25:43 -0700408 Animation prepareThumbnailAnimationWithDuration(Animation a, int appWidth, int appHeight,
409 int duration, Interpolator interpolator) {
410 a.setDuration(duration);
411 a.setFillAfter(true);
412 a.setInterpolator(interpolator);
413 a.initialize(appWidth, appHeight, appWidth, appHeight);
414 return a;
415 }
416
417 /**
418 * Prepares the specified animation with a standard duration, interpolator, etc.
419 */
Winson Chung399f6202014-03-19 10:47:20 -0700420 Animation prepareThumbnailAnimation(Animation a, int appWidth, int appHeight, int transit) {
Craig Mautner321bdf52012-12-18 09:53:24 -0800421 // Pick the desired duration. If this is an inter-activity transition,
422 // it is the standard duration for that. Otherwise we use the longer
423 // task transition duration.
Winson Chung5393dff2014-05-08 14:25:43 -0700424 final int duration;
Craig Mautner321bdf52012-12-18 09:53:24 -0800425 switch (transit) {
Craig Mautner4b71aa12012-12-27 17:20:01 -0800426 case TRANSIT_ACTIVITY_OPEN:
427 case TRANSIT_ACTIVITY_CLOSE:
Craig Mautner321bdf52012-12-18 09:53:24 -0800428 duration = mConfigShortAnimTime;
429 break;
430 default:
431 duration = DEFAULT_APP_TRANSITION_DURATION;
432 break;
433 }
Winson Chung5393dff2014-05-08 14:25:43 -0700434 return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, duration,
435 mDecelerateInterpolator);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800436 }
437
Winson Chung399f6202014-03-19 10:47:20 -0700438 /**
439 * Return the current thumbnail transition state.
440 */
441 int getThumbnailTransitionState(boolean enter) {
442 if (enter) {
443 if (mNextAppTransitionScaleUp) {
444 return THUMBNAIL_TRANSITION_ENTER_SCALE_UP;
445 } else {
446 return THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN;
447 }
448 } else {
449 if (mNextAppTransitionScaleUp) {
450 return THUMBNAIL_TRANSITION_EXIT_SCALE_UP;
451 } else {
452 return THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN;
453 }
454 }
455 }
456
457 /**
458 * This animation runs for the thumbnail that gets cross faded with the enter/exit activity
459 * when a thumbnail is specified with the activity options.
460 */
461 Animation createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit) {
462 Animation a;
463 final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
464 final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
465 final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
466 final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
467
468 if (mNextAppTransitionScaleUp) {
469 // Animation for the thumbnail zooming from its initial size to the full screen
470 float scaleW = appWidth / thumbWidth;
471 float scaleH = appHeight / thumbHeight;
472 Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
473 computePivot(mNextAppTransitionStartX, 1 / scaleW),
474 computePivot(mNextAppTransitionStartY, 1 / scaleH));
475 scale.setInterpolator(mDecelerateInterpolator);
476
477 Animation alpha = new AlphaAnimation(1, 0);
478 alpha.setInterpolator(mThumbnailFadeoutInterpolator);
479
480 // This AnimationSet uses the Interpolators assigned above.
481 AnimationSet set = new AnimationSet(false);
482 set.addAnimation(scale);
483 set.addAnimation(alpha);
484 a = set;
485 } else {
486 // Animation for the thumbnail zooming down from the full screen to its final size
487 float scaleW = appWidth / thumbWidth;
488 float scaleH = appHeight / thumbHeight;
489 a = new ScaleAnimation(scaleW, 1, scaleH, 1,
490 computePivot(mNextAppTransitionStartX, 1 / scaleW),
491 computePivot(mNextAppTransitionStartY, 1 / scaleH));
492 }
493
494 return prepareThumbnailAnimation(a, appWidth, appHeight, transit);
495 }
496
497 /**
498 * This alternate animation is created when we are doing a thumbnail transition, for the
499 * activity that is leaving, and the activity that is entering.
500 */
501 Animation createAlternateThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth,
Winson Chung2820c452014-04-15 15:34:44 -0700502 int appHeight, int orientation, int transit,
Winson Chung399f6202014-03-19 10:47:20 -0700503 Rect containingFrame, Rect contentInsets) {
504 Animation a;
505 final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
506 final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
507 final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
508 final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
509
Winson Chung2820c452014-04-15 15:34:44 -0700510 // Used for the ENTER_SCALE_UP and EXIT_SCALE_DOWN transitions
511 float scale = 1f;
512 int scaledTopDecor = 0;
513
Winson Chung399f6202014-03-19 10:47:20 -0700514 switch (thumbTransitState) {
515 case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: {
516 // Entering app scales up with the thumbnail
Winson Chung2820c452014-04-15 15:34:44 -0700517 if (orientation == Configuration.ORIENTATION_PORTRAIT) {
518 // In portrait, we scale the width and clip to the top/left square
519 scale = thumbWidth / appWidth;
520 scaledTopDecor = (int) (scale * contentInsets.top);
521 int unscaledThumbHeight = (int) (thumbHeight / scale);
522 mTmpFromClipRect.set(containingFrame);
523 mTmpFromClipRect.bottom = (mTmpFromClipRect.top + unscaledThumbHeight);
524 mTmpToClipRect.set(containingFrame);
525 } else {
526 // In landscape, we scale the height and clip to the top/left square
527 scale = thumbHeight / (appHeight - contentInsets.top);
528 scaledTopDecor = (int) (scale * contentInsets.top);
529 int unscaledThumbWidth = (int) (thumbWidth / scale);
530 mTmpFromClipRect.set(containingFrame);
531 mTmpFromClipRect.right = (mTmpFromClipRect.left + unscaledThumbWidth);
532 mTmpToClipRect.set(containingFrame);
533 }
Winson Chung399f6202014-03-19 10:47:20 -0700534
535 Animation scaleAnim = new ScaleAnimation(scale, 1, scale, 1,
536 computePivot(mNextAppTransitionStartX, scale),
537 computePivot(mNextAppTransitionStartY, scale));
538 Animation alphaAnim = new AlphaAnimation(1, 1);
Winson Chung2820c452014-04-15 15:34:44 -0700539 Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
Winson Chung399f6202014-03-19 10:47:20 -0700540 Animation translateAnim = new TranslateAnimation(0, 0, -scaledTopDecor, 0);
541
542 AnimationSet set = new AnimationSet(true);
543 set.addAnimation(alphaAnim);
544 set.addAnimation(clipAnim);
545 set.addAnimation(scaleAnim);
546 set.addAnimation(translateAnim);
547 a = set;
548 break;
549 }
550 case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: {
551 // Exiting app while the thumbnail is scaling up should fade
552 if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) {
553 // Fade out while bringing up selected activity. This keeps the
554 // current activity from showing through a launching wallpaper
555 // activity.
556 a = new AlphaAnimation(1, 0);
557 } else {
558 // noop animation
559 a = new AlphaAnimation(1, 1);
560 }
561 break;
562 }
563 case THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN: {
564 // Entering the other app, it should just be visible while we scale the thumbnail
565 // down above it
566 a = new AlphaAnimation(1, 1);
567 break;
568 }
569 case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: {
570 // Exiting the current app, the app should scale down with the thumbnail
Winson Chung2820c452014-04-15 15:34:44 -0700571 if (orientation == Configuration.ORIENTATION_PORTRAIT) {
572 // In portrait, we scale the width and clip to the top/left square
573 scale = thumbWidth / appWidth;
574 scaledTopDecor = (int) (scale * contentInsets.top);
575 int unscaledThumbHeight = (int) (thumbHeight / scale);
576 mTmpFromClipRect.set(containingFrame);
577 mTmpToClipRect.set(containingFrame);
578 mTmpToClipRect.bottom = (mTmpToClipRect.top + unscaledThumbHeight);
579 } else {
580 // In landscape, we scale the height and clip to the top/left square
581 scale = thumbHeight / (appHeight - contentInsets.top);
582 scaledTopDecor = (int) (scale * contentInsets.top);
583 int unscaledThumbWidth = (int) (thumbWidth / scale);
584 mTmpFromClipRect.set(containingFrame);
585 mTmpToClipRect.set(containingFrame);
586 mTmpToClipRect.right = (mTmpToClipRect.left + unscaledThumbWidth);
587 }
Winson Chung399f6202014-03-19 10:47:20 -0700588
589 Animation scaleAnim = new ScaleAnimation(1, scale, 1, scale,
590 computePivot(mNextAppTransitionStartX, scale),
591 computePivot(mNextAppTransitionStartY, scale));
592 Animation alphaAnim = new AlphaAnimation(1, 1);
Winson Chung2820c452014-04-15 15:34:44 -0700593 Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
Winson Chung399f6202014-03-19 10:47:20 -0700594 Animation translateAnim = new TranslateAnimation(0, 0, 0, -scaledTopDecor);
595
596 AnimationSet set = new AnimationSet(true);
597 set.addAnimation(alphaAnim);
598 set.addAnimation(clipAnim);
599 set.addAnimation(scaleAnim);
600 set.addAnimation(translateAnim);
601
602 a = set;
603 a.setZAdjustment(Animation.ZORDER_TOP);
604 break;
605 }
606 default:
607 throw new RuntimeException("Invalid thumbnail transition state");
608 }
609
Winson Chung5393dff2014-05-08 14:25:43 -0700610 return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight,
611 THUMBNAIL_APP_TRANSITION_DURATION, mThumbnailCubicInterpolator);
Winson Chung399f6202014-03-19 10:47:20 -0700612 }
613
614 /**
615 * This animation is created when we are doing a thumbnail transition, for the activity that is
616 * leaving, and the activity that is entering.
617 */
618 Animation createThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth,
619 int appHeight, int transit) {
620 Animation a;
621 final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
622 final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
623 final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
624 final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
625
626 switch (thumbTransitState) {
627 case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: {
628 // Entering app scales up with the thumbnail
629 float scaleW = thumbWidth / appWidth;
630 float scaleH = thumbHeight / appHeight;
631 a = new ScaleAnimation(scaleW, 1, scaleH, 1,
632 computePivot(mNextAppTransitionStartX, scaleW),
633 computePivot(mNextAppTransitionStartY, scaleH));
634 break;
635 }
636 case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: {
637 // Exiting app while the thumbnail is scaling up should fade or stay in place
638 if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) {
639 // Fade out while bringing up selected activity. This keeps the
640 // current activity from showing through a launching wallpaper
641 // activity.
642 a = new AlphaAnimation(1, 0);
643 } else {
644 // noop animation
645 a = new AlphaAnimation(1, 1);
646 }
647 break;
648 }
649 case THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN: {
650 // Entering the other app, it should just be visible while we scale the thumbnail
651 // down above it
652 a = new AlphaAnimation(1, 1);
653 break;
654 }
655 case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: {
656 // Exiting the current app, the app should scale down with the thumbnail
657 float scaleW = thumbWidth / appWidth;
658 float scaleH = thumbHeight / appHeight;
659 Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
660 computePivot(mNextAppTransitionStartX, scaleW),
661 computePivot(mNextAppTransitionStartY, scaleH));
662
663 Animation alpha = new AlphaAnimation(1, 0);
664
665 AnimationSet set = new AnimationSet(true);
666 set.addAnimation(scale);
667 set.addAnimation(alpha);
668 set.setZAdjustment(Animation.ZORDER_TOP);
669 a = set;
670 break;
671 }
672 default:
673 throw new RuntimeException("Invalid thumbnail transition state");
674 }
675
676 return prepareThumbnailAnimation(a, appWidth, appHeight, transit);
677 }
678
Craig Mautner164d4bb2012-11-26 13:51:23 -0800679
680 Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
Winson Chung2820c452014-04-15 15:34:44 -0700681 int appWidth, int appHeight, int orientation,
Winson Chungf9f23142014-04-21 14:45:27 -0700682 Rect containingFrame, Rect contentInsets, Configuration configuration) {
Craig Mautner164d4bb2012-11-26 13:51:23 -0800683 Animation a;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800684 if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {
Craig Mautner164d4bb2012-11-26 13:51:23 -0800685 a = loadAnimation(mNextAppTransitionPackage, enter ?
686 mNextAppTransitionEnter : mNextAppTransitionExit);
687 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
688 "applyAnimation:"
689 + " anim=" + a + " nextAppTransition=ANIM_CUSTOM"
690 + " transit=" + transit + " isEntrance=" + enter
691 + " Callers=" + Debug.getCallers(3));
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800692 } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_SCALE_UP) {
Craig Mautner164d4bb2012-11-26 13:51:23 -0800693 a = createScaleUpAnimationLocked(transit, enter, appWidth, appHeight);
694 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
695 "applyAnimation:"
696 + " anim=" + a + " nextAppTransition=ANIM_SCALE_UP"
697 + " transit=" + transit + " isEntrance=" + enter
698 + " Callers=" + Debug.getCallers(3));
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800699 } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP ||
700 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) {
Craig Mautner164d4bb2012-11-26 13:51:23 -0800701 mNextAppTransitionScaleUp =
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800702 (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
Winson Chungf9f23142014-04-21 14:45:27 -0700703 boolean useAlternateThumbnailAnimation = (configuration.smallestScreenWidthDp < 600);
704 if (useAlternateThumbnailAnimation) {
Winson Chung399f6202014-03-19 10:47:20 -0700705 a = createAlternateThumbnailEnterExitAnimationLocked(
Winson Chung2820c452014-04-15 15:34:44 -0700706 getThumbnailTransitionState(enter), appWidth, appHeight, orientation,
707 transit, containingFrame, contentInsets);
Winson Chung399f6202014-03-19 10:47:20 -0700708 } else {
709 a = createThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter),
710 appWidth, appHeight, transit);
711 }
Craig Mautner164d4bb2012-11-26 13:51:23 -0800712 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
713 String animName = mNextAppTransitionScaleUp ?
714 "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
715 Slog.v(TAG, "applyAnimation:"
716 + " anim=" + a + " nextAppTransition=" + animName
717 + " transit=" + transit + " isEntrance=" + enter
718 + " Callers=" + Debug.getCallers(3));
719 }
720 } else {
721 int animAttr = 0;
722 switch (transit) {
Craig Mautner4b71aa12012-12-27 17:20:01 -0800723 case TRANSIT_ACTIVITY_OPEN:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800724 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800725 ? WindowAnimation_activityOpenEnterAnimation
726 : WindowAnimation_activityOpenExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800727 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800728 case TRANSIT_ACTIVITY_CLOSE:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800729 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800730 ? WindowAnimation_activityCloseEnterAnimation
731 : WindowAnimation_activityCloseExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800732 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800733 case TRANSIT_TASK_OPEN:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800734 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800735 ? WindowAnimation_taskOpenEnterAnimation
736 : WindowAnimation_taskOpenExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800737 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800738 case TRANSIT_TASK_CLOSE:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800739 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800740 ? WindowAnimation_taskCloseEnterAnimation
741 : WindowAnimation_taskCloseExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800742 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800743 case TRANSIT_TASK_TO_FRONT:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800744 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800745 ? WindowAnimation_taskToFrontEnterAnimation
746 : WindowAnimation_taskToFrontExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800747 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800748 case TRANSIT_TASK_TO_BACK:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800749 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800750 ? WindowAnimation_taskToBackEnterAnimation
751 : WindowAnimation_taskToBackExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800752 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800753 case TRANSIT_WALLPAPER_OPEN:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800754 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800755 ? WindowAnimation_wallpaperOpenEnterAnimation
756 : WindowAnimation_wallpaperOpenExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800757 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800758 case TRANSIT_WALLPAPER_CLOSE:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800759 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800760 ? WindowAnimation_wallpaperCloseEnterAnimation
761 : WindowAnimation_wallpaperCloseExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800762 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800763 case TRANSIT_WALLPAPER_INTRA_OPEN:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800764 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800765 ? WindowAnimation_wallpaperIntraOpenEnterAnimation
766 : WindowAnimation_wallpaperIntraOpenExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800767 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800768 case TRANSIT_WALLPAPER_INTRA_CLOSE:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800769 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800770 ? WindowAnimation_wallpaperIntraCloseEnterAnimation
771 : WindowAnimation_wallpaperIntraCloseExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800772 break;
773 }
774 a = animAttr != 0 ? loadAnimation(lp, animAttr) : null;
775 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
776 "applyAnimation:"
777 + " anim=" + a
778 + " animAttr=0x" + Integer.toHexString(animAttr)
779 + " transit=" + transit + " isEntrance=" + enter
780 + " Callers=" + Debug.getCallers(3));
781 }
782 return a;
783 }
784
785 void postAnimationCallback() {
786 if (mNextAppTransitionCallback != null) {
787 mH.sendMessage(mH.obtainMessage(H.DO_ANIMATION_CALLBACK, mNextAppTransitionCallback));
788 mNextAppTransitionCallback = null;
789 }
790 }
791
792 void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim,
793 IRemoteCallback startedCallback) {
794 if (isTransitionSet()) {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800795 mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800796 mNextAppTransitionPackage = packageName;
797 mNextAppTransitionThumbnail = null;
798 mNextAppTransitionEnter = enterAnim;
799 mNextAppTransitionExit = exitAnim;
800 postAnimationCallback();
801 mNextAppTransitionCallback = startedCallback;
802 } else {
803 postAnimationCallback();
804 }
805 }
806
807 void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
808 int startHeight) {
809 if (isTransitionSet()) {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800810 mNextAppTransitionType = NEXT_TRANSIT_TYPE_SCALE_UP;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800811 mNextAppTransitionPackage = null;
812 mNextAppTransitionThumbnail = null;
813 mNextAppTransitionStartX = startX;
814 mNextAppTransitionStartY = startY;
815 mNextAppTransitionStartWidth = startWidth;
816 mNextAppTransitionStartHeight = startHeight;
817 postAnimationCallback();
818 mNextAppTransitionCallback = null;
819 }
820 }
821
822 void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY,
823 IRemoteCallback startedCallback, boolean scaleUp) {
824 if (isTransitionSet()) {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800825 mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP
826 : NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800827 mNextAppTransitionPackage = null;
828 mNextAppTransitionThumbnail = srcThumb;
829 mNextAppTransitionScaleUp = scaleUp;
830 mNextAppTransitionStartX = startX;
831 mNextAppTransitionStartY = startY;
832 postAnimationCallback();
833 mNextAppTransitionCallback = startedCallback;
834 } else {
835 postAnimationCallback();
836 }
837 }
838
839 @Override
840 public String toString() {
841 return "mNextAppTransition=0x" + Integer.toHexString(mNextAppTransition);
842 }
843
Craig Mautner4b71aa12012-12-27 17:20:01 -0800844 /**
845 * Returns the human readable name of a window transition.
846 *
847 * @param transition The window transition.
848 * @return The transition symbolic name.
849 */
850 public static String appTransitionToString(int transition) {
851 switch (transition) {
852 case TRANSIT_UNSET: {
853 return "TRANSIT_UNSET";
854 }
855 case TRANSIT_NONE: {
856 return "TRANSIT_NONE";
857 }
858 case TRANSIT_EXIT_MASK: {
859 return "TRANSIT_EXIT_MASK";
860 }
861 case TRANSIT_ACTIVITY_OPEN: {
862 return "TRANSIT_ACTIVITY_OPEN";
863 }
864 case TRANSIT_ACTIVITY_CLOSE: {
865 return "TRANSIT_ACTIVITY_CLOSE";
866 }
867 case TRANSIT_TASK_OPEN: {
868 return "TRANSIT_TASK_OPEN";
869 }
870 case TRANSIT_TASK_CLOSE: {
871 return "TRANSIT_TASK_CLOSE";
872 }
873 case TRANSIT_TASK_TO_FRONT: {
874 return "TRANSIT_TASK_TO_FRONT";
875 }
876 case TRANSIT_TASK_TO_BACK: {
877 return "TRANSIT_TASK_TO_BACK";
878 }
879 case TRANSIT_WALLPAPER_CLOSE: {
880 return "TRANSIT_WALLPAPER_CLOSE";
881 }
882 case TRANSIT_WALLPAPER_OPEN: {
883 return "TRANSIT_WALLPAPER_OPEN";
884 }
885 case TRANSIT_WALLPAPER_INTRA_OPEN: {
886 return "TRANSIT_WALLPAPER_INTRA_OPEN";
887 }
888 case TRANSIT_WALLPAPER_INTRA_CLOSE: {
889 return "TRANSIT_WALLPAPER_INTRA_CLOSE";
890 }
891 default: {
892 return "<UNKNOWN>";
893 }
894 }
895 }
896
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800897 private String appStateToString() {
898 switch (mAppTransitionState) {
899 case APP_STATE_IDLE:
900 return "APP_STATE_IDLE";
901 case APP_STATE_READY:
902 return "APP_STATE_READY";
903 case APP_STATE_RUNNING:
904 return "APP_STATE_RUNNING";
905 case APP_STATE_TIMEOUT:
906 return "APP_STATE_TIMEOUT";
907 default:
908 return "unknown state=" + mAppTransitionState;
909 }
910 }
911
912 private String transitTypeToString() {
913 switch (mNextAppTransitionType) {
914 case NEXT_TRANSIT_TYPE_NONE:
915 return "NEXT_TRANSIT_TYPE_NONE";
916 case NEXT_TRANSIT_TYPE_CUSTOM:
917 return "NEXT_TRANSIT_TYPE_CUSTOM";
918 case NEXT_TRANSIT_TYPE_SCALE_UP:
919 return "NEXT_TRANSIT_TYPE_SCALE_UP";
920 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP:
921 return "NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP";
922 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN:
923 return "NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN";
924 default:
925 return "unknown type=" + mNextAppTransitionType;
926 }
927 }
928
Craig Mautner164d4bb2012-11-26 13:51:23 -0800929 @Override
930 public void dump(PrintWriter pw) {
931 pw.print(" " + this);
Craig Mautner28816302013-10-10 20:31:00 -0700932 pw.print(" mAppTransitionState="); pw.println(appStateToString());
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800933 if (mNextAppTransitionType != NEXT_TRANSIT_TYPE_NONE) {
934 pw.print(" mNextAppTransitionType="); pw.println(transitTypeToString());
Craig Mautner164d4bb2012-11-26 13:51:23 -0800935 }
936 switch (mNextAppTransitionType) {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800937 case NEXT_TRANSIT_TYPE_CUSTOM:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800938 pw.print(" mNextAppTransitionPackage=");
939 pw.println(mNextAppTransitionPackage);
940 pw.print(" mNextAppTransitionEnter=0x");
941 pw.print(Integer.toHexString(mNextAppTransitionEnter));
942 pw.print(" mNextAppTransitionExit=0x");
943 pw.println(Integer.toHexString(mNextAppTransitionExit));
944 break;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800945 case NEXT_TRANSIT_TYPE_SCALE_UP:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800946 pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX);
947 pw.print(" mNextAppTransitionStartY=");
948 pw.println(mNextAppTransitionStartY);
949 pw.print(" mNextAppTransitionStartWidth=");
950 pw.print(mNextAppTransitionStartWidth);
951 pw.print(" mNextAppTransitionStartHeight=");
952 pw.println(mNextAppTransitionStartHeight);
953 break;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800954 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP:
955 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800956 pw.print(" mNextAppTransitionThumbnail=");
957 pw.print(mNextAppTransitionThumbnail);
958 pw.print(" mNextAppTransitionStartX=");
959 pw.print(mNextAppTransitionStartX);
960 pw.print(" mNextAppTransitionStartY=");
961 pw.println(mNextAppTransitionStartY);
962 pw.print(" mNextAppTransitionScaleUp="); pw.println(mNextAppTransitionScaleUp);
963 break;
964 }
965 if (mNextAppTransitionCallback != null) {
966 pw.print(" mNextAppTransitionCallback=");
967 pw.println(mNextAppTransitionCallback);
968 }
969 }
Amith Yamasani4befbec2013-07-10 16:18:01 -0700970
971 public void setCurrentUser(int newUserId) {
972 mCurrentUserId = newUserId;
973 }
Craig Mautner164d4bb2012-11-26 13:51:23 -0800974}