blob: 0126675107253e4a7ed7a290774cb2906f4b50ce [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;
Winson Chung399f6202014-03-19 10:47:20 -070022import android.graphics.Rect;
Craig Mautner164d4bb2012-11-26 13:51:23 -080023import android.os.Debug;
24import android.os.Handler;
25import android.os.IRemoteCallback;
26import android.util.Slog;
27import android.view.WindowManager;
Craig Mautner164d4bb2012-11-26 13:51:23 -080028import android.view.animation.AlphaAnimation;
29import android.view.animation.Animation;
30import android.view.animation.AnimationSet;
31import android.view.animation.AnimationUtils;
Winson Chung399f6202014-03-19 10:47:20 -070032import android.view.animation.ClipRectAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -080033import android.view.animation.Interpolator;
34import android.view.animation.ScaleAnimation;
Winson Chung399f6202014-03-19 10:47:20 -070035import android.view.animation.TranslateAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -080036import com.android.internal.util.DumpUtils.Dump;
37import com.android.server.AttributeCache;
38import com.android.server.wm.WindowManagerService.H;
39
40import java.io.PrintWriter;
41
Craig Mautner9a29a5d2012-12-27 19:03:40 -080042import static com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation;
43import static com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
44import static com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation;
45import static com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
46import static com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation;
47import static com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
Craig Mautnerbb742462014-07-07 15:28:55 -070048import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindBackgroundAnimation;
49import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindSourceAnimation;
Craig Mautner9a29a5d2012-12-27 19:03:40 -080050import static com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation;
51import static com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
52import static com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation;
53import static com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation;
54import static com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation;
55import static com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
56import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation;
57import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
58import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation;
59import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation;
60import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation;
61import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
62import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation;
63import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation;
64
Craig Mautner164d4bb2012-11-26 13:51:23 -080065// State management of app transitions. When we are preparing for a
66// transition, mNextAppTransition will be the kind of transition to
67// perform or TRANSIT_NONE if we are not waiting. If we are waiting,
68// mOpeningApps and mClosingApps are the lists of tokens that will be
69// made visible or hidden at the next transition.
70public class AppTransition implements Dump {
71 private static final String TAG = "AppTransition";
Craig Mautner321bdf52012-12-18 09:53:24 -080072 private static final boolean DEBUG_APP_TRANSITIONS =
73 WindowManagerService.DEBUG_APP_TRANSITIONS;
74 private static final boolean DEBUG_ANIM = WindowManagerService.DEBUG_ANIM;
75
Craig Mautner9a29a5d2012-12-27 19:03:40 -080076
Craig Mautner4b71aa12012-12-27 17:20:01 -080077 /** Not set up for a transition. */
78 public static final int TRANSIT_UNSET = -1;
79 /** No animation for transition. */
80 public static final int TRANSIT_NONE = 0;
81 /** A window in a new activity is being opened on top of an existing one in the same task. */
Craig Mautnerbb742462014-07-07 15:28:55 -070082 public static final int TRANSIT_ACTIVITY_OPEN = 6;
Craig Mautner4b71aa12012-12-27 17:20:01 -080083 /** The window in the top-most activity is being closed to reveal the
84 * previous activity in the same task. */
Craig Mautnerbb742462014-07-07 15:28:55 -070085 public static final int TRANSIT_ACTIVITY_CLOSE = 7;
Craig Mautner4b71aa12012-12-27 17:20:01 -080086 /** A window in a new task is being opened on top of an existing one
87 * in another activity's task. */
Craig Mautnerbb742462014-07-07 15:28:55 -070088 public static final int TRANSIT_TASK_OPEN = 8;
Craig Mautner4b71aa12012-12-27 17:20:01 -080089 /** A window in the top-most activity is being closed to reveal the
90 * previous activity in a different task. */
Craig Mautnerbb742462014-07-07 15:28:55 -070091 public static final int TRANSIT_TASK_CLOSE = 9;
Craig Mautner4b71aa12012-12-27 17:20:01 -080092 /** A window in an existing task is being displayed on top of an existing one
93 * in another activity's task. */
Craig Mautnerbb742462014-07-07 15:28:55 -070094 public static final int TRANSIT_TASK_TO_FRONT = 10;
Craig Mautner4b71aa12012-12-27 17:20:01 -080095 /** A window in an existing task is being put below all other tasks. */
Craig Mautnerbb742462014-07-07 15:28:55 -070096 public static final int TRANSIT_TASK_TO_BACK = 11;
Craig Mautner9a29a5d2012-12-27 19:03:40 -080097 /** A window in a new activity that doesn't have a wallpaper is being opened on top of one that
98 * does, effectively closing the wallpaper. */
Craig Mautnerbb742462014-07-07 15:28:55 -070099 public static final int TRANSIT_WALLPAPER_CLOSE = 12;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800100 /** A window in a new activity that does have a wallpaper is being opened on one that didn't,
101 * effectively opening the wallpaper. */
Craig Mautnerbb742462014-07-07 15:28:55 -0700102 public static final int TRANSIT_WALLPAPER_OPEN = 13;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800103 /** A window in a new activity is being opened on top of an existing one, and both are on top
104 * of the wallpaper. */
Craig Mautnerbb742462014-07-07 15:28:55 -0700105 public static final int TRANSIT_WALLPAPER_INTRA_OPEN = 14;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800106 /** The window in the top-most activity is being closed to reveal the previous activity, and
107 * both are on top of the wallpaper. */
Craig Mautnerbb742462014-07-07 15:28:55 -0700108 public static final int TRANSIT_WALLPAPER_INTRA_CLOSE = 15;
109 /** A window in a new task is being opened behind an existing one in another activity's task.
110 * The new window will show briefly and then be gone. */
111 public static final int TRANSIT_TASK_OPEN_BEHIND = 16;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800112
Winson Chunga4ccb862014-08-22 15:26:27 -0700113 /** Fraction of animation at which the recents thumbnail stays completely transparent */
114 private static final float RECENTS_THUMBNAIL_FADEIN_FRACTION = 0.7f;
Craig Mautner321bdf52012-12-18 09:53:24 -0800115 /** Fraction of animation at which the recents thumbnail becomes completely transparent */
Winson Chunga4ccb862014-08-22 15:26:27 -0700116 private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.3f;
Craig Mautner321bdf52012-12-18 09:53:24 -0800117
Winson Chung5393dff2014-05-08 14:25:43 -0700118 private static final int DEFAULT_APP_TRANSITION_DURATION = 250;
Winson Chunga4ccb862014-08-22 15:26:27 -0700119 private static final int THUMBNAIL_APP_TRANSITION_DURATION = 300;
120 private static final int THUMBNAIL_APP_TRANSITION_ALPHA_DURATION = 325;
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;
Winson Chunga4ccb862014-08-22 15:26:27 -0700132 private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP = 5;
133 private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN = 6;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800134 private int mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
135
Winson Chung399f6202014-03-19 10:47:20 -0700136 // These are the possible states for the enter/exit activities during a thumbnail transition
137 private static final int THUMBNAIL_TRANSITION_ENTER_SCALE_UP = 0;
138 private static final int THUMBNAIL_TRANSITION_EXIT_SCALE_UP = 1;
139 private static final int THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN = 2;
140 private static final int THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN = 3;
141
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800142 private String mNextAppTransitionPackage;
143 private Bitmap mNextAppTransitionThumbnail;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800144 // Used for thumbnail transitions. True if we're scaling up, false if scaling down
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800145 private boolean mNextAppTransitionScaleUp;
146 private IRemoteCallback mNextAppTransitionCallback;
147 private int mNextAppTransitionEnter;
148 private int mNextAppTransitionExit;
149 private int mNextAppTransitionStartX;
150 private int mNextAppTransitionStartY;
151 private int mNextAppTransitionStartWidth;
152 private int mNextAppTransitionStartHeight;
Winson Chunga4ccb862014-08-22 15:26:27 -0700153 private Rect mNextAppTransitionInsets = new Rect();
Craig Mautner164d4bb2012-11-26 13:51:23 -0800154
Winson Chung2820c452014-04-15 15:34:44 -0700155 private Rect mTmpFromClipRect = new Rect();
156 private Rect mTmpToClipRect = new Rect();
157
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800158 private final static int APP_STATE_IDLE = 0;
159 private final static int APP_STATE_READY = 1;
160 private final static int APP_STATE_RUNNING = 2;
161 private final static int APP_STATE_TIMEOUT = 3;
162 private int mAppTransitionState = APP_STATE_IDLE;
163
164 private final int mConfigShortAnimTime;
Craig Mautner321bdf52012-12-18 09:53:24 -0800165 private final Interpolator mDecelerateInterpolator;
Winson Chunga4ccb862014-08-22 15:26:27 -0700166 private final Interpolator mThumbnailFadeInInterpolator;
167 private final Interpolator mThumbnailFadeOutInterpolator;
Winson Chung60a729c2014-08-12 16:33:32 -0700168 private final Interpolator mThumbnailFastOutSlowInInterpolator;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800169
Amith Yamasani4befbec2013-07-10 16:18:01 -0700170 private int mCurrentUserId = 0;
171
Craig Mautner164d4bb2012-11-26 13:51:23 -0800172 AppTransition(Context context, Handler h) {
173 mContext = context;
174 mH = h;
175 mConfigShortAnimTime = context.getResources().getInteger(
176 com.android.internal.R.integer.config_shortAnimTime);
Craig Mautner321bdf52012-12-18 09:53:24 -0800177 mDecelerateInterpolator = AnimationUtils.loadInterpolator(context,
178 com.android.internal.R.interpolator.decelerate_cubic);
Winson Chung60a729c2014-08-12 16:33:32 -0700179 mThumbnailFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
Winson Chung5393dff2014-05-08 14:25:43 -0700180 com.android.internal.R.interpolator.fast_out_slow_in);
Winson Chunga4ccb862014-08-22 15:26:27 -0700181 mThumbnailFadeInInterpolator = new Interpolator() {
182 @Override
183 public float getInterpolation(float input) {
184 // Linear response for first fraction, then complete after that.
185 if (input < RECENTS_THUMBNAIL_FADEIN_FRACTION) {
186 return 0f;
187 }
188 return (input - RECENTS_THUMBNAIL_FADEIN_FRACTION) /
189 (1f - RECENTS_THUMBNAIL_FADEIN_FRACTION);
190 }
191 };
192 mThumbnailFadeOutInterpolator = new Interpolator() {
Craig Mautner321bdf52012-12-18 09:53:24 -0800193 @Override
194 public float getInterpolation(float input) {
195 // Linear response for first fraction, then complete after that.
196 if (input < RECENTS_THUMBNAIL_FADEOUT_FRACTION) {
197 return input / RECENTS_THUMBNAIL_FADEOUT_FRACTION;
198 }
Winson Chunga4ccb862014-08-22 15:26:27 -0700199 return 1f;
Craig Mautner321bdf52012-12-18 09:53:24 -0800200 }
201 };
Craig Mautner164d4bb2012-11-26 13:51:23 -0800202 }
203
204 boolean isTransitionSet() {
205 return mNextAppTransition != TRANSIT_UNSET;
206 }
207
208 boolean isTransitionNone() {
209 return mNextAppTransition == TRANSIT_NONE;
210 }
211
212 boolean isTransitionEqual(int transit) {
213 return mNextAppTransition == transit;
214 }
215
216 int getAppTransition() {
Craig Mautner321bdf52012-12-18 09:53:24 -0800217 return mNextAppTransition;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800218 }
219
220 void setAppTransition(int transit) {
221 mNextAppTransition = transit;
222 }
223
224 boolean isReady() {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800225 return mAppTransitionState == APP_STATE_READY
226 || mAppTransitionState == APP_STATE_TIMEOUT;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800227 }
228
Craig Mautnerae446592012-12-06 19:05:05 -0800229 void setReady() {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800230 mAppTransitionState = APP_STATE_READY;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800231 }
232
233 boolean isRunning() {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800234 return mAppTransitionState == APP_STATE_RUNNING;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800235 }
236
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800237 void setIdle() {
238 mAppTransitionState = APP_STATE_IDLE;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800239 }
240
241 boolean isTimeout() {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800242 return mAppTransitionState == APP_STATE_TIMEOUT;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800243 }
244
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800245 void setTimeout() {
246 mAppTransitionState = APP_STATE_TIMEOUT;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800247 }
248
249 Bitmap getNextAppTransitionThumbnail() {
250 return mNextAppTransitionThumbnail;
251 }
252
Winson Chunga4ccb862014-08-22 15:26:27 -0700253 /** Returns whether the next thumbnail transition is aspect scaled up. */
254 boolean isNextThumbnailTransitionAspectScaled() {
255 return mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP ||
256 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
257 }
258
259 /** Returns whether the next thumbnail transition is scaling up. */
260 boolean isNextThumbnailTransitionScaleUp() {
261 return mNextAppTransitionScaleUp;
262 }
263
264 int getStartingX() {
265 return mNextAppTransitionStartX;
266 }
267
268 int getStartingY() {
269 return mNextAppTransitionStartY;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800270 }
271
Craig Mautner164d4bb2012-11-26 13:51:23 -0800272 void prepare() {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800273 if (!isRunning()) {
274 mAppTransitionState = APP_STATE_IDLE;
275 }
Craig Mautner164d4bb2012-11-26 13:51:23 -0800276 }
277
278 void goodToGo() {
Craig Mautner4b71aa12012-12-27 17:20:01 -0800279 mNextAppTransition = TRANSIT_UNSET;
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800280 mAppTransitionState = APP_STATE_RUNNING;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800281 }
282
283 void clear() {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800284 mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800285 mNextAppTransitionPackage = null;
286 mNextAppTransitionThumbnail = null;
287 }
288
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800289 void freeze() {
290 setAppTransition(AppTransition.TRANSIT_UNSET);
291 clear();
292 setReady();
293 }
294
Craig Mautner164d4bb2012-11-26 13:51:23 -0800295 private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
296 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: layout params pkg="
297 + (lp != null ? lp.packageName : null)
298 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null));
299 if (lp != null && lp.windowAnimations != 0) {
300 // If this is a system resource, don't try to load it from the
301 // application resources. It is nice to avoid loading application
302 // resources if we can.
303 String packageName = lp.packageName != null ? lp.packageName : "android";
304 int resId = lp.windowAnimations;
305 if ((resId&0xFF000000) == 0x01000000) {
306 packageName = "android";
307 }
308 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
309 + packageName);
310 return AttributeCache.instance().get(packageName, resId,
Amith Yamasani4befbec2013-07-10 16:18:01 -0700311 com.android.internal.R.styleable.WindowAnimation, mCurrentUserId);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800312 }
313 return null;
314 }
315
316 private AttributeCache.Entry getCachedAnimations(String packageName, int resId) {
317 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: package="
318 + packageName + " resId=0x" + Integer.toHexString(resId));
319 if (packageName != null) {
320 if ((resId&0xFF000000) == 0x01000000) {
321 packageName = "android";
322 }
323 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
324 + packageName);
325 return AttributeCache.instance().get(packageName, resId,
Amith Yamasani4befbec2013-07-10 16:18:01 -0700326 com.android.internal.R.styleable.WindowAnimation, mCurrentUserId);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800327 }
328 return null;
329 }
330
Dianne Hackborne30e02f2014-05-27 18:24:45 -0700331 Animation loadAnimationAttr(WindowManager.LayoutParams lp, int animAttr) {
Craig Mautner164d4bb2012-11-26 13:51:23 -0800332 int anim = 0;
333 Context context = mContext;
334 if (animAttr >= 0) {
335 AttributeCache.Entry ent = getCachedAnimations(lp);
336 if (ent != null) {
337 context = ent.context;
338 anim = ent.array.getResourceId(animAttr, 0);
339 }
340 }
341 if (anim != 0) {
342 return AnimationUtils.loadAnimation(context, anim);
343 }
344 return null;
345 }
346
Dianne Hackborne30e02f2014-05-27 18:24:45 -0700347 Animation loadAnimationRes(WindowManager.LayoutParams lp, int resId) {
348 Context context = mContext;
349 if (resId >= 0) {
350 AttributeCache.Entry ent = getCachedAnimations(lp);
351 if (ent != null) {
352 context = ent.context;
353 }
354 return AnimationUtils.loadAnimation(context, resId);
355 }
356 return null;
357 }
358
359 private Animation loadAnimationRes(String packageName, int resId) {
Craig Mautner164d4bb2012-11-26 13:51:23 -0800360 int anim = 0;
361 Context context = mContext;
362 if (resId >= 0) {
363 AttributeCache.Entry ent = getCachedAnimations(packageName, resId);
364 if (ent != null) {
365 context = ent.context;
366 anim = resId;
367 }
368 }
369 if (anim != 0) {
370 return AnimationUtils.loadAnimation(context, anim);
371 }
372 return null;
373 }
374
Craig Mautner164d4bb2012-11-26 13:51:23 -0800375 /**
376 * Compute the pivot point for an animation that is scaling from a small
377 * rect on screen to a larger rect. The pivot point varies depending on
378 * the distance between the inner and outer edges on both sides. This
379 * function computes the pivot point for one dimension.
380 * @param startPos Offset from left/top edge of outer rectangle to
381 * left/top edge of inner rectangle.
382 * @param finalScale The scaling factor between the size of the outer
383 * and inner rectangles.
384 */
385 private static float computePivot(int startPos, float finalScale) {
386 final float denom = finalScale-1;
387 if (Math.abs(denom) < .0001f) {
388 return startPos;
389 }
390 return -startPos / denom;
391 }
392
393 private Animation createScaleUpAnimationLocked(int transit, boolean enter,
394 int appWidth, int appHeight) {
395 Animation a = null;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800396 if (enter) {
397 // Entering app zooms out from the center of the initial rect.
398 float scaleW = mNextAppTransitionStartWidth / (float) appWidth;
399 float scaleH = mNextAppTransitionStartHeight / (float) appHeight;
400 Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
401 computePivot(mNextAppTransitionStartX, scaleW),
402 computePivot(mNextAppTransitionStartY, scaleH));
Craig Mautner321bdf52012-12-18 09:53:24 -0800403 scale.setInterpolator(mDecelerateInterpolator);
404
Craig Mautner164d4bb2012-11-26 13:51:23 -0800405 Animation alpha = new AlphaAnimation(0, 1);
Winson Chunga4ccb862014-08-22 15:26:27 -0700406 alpha.setInterpolator(mThumbnailFadeOutInterpolator);
Craig Mautner321bdf52012-12-18 09:53:24 -0800407
408 AnimationSet set = new AnimationSet(false);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800409 set.addAnimation(scale);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800410 set.addAnimation(alpha);
411 set.setDetachWallpaper(true);
412 a = set;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800413 } else if (transit == TRANSIT_WALLPAPER_INTRA_OPEN ||
414 transit == TRANSIT_WALLPAPER_INTRA_CLOSE) {
Craig Mautner321bdf52012-12-18 09:53:24 -0800415 // If we are on top of the wallpaper, we need an animation that
416 // correctly handles the wallpaper staying static behind all of
417 // the animated elements. To do this, will just have the existing
418 // element fade out.
419 a = new AlphaAnimation(1, 0);
420 a.setDetachWallpaper(true);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800421 } else {
Craig Mautner321bdf52012-12-18 09:53:24 -0800422 // For normal animations, the exiting element just holds in place.
423 a = new AlphaAnimation(1, 1);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800424 }
Craig Mautner321bdf52012-12-18 09:53:24 -0800425
426 // Pick the desired duration. If this is an inter-activity transition,
427 // it is the standard duration for that. Otherwise we use the longer
428 // task transition duration.
429 final long duration;
430 switch (transit) {
Craig Mautner4b71aa12012-12-27 17:20:01 -0800431 case TRANSIT_ACTIVITY_OPEN:
432 case TRANSIT_ACTIVITY_CLOSE:
Craig Mautner321bdf52012-12-18 09:53:24 -0800433 duration = mConfigShortAnimTime;
434 break;
435 default:
436 duration = DEFAULT_APP_TRANSITION_DURATION;
437 break;
438 }
439 a.setDuration(duration);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800440 a.setFillAfter(true);
Craig Mautner321bdf52012-12-18 09:53:24 -0800441 a.setInterpolator(mDecelerateInterpolator);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800442 a.initialize(appWidth, appHeight, appWidth, appHeight);
443 return a;
444 }
445
Winson Chung399f6202014-03-19 10:47:20 -0700446 /**
447 * Prepares the specified animation with a standard duration, interpolator, etc.
448 */
Winson Chung5393dff2014-05-08 14:25:43 -0700449 Animation prepareThumbnailAnimationWithDuration(Animation a, int appWidth, int appHeight,
450 int duration, Interpolator interpolator) {
Winson Chunga4ccb862014-08-22 15:26:27 -0700451 if (duration > 0) {
452 a.setDuration(duration);
453 }
Winson Chung5393dff2014-05-08 14:25:43 -0700454 a.setFillAfter(true);
455 a.setInterpolator(interpolator);
456 a.initialize(appWidth, appHeight, appWidth, appHeight);
457 return a;
458 }
459
460 /**
461 * Prepares the specified animation with a standard duration, interpolator, etc.
462 */
Winson Chung399f6202014-03-19 10:47:20 -0700463 Animation prepareThumbnailAnimation(Animation a, int appWidth, int appHeight, int transit) {
Craig Mautner321bdf52012-12-18 09:53:24 -0800464 // Pick the desired duration. If this is an inter-activity transition,
465 // it is the standard duration for that. Otherwise we use the longer
466 // task transition duration.
Winson Chung5393dff2014-05-08 14:25:43 -0700467 final int duration;
Craig Mautner321bdf52012-12-18 09:53:24 -0800468 switch (transit) {
Craig Mautner4b71aa12012-12-27 17:20:01 -0800469 case TRANSIT_ACTIVITY_OPEN:
470 case TRANSIT_ACTIVITY_CLOSE:
Craig Mautner321bdf52012-12-18 09:53:24 -0800471 duration = mConfigShortAnimTime;
472 break;
473 default:
474 duration = DEFAULT_APP_TRANSITION_DURATION;
475 break;
476 }
Winson Chung5393dff2014-05-08 14:25:43 -0700477 return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, duration,
478 mDecelerateInterpolator);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800479 }
480
Winson Chung399f6202014-03-19 10:47:20 -0700481 /**
482 * Return the current thumbnail transition state.
483 */
484 int getThumbnailTransitionState(boolean enter) {
485 if (enter) {
486 if (mNextAppTransitionScaleUp) {
487 return THUMBNAIL_TRANSITION_ENTER_SCALE_UP;
488 } else {
489 return THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN;
490 }
491 } else {
492 if (mNextAppTransitionScaleUp) {
493 return THUMBNAIL_TRANSITION_EXIT_SCALE_UP;
494 } else {
495 return THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN;
496 }
497 }
498 }
499
500 /**
501 * This animation runs for the thumbnail that gets cross faded with the enter/exit activity
502 * when a thumbnail is specified with the activity options.
503 */
Winson Chunga4ccb862014-08-22 15:26:27 -0700504 Animation createThumbnailAspectScaleAnimationLocked(int appWidth, int appHeight,
505 int deviceWidth, int transit) {
Winson Chung399f6202014-03-19 10:47:20 -0700506 Animation a;
507 final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
508 final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
509 final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
510 final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
511
Winson Chunga4ccb862014-08-22 15:26:27 -0700512 float scaleW = deviceWidth / thumbWidth;
513 float unscaledWidth = deviceWidth;
514 float unscaledHeight = thumbHeight * scaleW;
515 float unscaledStartY = mNextAppTransitionStartY - (unscaledHeight - thumbHeight) / 2f;
Winson Chung399f6202014-03-19 10:47:20 -0700516 if (mNextAppTransitionScaleUp) {
Winson Chunga4ccb862014-08-22 15:26:27 -0700517 // Animation up from the thumbnail to the full screen
518 Animation scale = new ScaleAnimation(1f, scaleW, 1f, scaleW,
519 mNextAppTransitionStartX + (thumbWidth / 2f),
520 mNextAppTransitionStartY + (thumbHeight / 2f));
521 scale.setInterpolator(mThumbnailFastOutSlowInInterpolator);
522 scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
Winson Chung399f6202014-03-19 10:47:20 -0700523 Animation alpha = new AlphaAnimation(1, 0);
Winson Chunga4ccb862014-08-22 15:26:27 -0700524 alpha.setInterpolator(mThumbnailFadeOutInterpolator);
525 alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION);
526 Animation translate = new TranslateAnimation(0, 0, 0, -unscaledStartY +
527 mNextAppTransitionInsets.top);
528 translate.setInterpolator(mThumbnailFastOutSlowInInterpolator);
529 translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
Winson Chung399f6202014-03-19 10:47:20 -0700530
531 // This AnimationSet uses the Interpolators assigned above.
532 AnimationSet set = new AnimationSet(false);
533 set.addAnimation(scale);
534 set.addAnimation(alpha);
Winson Chunga4ccb862014-08-22 15:26:27 -0700535 set.addAnimation(translate);
Winson Chung399f6202014-03-19 10:47:20 -0700536 a = set;
537 } else {
Winson Chunga4ccb862014-08-22 15:26:27 -0700538 // Animation down from the full screen to the thumbnail
539 Animation scale = new ScaleAnimation(scaleW, 1f, scaleW, 1f,
540 mNextAppTransitionStartX + (thumbWidth / 2f),
541 mNextAppTransitionStartY + (thumbHeight / 2f));
542 scale.setInterpolator(mThumbnailFastOutSlowInInterpolator);
543 scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
544 Animation alpha = new AlphaAnimation(0f, 1f);
545 alpha.setInterpolator(mThumbnailFadeInInterpolator);
546 alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION);
547 Animation translate = new TranslateAnimation(0, 0, -unscaledStartY +
548 mNextAppTransitionInsets.top, 0);
549 translate.setInterpolator(mThumbnailFastOutSlowInInterpolator);
550 translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
Winson Chung399f6202014-03-19 10:47:20 -0700551
Winson Chunga4ccb862014-08-22 15:26:27 -0700552 // This AnimationSet uses the Interpolators assigned above.
553 AnimationSet set = new AnimationSet(false);
554 set.addAnimation(scale);
555 set.addAnimation(alpha);
556 set.addAnimation(translate);
557 a = set;
558
559 }
560 return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, 0,
561 mThumbnailFastOutSlowInInterpolator);
Winson Chung399f6202014-03-19 10:47:20 -0700562 }
563
564 /**
565 * This alternate animation is created when we are doing a thumbnail transition, for the
566 * activity that is leaving, and the activity that is entering.
567 */
Winson Chunga4ccb862014-08-22 15:26:27 -0700568 Animation createAspectScaledThumbnailEnterExitAnimationLocked(int thumbTransitState,
569 int appWidth, int appHeight, int orientation, int transit, Rect containingFrame,
570 Rect contentInsets, boolean isFullScreen) {
Winson Chung399f6202014-03-19 10:47:20 -0700571 Animation a;
572 final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
573 final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
574 final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
575 final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
576
Winson Chung2820c452014-04-15 15:34:44 -0700577 // Used for the ENTER_SCALE_UP and EXIT_SCALE_DOWN transitions
578 float scale = 1f;
579 int scaledTopDecor = 0;
580
Winson Chung399f6202014-03-19 10:47:20 -0700581 switch (thumbTransitState) {
582 case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: {
Winson Chunga4ccb862014-08-22 15:26:27 -0700583 // App window scaling up to become full screen
Winson Chung2820c452014-04-15 15:34:44 -0700584 if (orientation == Configuration.ORIENTATION_PORTRAIT) {
585 // In portrait, we scale the width and clip to the top/left square
586 scale = thumbWidth / appWidth;
587 scaledTopDecor = (int) (scale * contentInsets.top);
588 int unscaledThumbHeight = (int) (thumbHeight / scale);
589 mTmpFromClipRect.set(containingFrame);
Winson Chungae084412014-05-20 14:17:22 -0700590 if (isFullScreen) {
591 mTmpFromClipRect.top = contentInsets.top;
592 }
Winson Chung2820c452014-04-15 15:34:44 -0700593 mTmpFromClipRect.bottom = (mTmpFromClipRect.top + unscaledThumbHeight);
594 mTmpToClipRect.set(containingFrame);
595 } else {
596 // In landscape, we scale the height and clip to the top/left square
597 scale = thumbHeight / (appHeight - contentInsets.top);
598 scaledTopDecor = (int) (scale * contentInsets.top);
599 int unscaledThumbWidth = (int) (thumbWidth / scale);
Winson Chungae084412014-05-20 14:17:22 -0700600 int unscaledThumbHeight = (int) (thumbHeight / scale);
Winson Chung2820c452014-04-15 15:34:44 -0700601 mTmpFromClipRect.set(containingFrame);
Winson Chungae084412014-05-20 14:17:22 -0700602 if (isFullScreen) {
603 mTmpFromClipRect.top = contentInsets.top;
604 mTmpFromClipRect.bottom = (mTmpFromClipRect.top + unscaledThumbHeight);
605 }
Winson Chung2820c452014-04-15 15:34:44 -0700606 mTmpFromClipRect.right = (mTmpFromClipRect.left + unscaledThumbWidth);
607 mTmpToClipRect.set(containingFrame);
608 }
Winson Chunga4ccb862014-08-22 15:26:27 -0700609 mNextAppTransitionInsets.set(contentInsets);
Winson Chung399f6202014-03-19 10:47:20 -0700610
611 Animation scaleAnim = new ScaleAnimation(scale, 1, scale, 1,
612 computePivot(mNextAppTransitionStartX, scale),
613 computePivot(mNextAppTransitionStartY, scale));
Winson Chung2820c452014-04-15 15:34:44 -0700614 Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
Winson Chung399f6202014-03-19 10:47:20 -0700615 Animation translateAnim = new TranslateAnimation(0, 0, -scaledTopDecor, 0);
616
617 AnimationSet set = new AnimationSet(true);
Winson Chung399f6202014-03-19 10:47:20 -0700618 set.addAnimation(clipAnim);
619 set.addAnimation(scaleAnim);
620 set.addAnimation(translateAnim);
621 a = set;
622 break;
623 }
624 case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: {
Winson Chunga4ccb862014-08-22 15:26:27 -0700625 // Previous app window during the scale up
Winson Chung399f6202014-03-19 10:47:20 -0700626 if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) {
Winson Chunga4ccb862014-08-22 15:26:27 -0700627 // Fade out the source activity if we are animating to a wallpaper
Winson Chung399f6202014-03-19 10:47:20 -0700628 // activity.
629 a = new AlphaAnimation(1, 0);
630 } else {
Winson Chung399f6202014-03-19 10:47:20 -0700631 a = new AlphaAnimation(1, 1);
632 }
633 break;
634 }
635 case THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN: {
Winson Chunga4ccb862014-08-22 15:26:27 -0700636 // Target app window during the scale down
637 if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) {
638 // Fade in the destination activity if we are animating from a wallpaper
639 // activity.
640 a = new AlphaAnimation(0, 1);
641 } else {
642 a = new AlphaAnimation(1, 1);
643 }
Winson Chung399f6202014-03-19 10:47:20 -0700644 break;
645 }
646 case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: {
Winson Chunga4ccb862014-08-22 15:26:27 -0700647 // App window scaling down from full screen
Winson Chung2820c452014-04-15 15:34:44 -0700648 if (orientation == Configuration.ORIENTATION_PORTRAIT) {
649 // In portrait, we scale the width and clip to the top/left square
650 scale = thumbWidth / appWidth;
651 scaledTopDecor = (int) (scale * contentInsets.top);
652 int unscaledThumbHeight = (int) (thumbHeight / scale);
653 mTmpFromClipRect.set(containingFrame);
654 mTmpToClipRect.set(containingFrame);
Winson Chungae084412014-05-20 14:17:22 -0700655 if (isFullScreen) {
656 mTmpToClipRect.top = contentInsets.top;
657 }
Winson Chung2820c452014-04-15 15:34:44 -0700658 mTmpToClipRect.bottom = (mTmpToClipRect.top + unscaledThumbHeight);
659 } else {
660 // In landscape, we scale the height and clip to the top/left square
661 scale = thumbHeight / (appHeight - contentInsets.top);
662 scaledTopDecor = (int) (scale * contentInsets.top);
663 int unscaledThumbWidth = (int) (thumbWidth / scale);
Winson Chungae084412014-05-20 14:17:22 -0700664 int unscaledThumbHeight = (int) (thumbHeight / scale);
Winson Chung2820c452014-04-15 15:34:44 -0700665 mTmpFromClipRect.set(containingFrame);
666 mTmpToClipRect.set(containingFrame);
Winson Chungae084412014-05-20 14:17:22 -0700667 if (isFullScreen) {
668 mTmpToClipRect.top = contentInsets.top;
669 mTmpToClipRect.bottom = (mTmpToClipRect.top + unscaledThumbHeight);
670 }
Winson Chung2820c452014-04-15 15:34:44 -0700671 mTmpToClipRect.right = (mTmpToClipRect.left + unscaledThumbWidth);
672 }
Winson Chunga4ccb862014-08-22 15:26:27 -0700673 mNextAppTransitionInsets.set(contentInsets);
Winson Chung399f6202014-03-19 10:47:20 -0700674
675 Animation scaleAnim = new ScaleAnimation(1, scale, 1, scale,
676 computePivot(mNextAppTransitionStartX, scale),
677 computePivot(mNextAppTransitionStartY, scale));
Winson Chung2820c452014-04-15 15:34:44 -0700678 Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
Winson Chung399f6202014-03-19 10:47:20 -0700679 Animation translateAnim = new TranslateAnimation(0, 0, 0, -scaledTopDecor);
680
681 AnimationSet set = new AnimationSet(true);
Winson Chung399f6202014-03-19 10:47:20 -0700682 set.addAnimation(clipAnim);
683 set.addAnimation(scaleAnim);
684 set.addAnimation(translateAnim);
685
686 a = set;
687 a.setZAdjustment(Animation.ZORDER_TOP);
688 break;
689 }
690 default:
691 throw new RuntimeException("Invalid thumbnail transition state");
692 }
693
Winson Chung5393dff2014-05-08 14:25:43 -0700694 return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight,
Winson Chung60a729c2014-08-12 16:33:32 -0700695 THUMBNAIL_APP_TRANSITION_DURATION, mThumbnailFastOutSlowInInterpolator);
Winson Chung399f6202014-03-19 10:47:20 -0700696 }
697
698 /**
Winson Chunga4ccb862014-08-22 15:26:27 -0700699 * This animation runs for the thumbnail that gets cross faded with the enter/exit activity
700 * when a thumbnail is specified with the activity options.
701 */
702 Animation createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit) {
703 Animation a;
704 final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
705 final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
706 final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
707 final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
708
709 if (mNextAppTransitionScaleUp) {
710 // Animation for the thumbnail zooming from its initial size to the full screen
711 float scaleW = appWidth / thumbWidth;
712 float scaleH = appHeight / thumbHeight;
713 Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
714 computePivot(mNextAppTransitionStartX, 1 / scaleW),
715 computePivot(mNextAppTransitionStartY, 1 / scaleH));
716 scale.setInterpolator(mDecelerateInterpolator);
717
718 Animation alpha = new AlphaAnimation(1, 0);
719 alpha.setInterpolator(mThumbnailFadeOutInterpolator);
720
721 // This AnimationSet uses the Interpolators assigned above.
722 AnimationSet set = new AnimationSet(false);
723 set.addAnimation(scale);
724 set.addAnimation(alpha);
725 a = set;
726 } else {
727 // Animation for the thumbnail zooming down from the full screen to its final size
728 float scaleW = appWidth / thumbWidth;
729 float scaleH = appHeight / thumbHeight;
730 a = new ScaleAnimation(scaleW, 1, scaleH, 1,
731 computePivot(mNextAppTransitionStartX, 1 / scaleW),
732 computePivot(mNextAppTransitionStartY, 1 / scaleH));
733 }
734
735 return prepareThumbnailAnimation(a, appWidth, appHeight, transit);
736 }
737
738 /**
Winson Chung399f6202014-03-19 10:47:20 -0700739 * This animation is created when we are doing a thumbnail transition, for the activity that is
740 * leaving, and the activity that is entering.
741 */
742 Animation createThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth,
743 int appHeight, int transit) {
744 Animation a;
745 final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
746 final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
747 final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
748 final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
749
750 switch (thumbTransitState) {
751 case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: {
752 // Entering app scales up with the thumbnail
753 float scaleW = thumbWidth / appWidth;
754 float scaleH = thumbHeight / appHeight;
755 a = new ScaleAnimation(scaleW, 1, scaleH, 1,
756 computePivot(mNextAppTransitionStartX, scaleW),
757 computePivot(mNextAppTransitionStartY, scaleH));
758 break;
759 }
760 case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: {
761 // Exiting app while the thumbnail is scaling up should fade or stay in place
762 if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) {
763 // Fade out while bringing up selected activity. This keeps the
764 // current activity from showing through a launching wallpaper
765 // activity.
766 a = new AlphaAnimation(1, 0);
767 } else {
768 // noop animation
769 a = new AlphaAnimation(1, 1);
770 }
771 break;
772 }
773 case THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN: {
774 // Entering the other app, it should just be visible while we scale the thumbnail
775 // down above it
776 a = new AlphaAnimation(1, 1);
777 break;
778 }
779 case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: {
780 // Exiting the current app, the app should scale down with the thumbnail
781 float scaleW = thumbWidth / appWidth;
782 float scaleH = thumbHeight / appHeight;
783 Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
784 computePivot(mNextAppTransitionStartX, scaleW),
785 computePivot(mNextAppTransitionStartY, scaleH));
786
787 Animation alpha = new AlphaAnimation(1, 0);
788
789 AnimationSet set = new AnimationSet(true);
790 set.addAnimation(scale);
791 set.addAnimation(alpha);
792 set.setZAdjustment(Animation.ZORDER_TOP);
793 a = set;
794 break;
795 }
796 default:
797 throw new RuntimeException("Invalid thumbnail transition state");
798 }
799
800 return prepareThumbnailAnimation(a, appWidth, appHeight, transit);
801 }
802
Craig Mautner164d4bb2012-11-26 13:51:23 -0800803
804 Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
Dianne Hackborne30e02f2014-05-27 18:24:45 -0700805 int appWidth, int appHeight, int orientation, Rect containingFrame, Rect contentInsets,
806 boolean isFullScreen, boolean isVoiceInteraction) {
Craig Mautner164d4bb2012-11-26 13:51:23 -0800807 Animation a;
Dianne Hackborne30e02f2014-05-27 18:24:45 -0700808 if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_OPEN
809 || transit == TRANSIT_TASK_OPEN
810 || transit == TRANSIT_TASK_TO_FRONT)) {
811 a = loadAnimationRes(lp, enter
812 ? com.android.internal.R.anim.voice_activity_open_enter
813 : com.android.internal.R.anim.voice_activity_open_exit);
814 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
815 "applyAnimation voice:"
816 + " anim=" + a + " transit=" + transit + " isEntrance=" + enter
817 + " Callers=" + Debug.getCallers(3));
818 } else if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_CLOSE
819 || transit == TRANSIT_TASK_CLOSE
820 || transit == TRANSIT_TASK_TO_BACK)) {
821 a = loadAnimationRes(lp, enter
822 ? com.android.internal.R.anim.voice_activity_close_enter
823 : com.android.internal.R.anim.voice_activity_close_exit);
824 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
825 "applyAnimation voice:"
826 + " anim=" + a + " transit=" + transit + " isEntrance=" + enter
827 + " Callers=" + Debug.getCallers(3));
828 } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {
829 a = loadAnimationRes(mNextAppTransitionPackage, enter ?
Craig Mautner164d4bb2012-11-26 13:51:23 -0800830 mNextAppTransitionEnter : mNextAppTransitionExit);
831 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
832 "applyAnimation:"
833 + " anim=" + a + " nextAppTransition=ANIM_CUSTOM"
834 + " transit=" + transit + " isEntrance=" + enter
835 + " Callers=" + Debug.getCallers(3));
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800836 } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_SCALE_UP) {
Craig Mautner164d4bb2012-11-26 13:51:23 -0800837 a = createScaleUpAnimationLocked(transit, enter, appWidth, appHeight);
838 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
839 "applyAnimation:"
840 + " anim=" + a + " nextAppTransition=ANIM_SCALE_UP"
841 + " transit=" + transit + " isEntrance=" + enter
842 + " Callers=" + Debug.getCallers(3));
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800843 } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP ||
844 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) {
Craig Mautner164d4bb2012-11-26 13:51:23 -0800845 mNextAppTransitionScaleUp =
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800846 (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
Winson Chunga4ccb862014-08-22 15:26:27 -0700847 a = createThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter),
848 appWidth, appHeight, transit);
849 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
850 String animName = mNextAppTransitionScaleUp ?
851 "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
852 Slog.v(TAG, "applyAnimation:"
853 + " anim=" + a + " nextAppTransition=" + animName
854 + " transit=" + transit + " isEntrance=" + enter
855 + " Callers=" + Debug.getCallers(3));
856 }
857 } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP ||
858 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN) {
859 mNextAppTransitionScaleUp =
860 (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP);
861 a = createAspectScaledThumbnailEnterExitAnimationLocked(
Winson Chungfd086222014-05-13 15:49:42 -0700862 getThumbnailTransitionState(enter), appWidth, appHeight, orientation,
Winson Chungae084412014-05-20 14:17:22 -0700863 transit, containingFrame, contentInsets, isFullScreen);
Craig Mautner164d4bb2012-11-26 13:51:23 -0800864 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
865 String animName = mNextAppTransitionScaleUp ?
Winson Chunga4ccb862014-08-22 15:26:27 -0700866 "ANIM_THUMBNAIL_ASPECT_SCALE_UP" : "ANIM_THUMBNAIL_ASPECT_SCALE_DOWN";
Craig Mautner164d4bb2012-11-26 13:51:23 -0800867 Slog.v(TAG, "applyAnimation:"
868 + " anim=" + a + " nextAppTransition=" + animName
869 + " transit=" + transit + " isEntrance=" + enter
870 + " Callers=" + Debug.getCallers(3));
871 }
872 } else {
873 int animAttr = 0;
874 switch (transit) {
Craig Mautner4b71aa12012-12-27 17:20:01 -0800875 case TRANSIT_ACTIVITY_OPEN:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800876 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800877 ? WindowAnimation_activityOpenEnterAnimation
878 : WindowAnimation_activityOpenExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800879 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800880 case TRANSIT_ACTIVITY_CLOSE:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800881 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800882 ? WindowAnimation_activityCloseEnterAnimation
883 : WindowAnimation_activityCloseExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800884 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800885 case TRANSIT_TASK_OPEN:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800886 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800887 ? WindowAnimation_taskOpenEnterAnimation
888 : WindowAnimation_taskOpenExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800889 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800890 case TRANSIT_TASK_CLOSE:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800891 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800892 ? WindowAnimation_taskCloseEnterAnimation
893 : WindowAnimation_taskCloseExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800894 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800895 case TRANSIT_TASK_TO_FRONT:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800896 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800897 ? WindowAnimation_taskToFrontEnterAnimation
898 : WindowAnimation_taskToFrontExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800899 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800900 case TRANSIT_TASK_TO_BACK:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800901 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800902 ? WindowAnimation_taskToBackEnterAnimation
903 : WindowAnimation_taskToBackExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800904 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800905 case TRANSIT_WALLPAPER_OPEN:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800906 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800907 ? WindowAnimation_wallpaperOpenEnterAnimation
908 : WindowAnimation_wallpaperOpenExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800909 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800910 case TRANSIT_WALLPAPER_CLOSE:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800911 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800912 ? WindowAnimation_wallpaperCloseEnterAnimation
913 : WindowAnimation_wallpaperCloseExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800914 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800915 case TRANSIT_WALLPAPER_INTRA_OPEN:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800916 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800917 ? WindowAnimation_wallpaperIntraOpenEnterAnimation
918 : WindowAnimation_wallpaperIntraOpenExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800919 break;
Craig Mautner4b71aa12012-12-27 17:20:01 -0800920 case TRANSIT_WALLPAPER_INTRA_CLOSE:
Craig Mautner164d4bb2012-11-26 13:51:23 -0800921 animAttr = enter
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800922 ? WindowAnimation_wallpaperIntraCloseEnterAnimation
923 : WindowAnimation_wallpaperIntraCloseExitAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800924 break;
Craig Mautnerbb742462014-07-07 15:28:55 -0700925 case TRANSIT_TASK_OPEN_BEHIND:
926 animAttr = enter
927 ? WindowAnimation_launchTaskBehindSourceAnimation
928 : WindowAnimation_launchTaskBehindBackgroundAnimation;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800929 }
Dianne Hackborne30e02f2014-05-27 18:24:45 -0700930 a = animAttr != 0 ? loadAnimationAttr(lp, animAttr) : null;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800931 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
932 "applyAnimation:"
933 + " anim=" + a
934 + " animAttr=0x" + Integer.toHexString(animAttr)
935 + " transit=" + transit + " isEntrance=" + enter
936 + " Callers=" + Debug.getCallers(3));
937 }
938 return a;
939 }
940
941 void postAnimationCallback() {
942 if (mNextAppTransitionCallback != null) {
943 mH.sendMessage(mH.obtainMessage(H.DO_ANIMATION_CALLBACK, mNextAppTransitionCallback));
944 mNextAppTransitionCallback = null;
945 }
946 }
947
948 void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim,
949 IRemoteCallback startedCallback) {
950 if (isTransitionSet()) {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800951 mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800952 mNextAppTransitionPackage = packageName;
953 mNextAppTransitionThumbnail = null;
954 mNextAppTransitionEnter = enterAnim;
955 mNextAppTransitionExit = exitAnim;
956 postAnimationCallback();
957 mNextAppTransitionCallback = startedCallback;
958 } else {
959 postAnimationCallback();
960 }
961 }
962
963 void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
964 int startHeight) {
965 if (isTransitionSet()) {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800966 mNextAppTransitionType = NEXT_TRANSIT_TYPE_SCALE_UP;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800967 mNextAppTransitionPackage = null;
968 mNextAppTransitionThumbnail = null;
969 mNextAppTransitionStartX = startX;
970 mNextAppTransitionStartY = startY;
971 mNextAppTransitionStartWidth = startWidth;
972 mNextAppTransitionStartHeight = startHeight;
973 postAnimationCallback();
974 mNextAppTransitionCallback = null;
975 }
976 }
977
978 void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY,
979 IRemoteCallback startedCallback, boolean scaleUp) {
980 if (isTransitionSet()) {
Craig Mautner9a29a5d2012-12-27 19:03:40 -0800981 mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP
982 : NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN;
Craig Mautner164d4bb2012-11-26 13:51:23 -0800983 mNextAppTransitionPackage = null;
984 mNextAppTransitionThumbnail = srcThumb;
985 mNextAppTransitionScaleUp = scaleUp;
986 mNextAppTransitionStartX = startX;
987 mNextAppTransitionStartY = startY;
988 postAnimationCallback();
989 mNextAppTransitionCallback = startedCallback;
990 } else {
991 postAnimationCallback();
992 }
993 }
994
Winson Chunga4ccb862014-08-22 15:26:27 -0700995 void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX, int startY,
996 IRemoteCallback startedCallback, boolean scaleUp) {
997 if (isTransitionSet()) {
998 mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
999 : NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
1000 mNextAppTransitionPackage = null;
1001 mNextAppTransitionThumbnail = srcThumb;
1002 mNextAppTransitionScaleUp = scaleUp;
1003 mNextAppTransitionStartX = startX;
1004 mNextAppTransitionStartY = startY;
1005 postAnimationCallback();
1006 mNextAppTransitionCallback = startedCallback;
1007 } else {
1008 postAnimationCallback();
1009 }
1010 }
1011
Craig Mautner164d4bb2012-11-26 13:51:23 -08001012 @Override
1013 public String toString() {
1014 return "mNextAppTransition=0x" + Integer.toHexString(mNextAppTransition);
1015 }
1016
Craig Mautner4b71aa12012-12-27 17:20:01 -08001017 /**
1018 * Returns the human readable name of a window transition.
1019 *
1020 * @param transition The window transition.
1021 * @return The transition symbolic name.
1022 */
1023 public static String appTransitionToString(int transition) {
1024 switch (transition) {
1025 case TRANSIT_UNSET: {
1026 return "TRANSIT_UNSET";
1027 }
1028 case TRANSIT_NONE: {
1029 return "TRANSIT_NONE";
1030 }
Craig Mautner4b71aa12012-12-27 17:20:01 -08001031 case TRANSIT_ACTIVITY_OPEN: {
1032 return "TRANSIT_ACTIVITY_OPEN";
1033 }
1034 case TRANSIT_ACTIVITY_CLOSE: {
1035 return "TRANSIT_ACTIVITY_CLOSE";
1036 }
1037 case TRANSIT_TASK_OPEN: {
1038 return "TRANSIT_TASK_OPEN";
1039 }
1040 case TRANSIT_TASK_CLOSE: {
1041 return "TRANSIT_TASK_CLOSE";
1042 }
1043 case TRANSIT_TASK_TO_FRONT: {
1044 return "TRANSIT_TASK_TO_FRONT";
1045 }
1046 case TRANSIT_TASK_TO_BACK: {
1047 return "TRANSIT_TASK_TO_BACK";
1048 }
1049 case TRANSIT_WALLPAPER_CLOSE: {
1050 return "TRANSIT_WALLPAPER_CLOSE";
1051 }
1052 case TRANSIT_WALLPAPER_OPEN: {
1053 return "TRANSIT_WALLPAPER_OPEN";
1054 }
1055 case TRANSIT_WALLPAPER_INTRA_OPEN: {
1056 return "TRANSIT_WALLPAPER_INTRA_OPEN";
1057 }
1058 case TRANSIT_WALLPAPER_INTRA_CLOSE: {
1059 return "TRANSIT_WALLPAPER_INTRA_CLOSE";
1060 }
Craig Mautnerbb742462014-07-07 15:28:55 -07001061 case TRANSIT_TASK_OPEN_BEHIND: {
1062 return "TRANSIT_TASK_OPEN_BEHIND";
1063 }
Craig Mautner4b71aa12012-12-27 17:20:01 -08001064 default: {
1065 return "<UNKNOWN>";
1066 }
1067 }
1068 }
1069
Craig Mautner9a29a5d2012-12-27 19:03:40 -08001070 private String appStateToString() {
1071 switch (mAppTransitionState) {
1072 case APP_STATE_IDLE:
1073 return "APP_STATE_IDLE";
1074 case APP_STATE_READY:
1075 return "APP_STATE_READY";
1076 case APP_STATE_RUNNING:
1077 return "APP_STATE_RUNNING";
1078 case APP_STATE_TIMEOUT:
1079 return "APP_STATE_TIMEOUT";
1080 default:
1081 return "unknown state=" + mAppTransitionState;
1082 }
1083 }
1084
1085 private String transitTypeToString() {
1086 switch (mNextAppTransitionType) {
1087 case NEXT_TRANSIT_TYPE_NONE:
1088 return "NEXT_TRANSIT_TYPE_NONE";
1089 case NEXT_TRANSIT_TYPE_CUSTOM:
1090 return "NEXT_TRANSIT_TYPE_CUSTOM";
1091 case NEXT_TRANSIT_TYPE_SCALE_UP:
1092 return "NEXT_TRANSIT_TYPE_SCALE_UP";
1093 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP:
1094 return "NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP";
1095 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN:
1096 return "NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN";
Winson Chunga4ccb862014-08-22 15:26:27 -07001097 case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP:
1098 return "NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP";
1099 case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN:
1100 return "NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN";
Craig Mautner9a29a5d2012-12-27 19:03:40 -08001101 default:
1102 return "unknown type=" + mNextAppTransitionType;
1103 }
1104 }
1105
Craig Mautner164d4bb2012-11-26 13:51:23 -08001106 @Override
1107 public void dump(PrintWriter pw) {
1108 pw.print(" " + this);
Craig Mautner28816302013-10-10 20:31:00 -07001109 pw.print(" mAppTransitionState="); pw.println(appStateToString());
Craig Mautner9a29a5d2012-12-27 19:03:40 -08001110 if (mNextAppTransitionType != NEXT_TRANSIT_TYPE_NONE) {
1111 pw.print(" mNextAppTransitionType="); pw.println(transitTypeToString());
Craig Mautner164d4bb2012-11-26 13:51:23 -08001112 }
1113 switch (mNextAppTransitionType) {
Craig Mautner9a29a5d2012-12-27 19:03:40 -08001114 case NEXT_TRANSIT_TYPE_CUSTOM:
Craig Mautner164d4bb2012-11-26 13:51:23 -08001115 pw.print(" mNextAppTransitionPackage=");
1116 pw.println(mNextAppTransitionPackage);
1117 pw.print(" mNextAppTransitionEnter=0x");
1118 pw.print(Integer.toHexString(mNextAppTransitionEnter));
1119 pw.print(" mNextAppTransitionExit=0x");
1120 pw.println(Integer.toHexString(mNextAppTransitionExit));
1121 break;
Craig Mautner9a29a5d2012-12-27 19:03:40 -08001122 case NEXT_TRANSIT_TYPE_SCALE_UP:
Craig Mautner164d4bb2012-11-26 13:51:23 -08001123 pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX);
1124 pw.print(" mNextAppTransitionStartY=");
1125 pw.println(mNextAppTransitionStartY);
1126 pw.print(" mNextAppTransitionStartWidth=");
1127 pw.print(mNextAppTransitionStartWidth);
1128 pw.print(" mNextAppTransitionStartHeight=");
1129 pw.println(mNextAppTransitionStartHeight);
1130 break;
Craig Mautner9a29a5d2012-12-27 19:03:40 -08001131 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP:
1132 case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN:
Winson Chunga4ccb862014-08-22 15:26:27 -07001133 case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP:
1134 case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN:
Craig Mautner164d4bb2012-11-26 13:51:23 -08001135 pw.print(" mNextAppTransitionThumbnail=");
1136 pw.print(mNextAppTransitionThumbnail);
1137 pw.print(" mNextAppTransitionStartX=");
1138 pw.print(mNextAppTransitionStartX);
1139 pw.print(" mNextAppTransitionStartY=");
1140 pw.println(mNextAppTransitionStartY);
1141 pw.print(" mNextAppTransitionScaleUp="); pw.println(mNextAppTransitionScaleUp);
1142 break;
1143 }
1144 if (mNextAppTransitionCallback != null) {
1145 pw.print(" mNextAppTransitionCallback=");
1146 pw.println(mNextAppTransitionCallback);
1147 }
1148 }
Amith Yamasani4befbec2013-07-10 16:18:01 -07001149
1150 public void setCurrentUser(int newUserId) {
1151 mCurrentUserId = newUserId;
1152 }
Craig Mautner164d4bb2012-11-26 13:51:23 -08001153}