blob: cd3daaa9f2714022e94eb472245e5b2a6409978c [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;
20import android.graphics.Bitmap;
21import android.graphics.Point;
22import android.os.Debug;
23import android.os.Handler;
24import android.os.IRemoteCallback;
25import android.util.Slog;
26import android.view.WindowManager;
Craig Mautner164d4bb2012-11-26 13:51:23 -080027import android.view.animation.AlphaAnimation;
28import android.view.animation.Animation;
29import android.view.animation.AnimationSet;
30import android.view.animation.AnimationUtils;
Craig Mautner164d4bb2012-11-26 13:51:23 -080031import android.view.animation.Interpolator;
32import android.view.animation.ScaleAnimation;
33
34import com.android.internal.util.DumpUtils.Dump;
35import com.android.server.AttributeCache;
36import com.android.server.wm.WindowManagerService.H;
37
38import java.io.PrintWriter;
39
Craig Mautner9a29a5d2012-12-27 19:03:40 -080040import static com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation;
41import static com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
42import static com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation;
43import static com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
44import static com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation;
45import static com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
46import static com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation;
47import static com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
48import static com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation;
49import static com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation;
50import static com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation;
51import static com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
52import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation;
53import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
54import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation;
55import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation;
56import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation;
57import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
58import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation;
59import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation;
60
Craig Mautner164d4bb2012-11-26 13:51:23 -080061// State management of app transitions. When we are preparing for a
62// transition, mNextAppTransition will be the kind of transition to
63// perform or TRANSIT_NONE if we are not waiting. If we are waiting,
64// mOpeningApps and mClosingApps are the lists of tokens that will be
65// made visible or hidden at the next transition.
66public class AppTransition implements Dump {
67 private static final String TAG = "AppTransition";
Craig Mautner321bdf52012-12-18 09:53:24 -080068 private static final boolean DEBUG_APP_TRANSITIONS =
69 WindowManagerService.DEBUG_APP_TRANSITIONS;
70 private static final boolean DEBUG_ANIM = WindowManagerService.DEBUG_ANIM;
71
Craig Mautner9a29a5d2012-12-27 19:03:40 -080072 /** Bit mask that is set for all enter transition. */
Craig Mautner4b71aa12012-12-27 17:20:01 -080073 public static final int TRANSIT_ENTER_MASK = 0x1000;
Craig Mautner9a29a5d2012-12-27 19:03:40 -080074
75 /** Bit mask that is set for all exit transitions. */
Craig Mautner4b71aa12012-12-27 17:20:01 -080076 public static final int TRANSIT_EXIT_MASK = 0x2000;
Craig Mautner9a29a5d2012-12-27 19:03:40 -080077
Craig Mautner4b71aa12012-12-27 17:20:01 -080078 /** Not set up for a transition. */
79 public static final int TRANSIT_UNSET = -1;
80 /** No animation for transition. */
81 public static final int TRANSIT_NONE = 0;
82 /** A window in a new activity is being opened on top of an existing one in the same task. */
83 public static final int TRANSIT_ACTIVITY_OPEN = 6 | TRANSIT_ENTER_MASK;
84 /** The window in the top-most activity is being closed to reveal the
85 * previous activity in the same task. */
86 public static final int TRANSIT_ACTIVITY_CLOSE = 7 | TRANSIT_EXIT_MASK;
87 /** A window in a new task is being opened on top of an existing one
88 * in another activity's task. */
89 public static final int TRANSIT_TASK_OPEN = 8 | TRANSIT_ENTER_MASK;
90 /** A window in the top-most activity is being closed to reveal the
91 * previous activity in a different task. */
92 public static final int TRANSIT_TASK_CLOSE = 9 | TRANSIT_EXIT_MASK;
93 /** A window in an existing task is being displayed on top of an existing one
94 * in another activity's task. */
95 public static final int TRANSIT_TASK_TO_FRONT = 10 | TRANSIT_ENTER_MASK;
96 /** A window in an existing task is being put below all other tasks. */
97 public static final int TRANSIT_TASK_TO_BACK = 11 | TRANSIT_EXIT_MASK;
Craig Mautner9a29a5d2012-12-27 19:03:40 -080098 /** A window in a new activity that doesn't have a wallpaper is being opened on top of one that
99 * does, effectively closing the wallpaper. */
Craig Mautner4b71aa12012-12-27 17:20:01 -0800100 public static final int TRANSIT_WALLPAPER_CLOSE = 12 | TRANSIT_EXIT_MASK;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800101 /** A window in a new activity that does have a wallpaper is being opened on one that didn't,
102 * effectively opening the wallpaper. */
Craig Mautner4b71aa12012-12-27 17:20:01 -0800103 public static final int TRANSIT_WALLPAPER_OPEN = 13 | TRANSIT_ENTER_MASK;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800104 /** A window in a new activity is being opened on top of an existing one, and both are on top
105 * of the wallpaper. */
Craig Mautner4b71aa12012-12-27 17:20:01 -0800106 public static final int TRANSIT_WALLPAPER_INTRA_OPEN = 14 | TRANSIT_ENTER_MASK;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800107 /** The window in the top-most activity is being closed to reveal the previous activity, and
108 * both are on top of the wallpaper. */
Craig Mautner4b71aa12012-12-27 17:20:01 -0800109 public static final int TRANSIT_WALLPAPER_INTRA_CLOSE = 15 | TRANSIT_EXIT_MASK;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800110
Craig Mautner321bdf52012-12-18 09:53:24 -0800111 /** Fraction of animation at which the recents thumbnail becomes completely transparent */
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800112 private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.25f;
Craig Mautner321bdf52012-12-18 09:53:24 -0800113
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800114 private static final long DEFAULT_APP_TRANSITION_DURATION = 250;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800115
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800116 private final Context mContext;
117 private final Handler mH;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800118
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800119 private int mNextAppTransition = TRANSIT_UNSET;
120
121 private static final int NEXT_TRANSIT_TYPE_NONE = 0;
122 private static final int NEXT_TRANSIT_TYPE_CUSTOM = 1;
123 private static final int NEXT_TRANSIT_TYPE_SCALE_UP = 2;
124 private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP = 3;
125 private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN = 4;
126 private int mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
127
128 private String mNextAppTransitionPackage;
129 private Bitmap mNextAppTransitionThumbnail;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800130 // Used for thumbnail transitions. True if we're scaling up, false if scaling down
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800131 private boolean mNextAppTransitionScaleUp;
132 private IRemoteCallback mNextAppTransitionCallback;
133 private int mNextAppTransitionEnter;
134 private int mNextAppTransitionExit;
135 private int mNextAppTransitionStartX;
136 private int mNextAppTransitionStartY;
137 private int mNextAppTransitionStartWidth;
138 private int mNextAppTransitionStartHeight;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800139
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800140 private final static int APP_STATE_IDLE = 0;
141 private final static int APP_STATE_READY = 1;
142 private final static int APP_STATE_RUNNING = 2;
143 private final static int APP_STATE_TIMEOUT = 3;
144 private int mAppTransitionState = APP_STATE_IDLE;
145
146 private final int mConfigShortAnimTime;
Craig Mautner321bdf52012-12-18 09:53:24 -0800147 private final Interpolator mDecelerateInterpolator;
148 private final Interpolator mThumbnailFadeoutInterpolator;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800149
Amith Yamasani4befbec2013-07-10 16:18:01 -0700150 private int mCurrentUserId = 0;
151
Craig Mautner164d4bb2012-11-26 13:51:23 -0800152 AppTransition(Context context, Handler h) {
153 mContext = context;
154 mH = h;
155 mConfigShortAnimTime = context.getResources().getInteger(
156 com.android.internal.R.integer.config_shortAnimTime);
Craig Mautner321bdf52012-12-18 09:53:24 -0800157 mDecelerateInterpolator = AnimationUtils.loadInterpolator(context,
158 com.android.internal.R.interpolator.decelerate_cubic);
159 mThumbnailFadeoutInterpolator = new Interpolator() {
160 @Override
161 public float getInterpolation(float input) {
162 // Linear response for first fraction, then complete after that.
163 if (input < RECENTS_THUMBNAIL_FADEOUT_FRACTION) {
164 return input / RECENTS_THUMBNAIL_FADEOUT_FRACTION;
165 }
166 return 1.0f;
167 }
168 };
Craig Mautner164d4bb2012-11-26 13:51:23 -0800169 }
170
171 boolean isTransitionSet() {
172 return mNextAppTransition != TRANSIT_UNSET;
173 }
174
175 boolean isTransitionNone() {
176 return mNextAppTransition == TRANSIT_NONE;
177 }
178
179 boolean isTransitionEqual(int transit) {
180 return mNextAppTransition == transit;
181 }
182
183 int getAppTransition() {
Craig Mautner321bdf52012-12-18 09:53:24 -0800184 return mNextAppTransition;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800185 }
186
187 void setAppTransition(int transit) {
188 mNextAppTransition = transit;
189 }
190
191 boolean isReady() {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800192 return mAppTransitionState == APP_STATE_READY
193 || mAppTransitionState == APP_STATE_TIMEOUT;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800194 }
195
Craig Mautnerae446592012-12-06 19:05:05 -0800196 void setReady() {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800197 mAppTransitionState = APP_STATE_READY;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800198 }
199
200 boolean isRunning() {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800201 return mAppTransitionState == APP_STATE_RUNNING;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800202 }
203
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800204 void setIdle() {
205 mAppTransitionState = APP_STATE_IDLE;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800206 }
207
208 boolean isTimeout() {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800209 return mAppTransitionState == APP_STATE_TIMEOUT;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800210 }
211
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800212 void setTimeout() {
213 mAppTransitionState = APP_STATE_TIMEOUT;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800214 }
215
216 Bitmap getNextAppTransitionThumbnail() {
217 return mNextAppTransitionThumbnail;
218 }
219
220 void getStartingPoint(Point outPoint) {
221 outPoint.x = mNextAppTransitionStartX;
222 outPoint.y = mNextAppTransitionStartY;
223 }
224
Craig Mautner164d4bb2012-11-26 13:51:23 -0800225 void prepare() {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800226 if (!isRunning()) {
227 mAppTransitionState = APP_STATE_IDLE;
228 }
Craig Mautner164d4bb2012-11-26 13:51:23 -0800229 }
230
231 void goodToGo() {
Craig Mautner4b71aa12012-12-27 17:20:01 -0800232 mNextAppTransition = TRANSIT_UNSET;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800233 mAppTransitionState = APP_STATE_RUNNING;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800234 }
235
236 void clear() {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800237 mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800238 mNextAppTransitionPackage = null;
239 mNextAppTransitionThumbnail = null;
240 }
241
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800242 void freeze() {
243 setAppTransition(AppTransition.TRANSIT_UNSET);
244 clear();
245 setReady();
246 }
247
Craig Mautner164d4bb2012-11-26 13:51:23 -0800248 private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
249 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: layout params pkg="
250 + (lp != null ? lp.packageName : null)
251 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null));
252 if (lp != null && lp.windowAnimations != 0) {
253 // If this is a system resource, don't try to load it from the
254 // application resources. It is nice to avoid loading application
255 // resources if we can.
256 String packageName = lp.packageName != null ? lp.packageName : "android";
257 int resId = lp.windowAnimations;
258 if ((resId&0xFF000000) == 0x01000000) {
259 packageName = "android";
260 }
261 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
262 + packageName);
263 return AttributeCache.instance().get(packageName, resId,
Amith Yamasani4befbec2013-07-10 16:18:01 -0700264 com.android.internal.R.styleable.WindowAnimation, mCurrentUserId);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800265 }
266 return null;
267 }
268
269 private AttributeCache.Entry getCachedAnimations(String packageName, int resId) {
270 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: package="
271 + packageName + " resId=0x" + Integer.toHexString(resId));
272 if (packageName != null) {
273 if ((resId&0xFF000000) == 0x01000000) {
274 packageName = "android";
275 }
276 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
277 + packageName);
278 return AttributeCache.instance().get(packageName, resId,
Amith Yamasani4befbec2013-07-10 16:18:01 -0700279 com.android.internal.R.styleable.WindowAnimation, mCurrentUserId);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800280 }
281 return null;
282 }
283
284 Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) {
285 int anim = 0;
286 Context context = mContext;
287 if (animAttr >= 0) {
288 AttributeCache.Entry ent = getCachedAnimations(lp);
289 if (ent != null) {
290 context = ent.context;
291 anim = ent.array.getResourceId(animAttr, 0);
292 }
293 }
294 if (anim != 0) {
295 return AnimationUtils.loadAnimation(context, anim);
296 }
297 return null;
298 }
299
300 private Animation loadAnimation(String packageName, int resId) {
301 int anim = 0;
302 Context context = mContext;
303 if (resId >= 0) {
304 AttributeCache.Entry ent = getCachedAnimations(packageName, resId);
305 if (ent != null) {
306 context = ent.context;
307 anim = resId;
308 }
309 }
310 if (anim != 0) {
311 return AnimationUtils.loadAnimation(context, anim);
312 }
313 return null;
314 }
315
Craig Mautner164d4bb2012-11-26 13:51:23 -0800316 /**
317 * Compute the pivot point for an animation that is scaling from a small
318 * rect on screen to a larger rect. The pivot point varies depending on
319 * the distance between the inner and outer edges on both sides. This
320 * function computes the pivot point for one dimension.
321 * @param startPos Offset from left/top edge of outer rectangle to
322 * left/top edge of inner rectangle.
323 * @param finalScale The scaling factor between the size of the outer
324 * and inner rectangles.
325 */
326 private static float computePivot(int startPos, float finalScale) {
327 final float denom = finalScale-1;
328 if (Math.abs(denom) < .0001f) {
329 return startPos;
330 }
331 return -startPos / denom;
332 }
333
334 private Animation createScaleUpAnimationLocked(int transit, boolean enter,
335 int appWidth, int appHeight) {
336 Animation a = null;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800337 if (enter) {
338 // Entering app zooms out from the center of the initial rect.
339 float scaleW = mNextAppTransitionStartWidth / (float) appWidth;
340 float scaleH = mNextAppTransitionStartHeight / (float) appHeight;
341 Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
342 computePivot(mNextAppTransitionStartX, scaleW),
343 computePivot(mNextAppTransitionStartY, scaleH));
Craig Mautner321bdf52012-12-18 09:53:24 -0800344 scale.setInterpolator(mDecelerateInterpolator);
345
Craig Mautner164d4bb2012-11-26 13:51:23 -0800346 Animation alpha = new AlphaAnimation(0, 1);
Craig Mautner321bdf52012-12-18 09:53:24 -0800347 alpha.setInterpolator(mThumbnailFadeoutInterpolator);
348
349 AnimationSet set = new AnimationSet(false);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800350 set.addAnimation(scale);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800351 set.addAnimation(alpha);
352 set.setDetachWallpaper(true);
353 a = set;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800354 } else if (transit == TRANSIT_WALLPAPER_INTRA_OPEN ||
355 transit == TRANSIT_WALLPAPER_INTRA_CLOSE) {
Craig Mautner321bdf52012-12-18 09:53:24 -0800356 // If we are on top of the wallpaper, we need an animation that
357 // correctly handles the wallpaper staying static behind all of
358 // the animated elements. To do this, will just have the existing
359 // element fade out.
360 a = new AlphaAnimation(1, 0);
361 a.setDetachWallpaper(true);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800362 } else {
Craig Mautner321bdf52012-12-18 09:53:24 -0800363 // For normal animations, the exiting element just holds in place.
364 a = new AlphaAnimation(1, 1);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800365 }
Craig Mautner321bdf52012-12-18 09:53:24 -0800366
367 // Pick the desired duration. If this is an inter-activity transition,
368 // it is the standard duration for that. Otherwise we use the longer
369 // task transition duration.
370 final long duration;
371 switch (transit) {
Craig Mautner4b71aa12012-12-27 17:20:01 -0800372 case TRANSIT_ACTIVITY_OPEN:
373 case TRANSIT_ACTIVITY_CLOSE:
Craig Mautner321bdf52012-12-18 09:53:24 -0800374 duration = mConfigShortAnimTime;
375 break;
376 default:
377 duration = DEFAULT_APP_TRANSITION_DURATION;
378 break;
379 }
380 a.setDuration(duration);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800381 a.setFillAfter(true);
Craig Mautner321bdf52012-12-18 09:53:24 -0800382 a.setInterpolator(mDecelerateInterpolator);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800383 a.initialize(appWidth, appHeight, appWidth, appHeight);
384 return a;
385 }
386
387 Animation createThumbnailAnimationLocked(int transit, boolean enter, boolean thumb,
388 int appWidth, int appHeight) {
389 Animation a;
390 final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
391 final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
392 final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
393 final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800394 if (thumb) {
395 // Animation for zooming thumbnail from its initial size to
396 // filling the screen.
397 if (mNextAppTransitionScaleUp) {
398 float scaleW = appWidth / thumbWidth;
399 float scaleH = appHeight / thumbHeight;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800400 Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
401 computePivot(mNextAppTransitionStartX, 1 / scaleW),
402 computePivot(mNextAppTransitionStartY, 1 / scaleH));
Craig Mautner321bdf52012-12-18 09:53:24 -0800403 scale.setInterpolator(mDecelerateInterpolator);
404
Craig Mautner164d4bb2012-11-26 13:51:23 -0800405 Animation alpha = new AlphaAnimation(1, 0);
Craig Mautner321bdf52012-12-18 09:53:24 -0800406 alpha.setInterpolator(mThumbnailFadeoutInterpolator);
407
408 // This AnimationSet uses the Interpolators assigned above.
409 AnimationSet set = new AnimationSet(false);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800410 set.addAnimation(scale);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800411 set.addAnimation(alpha);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800412 a = set;
413 } else {
414 float scaleW = appWidth / thumbWidth;
415 float scaleH = appHeight / thumbHeight;
Craig Mautner321bdf52012-12-18 09:53:24 -0800416 a = new ScaleAnimation(scaleW, 1, scaleH, 1,
Craig Mautner164d4bb2012-11-26 13:51:23 -0800417 computePivot(mNextAppTransitionStartX, 1 / scaleW),
418 computePivot(mNextAppTransitionStartY, 1 / scaleH));
Craig Mautner164d4bb2012-11-26 13:51:23 -0800419 }
420 } else if (enter) {
421 // Entering app zooms out from the center of the thumbnail.
422 if (mNextAppTransitionScaleUp) {
423 float scaleW = thumbWidth / appWidth;
424 float scaleH = thumbHeight / appHeight;
Craig Mautner321bdf52012-12-18 09:53:24 -0800425 a = new ScaleAnimation(scaleW, 1, scaleH, 1,
Craig Mautner164d4bb2012-11-26 13:51:23 -0800426 computePivot(mNextAppTransitionStartX, scaleW),
427 computePivot(mNextAppTransitionStartY, scaleH));
Craig Mautner164d4bb2012-11-26 13:51:23 -0800428 } else {
429 // noop animation
430 a = new AlphaAnimation(1, 1);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800431 }
432 } else {
433 // Exiting app
434 if (mNextAppTransitionScaleUp) {
Craig Mautner4b71aa12012-12-27 17:20:01 -0800435 if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) {
Craig Mautner164d4bb2012-11-26 13:51:23 -0800436 // Fade out while bringing up selected activity. This keeps the
437 // current activity from showing through a launching wallpaper
438 // activity.
439 a = new AlphaAnimation(1, 0);
440 } else {
441 // noop animation
442 a = new AlphaAnimation(1, 1);
443 }
Craig Mautner164d4bb2012-11-26 13:51:23 -0800444 } else {
445 float scaleW = thumbWidth / appWidth;
446 float scaleH = thumbHeight / appHeight;
447 Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
448 computePivot(mNextAppTransitionStartX, scaleW),
449 computePivot(mNextAppTransitionStartY, scaleH));
Craig Mautner321bdf52012-12-18 09:53:24 -0800450
Craig Mautner164d4bb2012-11-26 13:51:23 -0800451 Animation alpha = new AlphaAnimation(1, 0);
Craig Mautner321bdf52012-12-18 09:53:24 -0800452
453 AnimationSet set = new AnimationSet(true);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800454 set.addAnimation(scale);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800455 set.addAnimation(alpha);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800456 set.setZAdjustment(Animation.ZORDER_TOP);
457 a = set;
458 }
459 }
Craig Mautner321bdf52012-12-18 09:53:24 -0800460
461 // Pick the desired duration. If this is an inter-activity transition,
462 // it is the standard duration for that. Otherwise we use the longer
463 // task transition duration.
464 final long duration;
465 switch (transit) {
Craig Mautner4b71aa12012-12-27 17:20:01 -0800466 case TRANSIT_ACTIVITY_OPEN:
467 case TRANSIT_ACTIVITY_CLOSE:
Craig Mautner321bdf52012-12-18 09:53:24 -0800468 duration = mConfigShortAnimTime;
469 break;
470 default:
471 duration = DEFAULT_APP_TRANSITION_DURATION;
472 break;
473 }
474 a.setDuration(duration);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800475 a.setFillAfter(true);
Craig Mautner321bdf52012-12-18 09:53:24 -0800476 a.setInterpolator(mDecelerateInterpolator);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800477 a.initialize(appWidth, appHeight, appWidth, appHeight);
478 return a;
479 }
480
481
482 Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
483 int appWidth, int appHeight) {
484 Animation a;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800485 if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {
Craig Mautner164d4bb2012-11-26 13:51:23 -0800486 a = loadAnimation(mNextAppTransitionPackage, enter ?
487 mNextAppTransitionEnter : mNextAppTransitionExit);
488 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
489 "applyAnimation:"
490 + " anim=" + a + " nextAppTransition=ANIM_CUSTOM"
491 + " transit=" + transit + " isEntrance=" + enter
492 + " Callers=" + Debug.getCallers(3));
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800493 } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_SCALE_UP) {
Craig Mautner164d4bb2012-11-26 13:51:23 -0800494 a = createScaleUpAnimationLocked(transit, enter, appWidth, appHeight);
495 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
496 "applyAnimation:"
497 + " anim=" + a + " nextAppTransition=ANIM_SCALE_UP"
498 + " transit=" + transit + " isEntrance=" + enter
499 + " Callers=" + Debug.getCallers(3));
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800500 } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP ||
501 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) {
Craig Mautner164d4bb2012-11-26 13:51:23 -0800502 mNextAppTransitionScaleUp =
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800503 (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800504 a = createThumbnailAnimationLocked(transit, enter, false, appWidth, appHeight);
505 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
506 String animName = mNextAppTransitionScaleUp ?
507 "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
508 Slog.v(TAG, "applyAnimation:"
509 + " anim=" + a + " nextAppTransition=" + animName
510 + " transit=" + transit + " isEntrance=" + enter
511 + " Callers=" + Debug.getCallers(3));
512 }
513 } else {
514 int animAttr = 0;
515 switch (transit) {
Craig Mautner4b71aa12012-12-27 17:20:01 -0800516 case TRANSIT_ACTIVITY_OPEN:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800517 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800518 ? WindowAnimation_activityOpenEnterAnimation
519 : WindowAnimation_activityOpenExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800520 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800521 case TRANSIT_ACTIVITY_CLOSE:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800522 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800523 ? WindowAnimation_activityCloseEnterAnimation
524 : WindowAnimation_activityCloseExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800525 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800526 case TRANSIT_TASK_OPEN:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800527 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800528 ? WindowAnimation_taskOpenEnterAnimation
529 : WindowAnimation_taskOpenExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800530 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800531 case TRANSIT_TASK_CLOSE:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800532 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800533 ? WindowAnimation_taskCloseEnterAnimation
534 : WindowAnimation_taskCloseExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800535 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800536 case TRANSIT_TASK_TO_FRONT:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800537 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800538 ? WindowAnimation_taskToFrontEnterAnimation
539 : WindowAnimation_taskToFrontExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800540 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800541 case TRANSIT_TASK_TO_BACK:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800542 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800543 ? WindowAnimation_taskToBackEnterAnimation
544 : WindowAnimation_taskToBackExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800545 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800546 case TRANSIT_WALLPAPER_OPEN:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800547 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800548 ? WindowAnimation_wallpaperOpenEnterAnimation
549 : WindowAnimation_wallpaperOpenExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800550 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800551 case TRANSIT_WALLPAPER_CLOSE:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800552 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800553 ? WindowAnimation_wallpaperCloseEnterAnimation
554 : WindowAnimation_wallpaperCloseExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800555 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800556 case TRANSIT_WALLPAPER_INTRA_OPEN:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800557 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800558 ? WindowAnimation_wallpaperIntraOpenEnterAnimation
559 : WindowAnimation_wallpaperIntraOpenExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800560 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800561 case TRANSIT_WALLPAPER_INTRA_CLOSE:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800562 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800563 ? WindowAnimation_wallpaperIntraCloseEnterAnimation
564 : WindowAnimation_wallpaperIntraCloseExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800565 break;
566 }
567 a = animAttr != 0 ? loadAnimation(lp, animAttr) : null;
568 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
569 "applyAnimation:"
570 + " anim=" + a
571 + " animAttr=0x" + Integer.toHexString(animAttr)
572 + " transit=" + transit + " isEntrance=" + enter
573 + " Callers=" + Debug.getCallers(3));
574 }
575 return a;
576 }
577
578 void postAnimationCallback() {
579 if (mNextAppTransitionCallback != null) {
580 mH.sendMessage(mH.obtainMessage(H.DO_ANIMATION_CALLBACK, mNextAppTransitionCallback));
581 mNextAppTransitionCallback = null;
582 }
583 }
584
585 void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim,
586 IRemoteCallback startedCallback) {
587 if (isTransitionSet()) {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800588 mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800589 mNextAppTransitionPackage = packageName;
590 mNextAppTransitionThumbnail = null;
591 mNextAppTransitionEnter = enterAnim;
592 mNextAppTransitionExit = exitAnim;
593 postAnimationCallback();
594 mNextAppTransitionCallback = startedCallback;
595 } else {
596 postAnimationCallback();
597 }
598 }
599
600 void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
601 int startHeight) {
602 if (isTransitionSet()) {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800603 mNextAppTransitionType = NEXT_TRANSIT_TYPE_SCALE_UP;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800604 mNextAppTransitionPackage = null;
605 mNextAppTransitionThumbnail = null;
606 mNextAppTransitionStartX = startX;
607 mNextAppTransitionStartY = startY;
608 mNextAppTransitionStartWidth = startWidth;
609 mNextAppTransitionStartHeight = startHeight;
610 postAnimationCallback();
611 mNextAppTransitionCallback = null;
612 }
613 }
614
615 void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY,
616 IRemoteCallback startedCallback, boolean scaleUp) {
617 if (isTransitionSet()) {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800618 mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP
619 : NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800620 mNextAppTransitionPackage = null;
621 mNextAppTransitionThumbnail = srcThumb;
622 mNextAppTransitionScaleUp = scaleUp;
623 mNextAppTransitionStartX = startX;
624 mNextAppTransitionStartY = startY;
625 postAnimationCallback();
626 mNextAppTransitionCallback = startedCallback;
627 } else {
628 postAnimationCallback();
629 }
630 }
631
632 @Override
633 public String toString() {
634 return "mNextAppTransition=0x" + Integer.toHexString(mNextAppTransition);
635 }
636
Craig Mautner4b71aa12012-12-27 17:20:01 -0800637 /**
638 * Returns the human readable name of a window transition.
639 *
640 * @param transition The window transition.
641 * @return The transition symbolic name.
642 */
643 public static String appTransitionToString(int transition) {
644 switch (transition) {
645 case TRANSIT_UNSET: {
646 return "TRANSIT_UNSET";
647 }
648 case TRANSIT_NONE: {
649 return "TRANSIT_NONE";
650 }
651 case TRANSIT_EXIT_MASK: {
652 return "TRANSIT_EXIT_MASK";
653 }
654 case TRANSIT_ACTIVITY_OPEN: {
655 return "TRANSIT_ACTIVITY_OPEN";
656 }
657 case TRANSIT_ACTIVITY_CLOSE: {
658 return "TRANSIT_ACTIVITY_CLOSE";
659 }
660 case TRANSIT_TASK_OPEN: {
661 return "TRANSIT_TASK_OPEN";
662 }
663 case TRANSIT_TASK_CLOSE: {
664 return "TRANSIT_TASK_CLOSE";
665 }
666 case TRANSIT_TASK_TO_FRONT: {
667 return "TRANSIT_TASK_TO_FRONT";
668 }
669 case TRANSIT_TASK_TO_BACK: {
670 return "TRANSIT_TASK_TO_BACK";
671 }
672 case TRANSIT_WALLPAPER_CLOSE: {
673 return "TRANSIT_WALLPAPER_CLOSE";
674 }
675 case TRANSIT_WALLPAPER_OPEN: {
676 return "TRANSIT_WALLPAPER_OPEN";
677 }
678 case TRANSIT_WALLPAPER_INTRA_OPEN: {
679 return "TRANSIT_WALLPAPER_INTRA_OPEN";
680 }
681 case TRANSIT_WALLPAPER_INTRA_CLOSE: {
682 return "TRANSIT_WALLPAPER_INTRA_CLOSE";
683 }
684 default: {
685 return "<UNKNOWN>";
686 }
687 }
688 }
689
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800690 private String appStateToString() {
691 switch (mAppTransitionState) {
692 case APP_STATE_IDLE:
693 return "APP_STATE_IDLE";
694 case APP_STATE_READY:
695 return "APP_STATE_READY";
696 case APP_STATE_RUNNING:
697 return "APP_STATE_RUNNING";
698 case APP_STATE_TIMEOUT:
699 return "APP_STATE_TIMEOUT";
700 default:
701 return "unknown state=" + mAppTransitionState;
702 }
703 }
704
705 private String transitTypeToString() {
706 switch (mNextAppTransitionType) {
707 case NEXT_TRANSIT_TYPE_NONE:
708 return "NEXT_TRANSIT_TYPE_NONE";
709 case NEXT_TRANSIT_TYPE_CUSTOM:
710 return "NEXT_TRANSIT_TYPE_CUSTOM";
711 case NEXT_TRANSIT_TYPE_SCALE_UP:
712 return "NEXT_TRANSIT_TYPE_SCALE_UP";
713 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP:
714 return "NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP";
715 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN:
716 return "NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN";
717 default:
718 return "unknown type=" + mNextAppTransitionType;
719 }
720 }
721
Craig Mautner164d4bb2012-11-26 13:51:23 -0800722 @Override
723 public void dump(PrintWriter pw) {
724 pw.print(" " + this);
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800725 pw.print(" mAppTransitionState="); pw.println(appStateToString());
726 if (mNextAppTransitionType != NEXT_TRANSIT_TYPE_NONE) {
727 pw.print(" mNextAppTransitionType="); pw.println(transitTypeToString());
Craig Mautner164d4bb2012-11-26 13:51:23 -0800728 }
729 switch (mNextAppTransitionType) {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800730 case NEXT_TRANSIT_TYPE_CUSTOM:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800731 pw.print(" mNextAppTransitionPackage=");
732 pw.println(mNextAppTransitionPackage);
733 pw.print(" mNextAppTransitionEnter=0x");
734 pw.print(Integer.toHexString(mNextAppTransitionEnter));
735 pw.print(" mNextAppTransitionExit=0x");
736 pw.println(Integer.toHexString(mNextAppTransitionExit));
737 break;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800738 case NEXT_TRANSIT_TYPE_SCALE_UP:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800739 pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX);
740 pw.print(" mNextAppTransitionStartY=");
741 pw.println(mNextAppTransitionStartY);
742 pw.print(" mNextAppTransitionStartWidth=");
743 pw.print(mNextAppTransitionStartWidth);
744 pw.print(" mNextAppTransitionStartHeight=");
745 pw.println(mNextAppTransitionStartHeight);
746 break;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800747 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP:
748 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800749 pw.print(" mNextAppTransitionThumbnail=");
750 pw.print(mNextAppTransitionThumbnail);
751 pw.print(" mNextAppTransitionStartX=");
752 pw.print(mNextAppTransitionStartX);
753 pw.print(" mNextAppTransitionStartY=");
754 pw.println(mNextAppTransitionStartY);
755 pw.print(" mNextAppTransitionScaleUp="); pw.println(mNextAppTransitionScaleUp);
756 break;
757 }
758 if (mNextAppTransitionCallback != null) {
759 pw.print(" mNextAppTransitionCallback=");
760 pw.println(mNextAppTransitionCallback);
761 }
762 }
Amith Yamasani4befbec2013-07-10 16:18:01 -0700763
764 public void setCurrentUser(int newUserId) {
765 mCurrentUserId = newUserId;
766 }
Craig Mautner164d4bb2012-11-26 13:51:23 -0800767}