blob: d2479604e92bdf6b57d28337dd7b260bf74e4b29 [file] [log] [blame]
Robert Carre625fcf2017-09-01 12:36:28 -07001/*
2 * Copyright (C) 2017 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 */
Wale Ogunwalee05f5012016-09-16 16:27:29 -070016
Filip Gruszczynski4501d232015-09-02 13:00:02 -070017package com.android.server.wm;
18
Jorim Jaggi3878ca32017-02-02 17:13:05 -080019import static android.app.ActivityManagerInternal.APP_TRANSITION_SNAPSHOT;
20import static android.app.ActivityManagerInternal.APP_TRANSITION_SPLASH_SCREEN;
Jorim Jaggi275561a2016-02-23 10:11:02 -050021import static android.app.ActivityManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
Tony Mak64b8d562017-12-28 17:44:02 +000022
Adrian Roos93577212018-04-10 14:12:10 -070023import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
Winson Chungc1674272018-02-21 10:15:17 -080024import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
Jorim Jaggi98a9d202018-03-26 16:17:07 +020025import static android.view.WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE;
26import static android.view.WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_OPEN;
Adrian Roose99bc052017-11-20 17:55:31 +010027import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
28import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
Jorim Jaggif84e2f62018-01-16 14:17:59 +010029import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
30import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
31import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
32import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
33import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
34import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
35import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
36import static android.view.WindowManager.TRANSIT_NONE;
37import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
38import static android.view.WindowManager.TRANSIT_TASK_IN_PLACE;
39import static android.view.WindowManager.TRANSIT_TASK_OPEN;
40import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
41import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
42import static android.view.WindowManager.TRANSIT_WALLPAPER_CLOSE;
43import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_CLOSE;
44import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_OPEN;
45import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
Jorim Jaggia69243a2017-06-15 15:10:38 -040046import static com.android.server.wm.AppTransition.isKeyguardGoingAwayTransit;
Jorim Jaggi98a9d202018-03-26 16:17:07 +020047import static com.android.server.wm.AppTransition.isTaskTransit;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080048import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080049import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080050import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
Jorim Jaggi192086e2016-03-11 17:17:03 +010051import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080052import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Jorim Jaggi192086e2016-03-11 17:17:03 +010053import static com.android.server.wm.WindowManagerService.H.NOTIFY_APP_TRANSITION_STARTING;
Jorim Jaggi192086e2016-03-11 17:17:03 +010054import static com.android.server.wm.WindowManagerService.H.REPORT_WINDOWS_CHANGE;
Jorim Jaggi192086e2016-03-11 17:17:03 +010055import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
Filip Gruszczynski4501d232015-09-02 13:00:02 -070056import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
Filip Gruszczynski4501d232015-09-02 13:00:02 -070057
Jorim Jaggi77be1572018-03-09 16:48:24 +010058import android.app.WindowConfiguration;
Filip Gruszczynski4501d232015-09-02 13:00:02 -070059import android.os.Debug;
Filip Gruszczynski4501d232015-09-02 13:00:02 -070060import android.os.Trace;
Filip Gruszczynski49b80af2015-09-24 09:04:26 -070061import android.util.ArraySet;
Filip Gruszczynski4501d232015-09-02 13:00:02 -070062import android.util.Slog;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080063import android.util.SparseIntArray;
Filip Gruszczynski4501d232015-09-02 13:00:02 -070064import android.view.Display;
Jorim Jaggif84e2f62018-01-16 14:17:59 +010065import android.view.RemoteAnimationAdapter;
66import android.view.RemoteAnimationDefinition;
Jorim Jaggif84e2f62018-01-16 14:17:59 +010067import android.view.WindowManager;
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -080068import android.view.WindowManager.LayoutParams;
Jorim Jaggif84e2f62018-01-16 14:17:59 +010069import android.view.WindowManager.TransitionType;
Filip Gruszczynski4501d232015-09-02 13:00:02 -070070import android.view.animation.Animation;
Filip Gruszczynski4501d232015-09-02 13:00:02 -070071
Jorim Jaggi98a9d202018-03-26 16:17:07 +020072import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggid75962e2016-05-03 15:10:03 -070073import com.android.server.wm.WindowManagerService.H;
74
Filip Gruszczynski24966d42015-09-05 15:00:00 -070075import java.io.PrintWriter;
Jorim Jaggif84e2f62018-01-16 14:17:59 +010076import java.util.function.Predicate;
Filip Gruszczynski4501d232015-09-02 13:00:02 -070077
78/**
79 * Positions windows and their surfaces.
80 *
81 * It sets positions of windows by calculating their frames and then applies this by positioning
82 * surfaces according to these frames. Z layer is still assigned withing WindowManagerService.
83 */
84class WindowSurfacePlacer {
Filip Gruszczynskice4ec402016-01-22 11:22:47 -080085 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowSurfacePlacer" : TAG_WM;
Filip Gruszczynski4501d232015-09-02 13:00:02 -070086 private final WindowManagerService mService;
87 private final WallpaperController mWallpaperControllerLocked;
88
89 private boolean mInLayout = false;
90
91 /** Only do a maximum of 6 repeated layouts. After that quit */
92 private int mLayoutRepeatCount;
93
94 static final int SET_UPDATE_ROTATION = 1 << 0;
95 static final int SET_WALLPAPER_MAY_CHANGE = 1 << 1;
96 static final int SET_FORCE_HIDING_CHANGED = 1 << 2;
97 static final int SET_ORIENTATION_CHANGE_COMPLETE = 1 << 3;
chaviw042059d2018-01-11 11:24:08 -080098 static final int SET_WALLPAPER_ACTION_PENDING = 1 << 4;
Filip Gruszczynski4501d232015-09-02 13:00:02 -070099
Filip Gruszczynski24966d42015-09-05 15:00:00 -0700100 private boolean mTraversalScheduled;
Jorim Jaggic4025202015-10-22 16:43:34 +0200101 private int mDeferDepth = 0;
Filip Gruszczynski24966d42015-09-05 15:00:00 -0700102
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -0800103 private static final class LayerAndToken {
104 public int layer;
105 public AppWindowToken token;
106 }
107 private final LayerAndToken mTmpLayerAndToken = new LayerAndToken();
108
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800109 private final SparseIntArray mTempTransitionReasons = new SparseIntArray();
Jorim Jaggi3dac63a2016-03-01 12:37:07 +0100110
Jorim Jaggied7993b2017-03-28 18:50:01 +0100111 private final Runnable mPerformSurfacePlacement;
112
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700113 public WindowSurfacePlacer(WindowManagerService service) {
114 mService = service;
Wale Ogunwale0303c572016-10-20 10:16:29 -0700115 mWallpaperControllerLocked = mService.mRoot.mWallpaperController;
Jorim Jaggied7993b2017-03-28 18:50:01 +0100116 mPerformSurfacePlacement = () -> {
117 synchronized (mService.mWindowMap) {
118 performSurfacePlacement();
119 }
120 };
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700121 }
122
Jorim Jaggic4025202015-10-22 16:43:34 +0200123 /**
124 * See {@link WindowManagerService#deferSurfaceLayout()}
125 */
126 void deferLayout() {
127 mDeferDepth++;
128 }
129
130 /**
131 * See {@link WindowManagerService#continueSurfaceLayout()}
132 */
133 void continueLayout() {
134 mDeferDepth--;
135 if (mDeferDepth <= 0) {
136 performSurfacePlacement();
137 }
138 }
139
Jorim Jaggi1f833082017-08-04 18:06:56 +0200140 boolean isLayoutDeferred() {
141 return mDeferDepth > 0;
142 }
143
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700144 final void performSurfacePlacement() {
Jorim Jaggi02886a82016-12-06 09:10:06 -0800145 performSurfacePlacement(false /* force */);
146 }
147
148 final void performSurfacePlacement(boolean force) {
149 if (mDeferDepth > 0 && !force) {
Jorim Jaggic4025202015-10-22 16:43:34 +0200150 return;
151 }
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700152 int loopCount = 6;
153 do {
Filip Gruszczynski24966d42015-09-05 15:00:00 -0700154 mTraversalScheduled = false;
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700155 performSurfacePlacementLoop();
Jorim Jaggied7993b2017-03-28 18:50:01 +0100156 mService.mAnimationHandler.removeCallbacks(mPerformSurfacePlacement);
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700157 loopCount--;
Filip Gruszczynski24966d42015-09-05 15:00:00 -0700158 } while (mTraversalScheduled && loopCount > 0);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700159 mService.mRoot.mWallpaperActionPending = false;
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700160 }
161
162 private void performSurfacePlacementLoop() {
163 if (mInLayout) {
164 if (DEBUG) {
165 throw new RuntimeException("Recursive call!");
166 }
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800167 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700168 + Debug.getCallers(3));
169 return;
170 }
171
172 if (mService.mWaitingForConfig) {
173 // Our configuration has changed (most likely rotation), but we
174 // don't yet have the complete configuration to report to
175 // applications. Don't do any window layout until we have it.
176 return;
177 }
178
179 if (!mService.mDisplayReady) {
180 // Not yet initialized, nothing to do.
181 return;
182 }
183
184 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
185 mInLayout = true;
186
187 boolean recoveringMemory = false;
188 if (!mService.mForceRemoves.isEmpty()) {
189 recoveringMemory = true;
190 // Wait a little bit for things to settle down, and off we go.
191 while (!mService.mForceRemoves.isEmpty()) {
Wale Ogunwaleadde52e2016-07-16 13:11:55 -0700192 final WindowState ws = mService.mForceRemoves.remove(0);
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800193 Slog.i(TAG, "Force removing: " + ws);
Wale Ogunwale571771c2016-08-26 13:18:50 -0700194 ws.removeImmediately();
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700195 }
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800196 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700197 Object tmp = new Object();
198 synchronized (tmp) {
199 try {
200 tmp.wait(250);
201 } catch (InterruptedException e) {
202 }
203 }
204 }
205
206 try {
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700207 mService.mRoot.performSurfacePlacement(recoveringMemory);
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700208
209 mInLayout = false;
210
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -0700211 if (mService.mRoot.isLayoutNeeded()) {
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700212 if (++mLayoutRepeatCount < 6) {
Filip Gruszczynski24966d42015-09-05 15:00:00 -0700213 requestTraversal();
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700214 } else {
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800215 Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700216 mLayoutRepeatCount = 0;
217 }
218 } else {
219 mLayoutRepeatCount = 0;
220 }
221
222 if (mService.mWindowsChanged && !mService.mWindowChangeListeners.isEmpty()) {
223 mService.mH.removeMessages(REPORT_WINDOWS_CHANGE);
224 mService.mH.sendEmptyMessage(REPORT_WINDOWS_CHANGE);
225 }
226 } catch (RuntimeException e) {
227 mInLayout = false;
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800228 Slog.wtf(TAG, "Unhandled exception while laying out windows", e);
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700229 }
230
231 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
232 }
233
234 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
235 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800236 Slog.v(TAG, "Layouts looping: " + msg +
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700237 ", mPendingLayoutChanges = 0x" + Integer.toHexString(pendingLayoutChanges));
238 }
239 }
240
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700241 boolean isInLayout() {
242 return mInLayout;
243 }
244
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700245 /**
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700246 * @return bitmap indicating if another pass through layout must be made.
247 */
Wale Ogunwale0303c572016-10-20 10:16:29 -0700248 int handleAppTransitionReadyLocked() {
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700249 int appsCount = mService.mOpeningApps.size();
Jorim Jaggidbaad382017-07-18 13:22:52 +0200250 if (!transitionGoodToGo(appsCount, mTempTransitionReasons)) {
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700251 return 0;
252 }
Chong Zhang8784be62016-06-28 15:25:07 -0700253 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "AppTransitionReady");
254
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800255 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700256 int transit = mService.mAppTransition.getAppTransition();
Jorim Jaggia69243a2017-06-15 15:10:38 -0400257 if (mService.mSkipAppTransitionAnimation && !isKeyguardGoingAwayTransit(transit)) {
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100258 transit = WindowManager.TRANSIT_UNSET;
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700259 }
260 mService.mSkipAppTransitionAnimation = false;
261 mService.mNoAnimationNotifyOnTransitionFinished.clear();
262
Jorim Jaggid75962e2016-05-03 15:10:03 -0700263 mService.mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700264
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700265 final DisplayContent displayContent = mService.getDefaultDisplayContentLocked();
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700266
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700267 mService.mRoot.mWallpaperMayChange = false;
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700268
Chong Zhangec8299c2016-07-29 13:09:40 -0700269 int i;
270 for (i = 0; i < appsCount; i++) {
271 final AppWindowToken wtoken = mService.mOpeningApps.valueAt(i);
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700272 // Clearing the mAnimatingExit flag before entering animation. It's set to true if app
273 // window is removed, or window relayout to invisible. This also affects window
274 // visibility. We need to clear it *before* maybeUpdateTransitToWallpaper() as the
275 // transition selection depends on wallpaper target visibility.
Chong Zhangec8299c2016-07-29 13:09:40 -0700276 wtoken.clearAnimatingFlags();
Chong Zhangec8299c2016-07-29 13:09:40 -0700277 }
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700278
Chong Zhangec8299c2016-07-29 13:09:40 -0700279 // Adjust wallpaper before we pull the lower/upper target, since pending changes
280 // (like the clearAnimatingFlags() above) might affect wallpaper target result.
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700281 // Or, the opening app window should be a wallpaper target.
282 mWallpaperControllerLocked.adjustWallpaperWindowsForAppTransitionIfNeeded(displayContent,
Wale Ogunwale0303c572016-10-20 10:16:29 -0700283 mService.mOpeningApps);
Chong Zhangec8299c2016-07-29 13:09:40 -0700284
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100285 // Determine if closing and opening app token sets are wallpaper targets, in which case
286 // special animations are needed.
287 final boolean hasWallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget() != null;
288 final boolean openingAppHasWallpaper = canBeWallpaperTarget(mService.mOpeningApps)
289 && hasWallpaperTarget;
290 final boolean closingAppHasWallpaper = canBeWallpaperTarget(mService.mClosingApps)
291 && hasWallpaperTarget;
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700292
Jorim Jaggi98a9d202018-03-26 16:17:07 +0200293 transit = maybeUpdateTransitToTranslucentAnim(transit);
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700294 transit = maybeUpdateTransitToWallpaper(transit, openingAppHasWallpaper,
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800295 closingAppHasWallpaper);
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700296
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100297 // Find the layout params of the top-most application window in the tokens, which is
298 // what will control the animation theme. If all closing windows are obscured, then there is
299 // no need to do an animation. This is the case, for example, when this transition is being
300 // done behind a dream window.
Jorim Jaggi77be1572018-03-09 16:48:24 +0100301 final ArraySet<Integer> activityTypes = collectActivityTypes(mService.mOpeningApps,
302 mService.mClosingApps);
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100303 final AppWindowToken animLpToken = mService.mPolicy.allowAppAnimationsLw()
Jorim Jaggi77be1572018-03-09 16:48:24 +0100304 ? findAnimLayoutParamsToken(transit, activityTypes)
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100305 : null;
306
307 final LayoutParams animLp = getAnimLp(animLpToken);
Jorim Jaggi77be1572018-03-09 16:48:24 +0100308 overrideWithRemoteAnimationIfSet(animLpToken, transit, activityTypes);
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100309
310 final boolean voiceInteraction = containsVoiceInteraction(mService.mOpeningApps)
311 || containsVoiceInteraction(mService.mOpeningApps);
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700312
Jorim Jaggid6d97162018-01-05 18:28:36 +0100313 final int layoutRedo;
314 mService.mSurfaceAnimationRunner.deferStartingAnimations();
315 try {
316 processApplicationsAnimatingInPlace(transit);
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700317
Jorim Jaggid6d97162018-01-05 18:28:36 +0100318 mTmpLayerAndToken.token = null;
319 handleClosingApps(transit, animLp, voiceInteraction, mTmpLayerAndToken);
320 final AppWindowToken topClosingApp = mTmpLayerAndToken.token;
321 final AppWindowToken topOpeningApp = handleOpeningApps(transit, animLp,
322 voiceInteraction);
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -0800323
Jorim Jaggid6d97162018-01-05 18:28:36 +0100324 mService.mAppTransition.setLastAppTransition(transit, topOpeningApp, topClosingApp);
Chong Zhang1c93f6d2016-07-27 17:52:45 -0700325
Jorim Jaggid6d97162018-01-05 18:28:36 +0100326 final int flags = mService.mAppTransition.getTransitFlags();
327 layoutRedo = mService.mAppTransition.goodToGo(transit, topOpeningApp,
328 topClosingApp, mService.mOpeningApps, mService.mClosingApps);
329 handleNonAppWindowsInTransition(transit, flags);
330 mService.mAppTransition.postAnimationCallback();
331 mService.mAppTransition.clear();
332 } finally {
333 mService.mSurfaceAnimationRunner.continueStartingAnimations();
334 }
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -0800335
Jorim Jaggi02886a82016-12-06 09:10:06 -0800336 mService.mTaskSnapshotController.onTransitionStarting();
337
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -0800338 mService.mOpeningApps.clear();
339 mService.mClosingApps.clear();
Jorim Jaggi5a108c22016-10-13 14:33:27 +0200340 mService.mUnknownAppVisibilityController.clear();
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -0800341
342 // This has changed the visibility of windows, so perform
343 // a new layout to get them all up-to-date.
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -0700344 displayContent.setLayoutNeeded();
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -0800345
346 // TODO(multidisplay): IMEs are only supported on the default display.
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -0700347 final DisplayContent dc = mService.getDefaultDisplayContentLocked();
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000348 dc.computeImeTarget(true /* updateImeTarget */);
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -0800349 mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
350 true /*updateInputWindows*/);
351 mService.mFocusMayChange = false;
Chong Zhang8784be62016-06-28 15:25:07 -0700352
Jorim Jaggidbaad382017-07-18 13:22:52 +0200353 mService.mH.obtainMessage(NOTIFY_APP_TRANSITION_STARTING,
354 mTempTransitionReasons.clone()).sendToTarget();
355
Chong Zhang8784be62016-06-28 15:25:07 -0700356 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
357
Jorim Jaggife762342016-10-13 14:33:27 +0200358 return layoutRedo | FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_CONFIG;
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -0800359 }
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700360
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100361 private static LayoutParams getAnimLp(AppWindowToken wtoken) {
362 final WindowState mainWindow = wtoken != null ? wtoken.findMainWindow() : null;
363 return mainWindow != null ? mainWindow.mAttrs : null;
364 }
365
366 /**
367 * Overrides the pending transition with the remote animation defined for the transition in the
368 * set of defined remote animations in the app window token.
369 */
Jorim Jaggi77be1572018-03-09 16:48:24 +0100370 private void overrideWithRemoteAnimationIfSet(AppWindowToken animLpToken, int transit,
371 ArraySet<Integer> activityTypes) {
Adrian Roos93577212018-04-10 14:12:10 -0700372 if (transit == TRANSIT_CRASHING_ACTIVITY_CLOSE) {
373 // The crash transition has higher priority than any involved remote animations.
374 return;
375 }
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100376 if (animLpToken == null) {
377 return;
378 }
379 final RemoteAnimationDefinition definition = animLpToken.getRemoteAnimationDefinition();
380 if (definition != null) {
Jorim Jaggi77be1572018-03-09 16:48:24 +0100381 final RemoteAnimationAdapter adapter = definition.getAdapter(transit, activityTypes);
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100382 if (adapter != null) {
383 mService.mAppTransition.overridePendingAppTransitionRemote(adapter);
384 }
385 }
386 }
387
388 /**
389 * @return The window token that determines the animation theme.
390 */
Jorim Jaggi77be1572018-03-09 16:48:24 +0100391 private AppWindowToken findAnimLayoutParamsToken(@TransitionType int transit,
392 ArraySet<Integer> activityTypes) {
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100393 AppWindowToken result;
394
395 // Remote animations always win, but fullscreen tokens override non-fullscreen tokens.
396 result = lookForHighestTokenWithFilter(mService.mClosingApps, mService.mOpeningApps,
397 w -> w.getRemoteAnimationDefinition() != null
Jorim Jaggi77be1572018-03-09 16:48:24 +0100398 && w.getRemoteAnimationDefinition().hasTransition(transit, activityTypes));
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100399 if (result != null) {
400 return result;
401 }
402 result = lookForHighestTokenWithFilter(mService.mClosingApps, mService.mOpeningApps,
403 w -> w.fillsParent() && w.findMainWindow() != null);
404 if (result != null) {
405 return result;
406 }
407 return lookForHighestTokenWithFilter(mService.mClosingApps, mService.mOpeningApps,
408 w -> w.findMainWindow() != null);
409 }
410
Jorim Jaggi77be1572018-03-09 16:48:24 +0100411 /**
412 * @return The set of {@link WindowConfiguration.ActivityType}s contained in the set of apps in
413 * {@code array1} and {@code array2}.
414 */
415 private ArraySet<Integer> collectActivityTypes(ArraySet<AppWindowToken> array1,
416 ArraySet<AppWindowToken> array2) {
417 final ArraySet<Integer> result = new ArraySet<>();
418 for (int i = array1.size() - 1; i >= 0; i--) {
419 result.add(array1.valueAt(i).getActivityType());
420 }
421 for (int i = array2.size() - 1; i >= 0; i--) {
422 result.add(array2.valueAt(i).getActivityType());
423 }
424 return result;
425 }
426
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100427 private AppWindowToken lookForHighestTokenWithFilter(ArraySet<AppWindowToken> array1,
428 ArraySet<AppWindowToken> array2, Predicate<AppWindowToken> filter) {
429 final int array1count = array1.size();
430 final int count = array1count + array2.size();
431 int bestPrefixOrderIndex = Integer.MIN_VALUE;
432 AppWindowToken bestToken = null;
433 for (int i = 0; i < count; i++) {
Jorim Jaggi77be1572018-03-09 16:48:24 +0100434 final AppWindowToken wtoken = i < array1count
435 ? array1.valueAt(i)
436 : array2.valueAt(i - array1count);
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100437 final int prefixOrderIndex = wtoken.getPrefixOrderIndex();
438 if (filter.test(wtoken) && prefixOrderIndex > bestPrefixOrderIndex) {
439 bestPrefixOrderIndex = prefixOrderIndex;
440 bestToken = wtoken;
441 }
442 }
443 return bestToken;
444 }
445
446 private boolean containsVoiceInteraction(ArraySet<AppWindowToken> apps) {
447 for (int i = apps.size() - 1; i >= 0; i--) {
448 if (apps.valueAt(i).mVoiceInteraction) {
449 return true;
450 }
451 }
452 return false;
453 }
454
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -0800455 private AppWindowToken handleOpeningApps(int transit, LayoutParams animLp,
Matthew Ngb7e8a132017-09-29 10:27:24 -0700456 boolean voiceInteraction) {
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700457 AppWindowToken topOpeningApp = null;
Matthew Ngb7e8a132017-09-29 10:27:24 -0700458 int topOpeningLayer = Integer.MIN_VALUE;
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -0800459 final int appsCount = mService.mOpeningApps.size();
460 for (int i = 0; i < appsCount; i++) {
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700461 AppWindowToken wtoken = mService.mOpeningApps.valueAt(i);
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800462 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700463
Jorim Jaggiab9fcb22018-03-15 23:46:12 +0100464 if (!wtoken.setVisibility(animLp, true, transit, false, voiceInteraction)) {
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700465 // This token isn't going to be animating. Add it to the list of tokens to
466 // be notified of app transition complete since the notification will not be
467 // sent be the app window animator.
468 mService.mNoAnimationNotifyOnTransitionFinished.add(wtoken.token);
469 }
470 wtoken.updateReportedVisibilityLocked();
471 wtoken.waitingToShow = false;
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800472 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
Filip Gruszczynski974eb3d2015-10-23 17:33:11 -0700473 ">>> OPEN TRANSACTION handleAppTransitionReadyLocked()");
Robert Carr68e5c9e2016-09-14 10:50:09 -0700474 mService.openSurfaceTransaction();
Filip Gruszczynski974eb3d2015-10-23 17:33:11 -0700475 try {
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200476 wtoken.showAllWindowsLocked();
Filip Gruszczynski974eb3d2015-10-23 17:33:11 -0700477 } finally {
Adrian Roos111aff92017-09-27 18:11:46 +0200478 mService.closeSurfaceTransaction("handleAppTransitionReadyLocked");
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800479 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
Filip Gruszczynski974eb3d2015-10-23 17:33:11 -0700480 "<<< CLOSE TRANSACTION handleAppTransitionReadyLocked()");
481 }
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700482
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700483 if (animLp != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700484 final int layer = wtoken.getHighestAnimLayer();
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700485 if (topOpeningApp == null || layer > topOpeningLayer) {
486 topOpeningApp = wtoken;
487 topOpeningLayer = layer;
488 }
489 }
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -0800490 if (mService.mAppTransition.isNextAppTransitionThumbnailUp()) {
Jorim Jaggi988f6682017-11-17 17:46:43 +0100491 wtoken.attachThumbnailAnimation();
Tony Mak64b8d562017-12-28 17:44:02 +0000492 } else if (mService.mAppTransition.isNextAppTransitionOpenCrossProfileApps()) {
493 wtoken.attachCrossProfileAppsThumbnailAnimation();
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -0800494 }
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700495 }
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -0800496 return topOpeningApp;
497 }
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700498
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -0800499 private void handleClosingApps(int transit, LayoutParams animLp, boolean voiceInteraction,
500 LayerAndToken layerAndToken) {
501 final int appsCount;
502 appsCount = mService.mClosingApps.size();
503 for (int i = 0; i < appsCount; i++) {
504 AppWindowToken wtoken = mService.mClosingApps.valueAt(i);
Chong Zhangf58631a2016-05-24 16:02:10 -0700505
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800506 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
Winson Chung87e5d552017-04-05 11:49:38 -0700507 // TODO: Do we need to add to mNoAnimationNotifyOnTransitionFinished like above if not
508 // animating?
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700509 wtoken.setVisibility(animLp, false, transit, false, voiceInteraction);
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -0800510 wtoken.updateReportedVisibilityLocked();
511 // Force the allDrawn flag, because we want to start
512 // this guy's animations regardless of whether it's
513 // gotten drawn.
514 wtoken.allDrawn = true;
515 wtoken.deferClearAllDrawn = false;
516 // Ensure that apps that are mid-starting are also scheduled to have their
517 // starting windows removed after the animation is complete
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800518 if (wtoken.startingWindow != null && !wtoken.startingWindow.mAnimatingExit
519 && wtoken.getController() != null) {
520 wtoken.getController().removeStartingWindow();
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -0800521 }
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700522
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -0800523 if (animLp != null) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700524 int layer = wtoken.getHighestAnimLayer();
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -0800525 if (layerAndToken.token == null || layer > layerAndToken.layer) {
526 layerAndToken.token = wtoken;
527 layerAndToken.layer = layer;
528 }
529 }
530 if (mService.mAppTransition.isNextAppTransitionThumbnailDown()) {
Jorim Jaggi988f6682017-11-17 17:46:43 +0100531 wtoken.attachThumbnailAnimation();
Filip Gruszczynski4cbc3152015-12-07 11:50:57 -0800532 }
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700533 }
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700534 }
535
Jorim Jaggife762342016-10-13 14:33:27 +0200536 private void handleNonAppWindowsInTransition(int transit, int flags) {
537 if (transit == TRANSIT_KEYGUARD_GOING_AWAY) {
538 if ((flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0
539 && (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION) == 0) {
540 Animation anim = mService.mPolicy.createKeyguardWallpaperExit(
541 (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE) != 0);
542 if (anim != null) {
543 mService.getDefaultDisplayContentLocked().mWallpaperController
544 .startWallpaperAnimation(anim);
545 }
546 }
547 }
548 if (transit == TRANSIT_KEYGUARD_GOING_AWAY
549 || transit == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER) {
550 mService.getDefaultDisplayContentLocked().startKeyguardExitOnNonAppWindows(
551 transit == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
552 (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE) != 0);
553 }
554 }
555
Jorim Jaggidbaad382017-07-18 13:22:52 +0200556 private boolean transitionGoodToGo(int appsCount, SparseIntArray outReasons) {
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800557 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700558 "Checking " + appsCount + " opening apps (frozen="
559 + mService.mDisplayFrozen + " timeout="
560 + mService.mAppTransition.isTimeout() + ")...");
Robert Carr42769ff2016-09-20 13:36:42 -0700561 final ScreenRotationAnimation screenRotationAnimation =
562 mService.mAnimator.getScreenRotationAnimationLocked(
563 Display.DEFAULT_DISPLAY);
564
Jorim Jaggidbaad382017-07-18 13:22:52 +0200565 outReasons.clear();
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700566 if (!mService.mAppTransition.isTimeout()) {
Robert Carr42769ff2016-09-20 13:36:42 -0700567 // Imagine the case where we are changing orientation due to an app transition, but a previous
568 // orientation change is still in progress. We won't process the orientation change
569 // for our transition because we need to wait for the rotation animation to finish.
570 // If we start the app transition at this point, we will interrupt it halfway with a new rotation
571 // animation after the old one finally finishes. It's better to defer the
572 // app transition.
573 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating() &&
574 mService.rotationNeedsUpdateLocked()) {
575 if (DEBUG_APP_TRANSITIONS) {
576 Slog.v(TAG, "Delaying app transition for screen rotation animation to finish");
577 }
578 return false;
579 }
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700580 for (int i = 0; i < appsCount; i++) {
581 AppWindowToken wtoken = mService.mOpeningApps.valueAt(i);
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800582 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700583 "Check opening app=" + wtoken + ": allDrawn="
584 + wtoken.allDrawn + " startingDisplayed="
585 + wtoken.startingDisplayed + " startingMoved="
Chong Zhangd78ddb42016-03-02 17:01:14 -0800586 + wtoken.startingMoved + " isRelaunching()="
Jorim Jaggi60f9c972018-02-01 19:21:07 +0100587 + wtoken.isRelaunching() + " startingWindow="
588 + wtoken.startingWindow);
Chong Zhangd78ddb42016-03-02 17:01:14 -0800589
Chong Zhangbfc2f8f2016-01-29 15:50:34 -0800590
Jorim Jaggi02886a82016-12-06 09:10:06 -0800591 final boolean allDrawn = wtoken.allDrawn && !wtoken.isRelaunching();
592 if (!allDrawn && !wtoken.startingDisplayed && !wtoken.startingMoved) {
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700593 return false;
594 }
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100595 final int windowingMode = wtoken.getWindowingMode();
Jorim Jaggi02886a82016-12-06 09:10:06 -0800596 if (allDrawn) {
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100597 outReasons.put(windowingMode, APP_TRANSITION_WINDOWS_DRAWN);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500598 } else {
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100599 outReasons.put(windowingMode,
600 wtoken.startingData instanceof SplashScreenStartingData
601 ? APP_TRANSITION_SPLASH_SCREEN
602 : APP_TRANSITION_SNAPSHOT);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500603 }
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700604 }
605
Jorim Jaggi2f7d2922015-10-29 13:08:29 +0100606 // We also need to wait for the specs to be fetched, if needed.
607 if (mService.mAppTransition.isFetchingAppTransitionsSpecs()) {
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800608 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "isFetchingAppTransitionSpecs=true");
Jorim Jaggi2f7d2922015-10-29 13:08:29 +0100609 return false;
610 }
611
Jorim Jaggi5a108c22016-10-13 14:33:27 +0200612 if (!mService.mUnknownAppVisibilityController.allResolved()) {
613 if (DEBUG_APP_TRANSITIONS) {
614 Slog.v(TAG, "unknownApps is not empty: "
615 + mService.mUnknownAppVisibilityController.getDebugMessage());
616 }
617 return false;
618 }
619
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700620 // If the wallpaper is visible, we need to check it's ready too.
Jorim Jaggi275561a2016-02-23 10:11:02 -0500621 boolean wallpaperReady = !mWallpaperControllerLocked.isWallpaperVisible() ||
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700622 mWallpaperControllerLocked.wallpaperTransitionReady();
Jorim Jaggi275561a2016-02-23 10:11:02 -0500623 if (wallpaperReady) {
Jorim Jaggi275561a2016-02-23 10:11:02 -0500624 return true;
625 }
626 return false;
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700627 }
628 return true;
629 }
630
631 private int maybeUpdateTransitToWallpaper(int transit, boolean openingAppHasWallpaper,
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800632 boolean closingAppHasWallpaper) {
Adrian Roos93577212018-04-10 14:12:10 -0700633 // Given no app transition pass it through instead of a wallpaper transition.
634 // Never convert the crashing transition.
Winson Chungc1674272018-02-21 10:15:17 -0800635 // Never update the transition for the wallpaper if we are just docking from recents
Adrian Roos93577212018-04-10 14:12:10 -0700636 if (transit == TRANSIT_NONE || transit == TRANSIT_CRASHING_ACTIVITY_CLOSE
637 || transit == TRANSIT_DOCK_TASK_FROM_RECENTS) {
638 return transit;
Winson Chungc1674272018-02-21 10:15:17 -0800639 }
Matthew Ng26a1cec2017-05-18 14:42:51 -0700640
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700641 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
642 final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700643 final WindowState oldWallpaper = mWallpaperControllerLocked.isWallpaperTargetAnimating()
644 ? null : wallpaperTarget;
Filip Gruszczynski49b80af2015-09-24 09:04:26 -0700645 final ArraySet<AppWindowToken> openingApps = mService.mOpeningApps;
646 final ArraySet<AppWindowToken> closingApps = mService.mClosingApps;
Jorim Jaggia96967d2018-05-22 16:30:13 +0200647 final AppWindowToken topOpeningApp = getTopApp(mService.mOpeningApps,
648 false /* ignoreHidden */);
649 final AppWindowToken topClosingApp = getTopApp(mService.mClosingApps,
650 true /* ignoreHidden */);
651
Jorim Jaggife762342016-10-13 14:33:27 +0200652 boolean openingCanBeWallpaperTarget = canBeWallpaperTarget(openingApps);
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800653 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700654 "New wallpaper target=" + wallpaperTarget
655 + ", oldWallpaper=" + oldWallpaper
Filip Gruszczynski49b80af2015-09-24 09:04:26 -0700656 + ", openingApps=" + openingApps
657 + ", closingApps=" + closingApps);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100658
Jorim Jaggia69243a2017-06-15 15:10:38 -0400659 if (openingCanBeWallpaperTarget && transit == TRANSIT_KEYGUARD_GOING_AWAY) {
Jorim Jaggife762342016-10-13 14:33:27 +0200660 transit = TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
661 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
662 "New transit: " + AppTransition.appTransitionToString(transit));
Jorim Jaggia69243a2017-06-15 15:10:38 -0400663 }
664 // We never want to change from a Keyguard transit to a non-Keyguard transit, as our logic
665 // relies on the fact that we always execute a Keyguard transition after preparing one.
666 else if (!isKeyguardGoingAwayTransit(transit)) {
667 if (closingAppHasWallpaper && openingAppHasWallpaper) {
668 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
669 switch (transit) {
670 case TRANSIT_ACTIVITY_OPEN:
671 case TRANSIT_TASK_OPEN:
672 case TRANSIT_TASK_TO_FRONT:
673 transit = TRANSIT_WALLPAPER_INTRA_OPEN;
674 break;
675 case TRANSIT_ACTIVITY_CLOSE:
676 case TRANSIT_TASK_CLOSE:
677 case TRANSIT_TASK_TO_BACK:
678 transit = TRANSIT_WALLPAPER_INTRA_CLOSE;
679 break;
680 }
681 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
682 "New transit: " + AppTransition.appTransitionToString(transit));
683 } else if (oldWallpaper != null && !mService.mOpeningApps.isEmpty()
684 && !openingApps.contains(oldWallpaper.mAppToken)
Jorim Jaggia96967d2018-05-22 16:30:13 +0200685 && closingApps.contains(oldWallpaper.mAppToken)
686 && topClosingApp == oldWallpaper.mAppToken) {
Jorim Jaggia69243a2017-06-15 15:10:38 -0400687 // We are transitioning from an activity with a wallpaper to one without.
688 transit = TRANSIT_WALLPAPER_CLOSE;
689 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit away from wallpaper: "
690 + AppTransition.appTransitionToString(transit));
Jorim Jaggi98a9d202018-03-26 16:17:07 +0200691 } else if (wallpaperTarget != null && wallpaperTarget.isVisibleLw()
692 && openingApps.contains(wallpaperTarget.mAppToken)
Jorim Jaggia96967d2018-05-22 16:30:13 +0200693 && topOpeningApp == wallpaperTarget.mAppToken
Jorim Jaggi98a9d202018-03-26 16:17:07 +0200694 && transit != TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE) {
Jorim Jaggia69243a2017-06-15 15:10:38 -0400695 // We are transitioning from an activity without
696 // a wallpaper to now showing the wallpaper
697 transit = TRANSIT_WALLPAPER_OPEN;
698 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit into wallpaper: "
699 + AppTransition.appTransitionToString(transit));
Jorim Jaggia69243a2017-06-15 15:10:38 -0400700 }
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700701 }
702 return transit;
703 }
704
Jorim Jaggi98a9d202018-03-26 16:17:07 +0200705 /**
706 * There are cases where we open/close a new task/activity, but in reality only a translucent
707 * activity on top of existing activities is opening/closing. For that one, we have a different
708 * animation because non of the task/activity animations actually work well with translucent
709 * apps.
710 *
711 * @param transit The current transition type.
712 * @return The current transition type or
713 * {@link WindowManager#TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE}/
714 * {@link WindowManager#TRANSIT_TRANSLUCENT_ACTIVITY_OPEN} if appropriate for the
715 * situation.
716 */
717 @VisibleForTesting
718 int maybeUpdateTransitToTranslucentAnim(int transit) {
719 final boolean taskOrActivity = AppTransition.isTaskTransit(transit)
720 || AppTransition.isActivityTransit(transit);
721 boolean allOpeningVisible = true;
722 boolean allTranslucentOpeningApps = !mService.mOpeningApps.isEmpty();
723 for (int i = mService.mOpeningApps.size() - 1; i >= 0; i--) {
724 final AppWindowToken token = mService.mOpeningApps.valueAt(i);
725 if (!token.isVisible()) {
726 allOpeningVisible = false;
727 if (token.fillsParent()) {
728 allTranslucentOpeningApps = false;
729 }
730 }
731 }
732 boolean allTranslucentClosingApps = !mService.mClosingApps.isEmpty();
733 for (int i = mService.mClosingApps.size() - 1; i >= 0; i--) {
734 if (mService.mClosingApps.valueAt(i).fillsParent()) {
735 allTranslucentClosingApps = false;
736 break;
737 }
738 }
739
740 if (taskOrActivity && allTranslucentClosingApps && allOpeningVisible) {
741 return TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE;
742 }
743 if (taskOrActivity && allTranslucentOpeningApps && mService.mClosingApps.isEmpty()) {
744 return TRANSIT_TRANSLUCENT_ACTIVITY_OPEN;
745 }
746 return transit;
747 }
748
Jorim Jaggife762342016-10-13 14:33:27 +0200749 private boolean canBeWallpaperTarget(ArraySet<AppWindowToken> apps) {
750 for (int i = apps.size() - 1; i >= 0; i--) {
751 if (apps.valueAt(i).windowsCanBeWallpaperTarget()) {
752 return true;
753 }
754 }
755 return false;
756 }
757
Jorim Jaggia96967d2018-05-22 16:30:13 +0200758 /**
759 * Finds the top app in a list of apps, using its {@link AppWindowToken#getPrefixOrderIndex} to
760 * compare z-order.
761 *
762 * @param apps The list of apps to search.
763 * @param ignoreHidden If set to true, ignores apps that are {@link AppWindowToken#isHidden}.
764 * @return The top {@link AppWindowToken}.
765 */
766 private AppWindowToken getTopApp(ArraySet<AppWindowToken> apps, boolean ignoreHidden) {
767 int topPrefixOrderIndex = Integer.MIN_VALUE;
768 AppWindowToken topApp = null;
769 for (int i = apps.size() - 1; i >= 0; i--) {
770 final AppWindowToken app = apps.valueAt(i);
771 if (ignoreHidden && app.isHidden()) {
772 continue;
773 }
774 final int prefixOrderIndex = app.getPrefixOrderIndex();
775 if (prefixOrderIndex > topPrefixOrderIndex) {
776 topPrefixOrderIndex = prefixOrderIndex;
777 topApp = app;
778 }
779 }
780 return topApp;
781 }
782
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700783 private void processApplicationsAnimatingInPlace(int transit) {
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700784 if (transit == TRANSIT_TASK_IN_PLACE) {
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700785 // Find the focused window
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700786 final WindowState win = mService.getDefaultDisplayContentLocked().findFocusedWindow();
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700787 if (win != null) {
788 final AppWindowToken wtoken = win.mAppToken;
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700789 if (DEBUG_APP_TRANSITIONS)
Filip Gruszczynskice4ec402016-01-22 11:22:47 -0800790 Slog.v(TAG, "Now animating app in place " + wtoken);
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200791 wtoken.cancelAnimation();
792 wtoken.applyAnimationLocked(null, transit, false, false);
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700793 wtoken.updateReportedVisibilityLocked();
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200794 wtoken.showAllWindowsLocked();
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700795 }
796 }
797 }
798
Filip Gruszczynski24966d42015-09-05 15:00:00 -0700799 void requestTraversal() {
800 if (!mTraversalScheduled) {
801 mTraversalScheduled = true;
Jorim Jaggied7993b2017-03-28 18:50:01 +0100802 mService.mAnimationHandler.post(mPerformSurfacePlacement);
Filip Gruszczynski24966d42015-09-05 15:00:00 -0700803 }
804 }
805
806 public void dump(PrintWriter pw, String prefix) {
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700807 pw.println(prefix + "mTraversalScheduled=" + mTraversalScheduled);
808 pw.println(prefix + "mHoldScreenWindow=" + mService.mRoot.mHoldScreenWindow);
Wale Ogunwaled4a00a02016-10-10 11:29:17 -0700809 pw.println(prefix + "mObscuringWindow=" + mService.mRoot.mObscuringWindow);
Filip Gruszczynski24966d42015-09-05 15:00:00 -0700810 }
Filip Gruszczynski4501d232015-09-02 13:00:02 -0700811}