blob: e9ad0d361b07c95a0bcddfea82495da1a87129f6 [file] [log] [blame]
lumark588a3e82018-07-20 18:53:54 +08001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.server.wm;
18
19import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
20import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
21import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
Evan Rosky7735d352019-03-18 17:27:27 -070022import static android.view.WindowManager.TRANSIT_ACTIVITY_RELAUNCH;
lumark588a3e82018-07-20 18:53:54 +080023import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
24import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
25import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
Issei Suzuki5609ccb2019-06-13 15:04:08 +020026import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION;
lumark588a3e82018-07-20 18:53:54 +080027import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
28import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
29import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
30import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
31import static android.view.WindowManager.TRANSIT_NONE;
Issei Suzukicac2a502019-04-16 16:52:50 +020032import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
lumark588a3e82018-07-20 18:53:54 +080033import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
lumark588a3e82018-07-20 18:53:54 +080034import static android.view.WindowManager.TRANSIT_TASK_OPEN;
35import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
36import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
37import static android.view.WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE;
38import static android.view.WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_OPEN;
39import static android.view.WindowManager.TRANSIT_WALLPAPER_CLOSE;
40import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_CLOSE;
41import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_OPEN;
42import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
43
44import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
45import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
46import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SNAPSHOT;
47import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SPLASH_SCREEN;
48import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
49import static com.android.server.wm.AppTransition.isKeyguardGoingAwayTransit;
Adrian Roosb125e0b2019-10-02 14:55:14 +020050import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
lumark588a3e82018-07-20 18:53:54 +080051import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
52import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
53import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
lumark588a3e82018-07-20 18:53:54 +080054
lumark588a3e82018-07-20 18:53:54 +080055import android.os.Trace;
Riddle Hsufd66d4d2019-11-14 10:35:55 +080056import android.util.ArrayMap;
lumark588a3e82018-07-20 18:53:54 +080057import android.util.ArraySet;
58import android.util.Slog;
lumark588a3e82018-07-20 18:53:54 +080059import android.view.Display;
60import android.view.RemoteAnimationAdapter;
61import android.view.RemoteAnimationDefinition;
62import android.view.WindowManager;
63import android.view.WindowManager.LayoutParams;
64import android.view.animation.Animation;
65
66import com.android.internal.annotations.VisibleForTesting;
Adrian Roosb125e0b2019-10-02 14:55:14 +020067import com.android.server.protolog.common.ProtoLog;
lumark588a3e82018-07-20 18:53:54 +080068
69import java.util.function.Predicate;
70
71
72/**
73 * Checks for app transition readiness, resolves animation attributes and performs visibility
74 * change for apps that animate as part of an app transition.
75 */
76public class AppTransitionController {
77 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppTransitionController" : TAG_WM;
78 private final WindowManagerService mService;
79 private final DisplayContent mDisplayContent;
80 private final WallpaperController mWallpaperControllerLocked;
Evan Rosky966759f2019-01-15 10:33:58 -080081 private RemoteAnimationDefinition mRemoteAnimationDefinition = null;
lumark588a3e82018-07-20 18:53:54 +080082
Riddle Hsufd66d4d2019-11-14 10:35:55 +080083 private final ArrayMap<ActivityRecord, Integer> mTempTransitionReasons = new ArrayMap<>();
lumark588a3e82018-07-20 18:53:54 +080084
85 AppTransitionController(WindowManagerService service, DisplayContent displayContent) {
86 mService = service;
87 mDisplayContent = displayContent;
wilsonshihc32538e2018-11-07 17:27:34 +080088 mWallpaperControllerLocked = mDisplayContent.mWallpaperController;
lumark588a3e82018-07-20 18:53:54 +080089 }
90
Evan Rosky966759f2019-01-15 10:33:58 -080091 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
92 mRemoteAnimationDefinition = definition;
93 }
94
lumark588a3e82018-07-20 18:53:54 +080095 /**
96 * Handle application transition for given display.
97 */
98 void handleAppTransitionReady() {
Evan Rosky2289ba12018-11-19 18:28:18 -080099 mTempTransitionReasons.clear();
100 if (!transitionGoodToGo(mDisplayContent.mOpeningApps, mTempTransitionReasons)
101 || !transitionGoodToGo(mDisplayContent.mChangingApps, mTempTransitionReasons)) {
lumark588a3e82018-07-20 18:53:54 +0800102 return;
103 }
104 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "AppTransitionReady");
105
Adrian Roosb125e0b2019-10-02 14:55:14 +0200106 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "**** GOOD TO GO");
Tiger Huang7c610aa2018-10-27 00:01:01 +0800107 final AppTransition appTransition = mDisplayContent.mAppTransition;
108 int transit = appTransition.getAppTransition();
lumark588a3e82018-07-20 18:53:54 +0800109 if (mDisplayContent.mSkipAppTransitionAnimation && !isKeyguardGoingAwayTransit(transit)) {
110 transit = WindowManager.TRANSIT_UNSET;
111 }
112 mDisplayContent.mSkipAppTransitionAnimation = false;
113 mDisplayContent.mNoAnimationNotifyOnTransitionFinished.clear();
114
Tiger Huang7c610aa2018-10-27 00:01:01 +0800115 appTransition.removeAppTransitionTimeoutCallbacks();
lumark588a3e82018-07-20 18:53:54 +0800116
wilsonshihc32538e2018-11-07 17:27:34 +0800117 mDisplayContent.mWallpaperMayChange = false;
lumark588a3e82018-07-20 18:53:54 +0800118
Evan Rosky2289ba12018-11-19 18:28:18 -0800119 int appCount = mDisplayContent.mOpeningApps.size();
120 for (int i = 0; i < appCount; ++i) {
lumark588a3e82018-07-20 18:53:54 +0800121 // Clearing the mAnimatingExit flag before entering animation. It's set to true if app
122 // window is removed, or window relayout to invisible. This also affects window
123 // visibility. We need to clear it *before* maybeUpdateTransitToWallpaper() as the
124 // transition selection depends on wallpaper target visibility.
Evan Rosky2289ba12018-11-19 18:28:18 -0800125 mDisplayContent.mOpeningApps.valueAtUnchecked(i).clearAnimatingFlags();
126 }
127 appCount = mDisplayContent.mChangingApps.size();
128 for (int i = 0; i < appCount; ++i) {
129 // Clearing for same reason as above.
130 mDisplayContent.mChangingApps.valueAtUnchecked(i).clearAnimatingFlags();
lumark588a3e82018-07-20 18:53:54 +0800131 }
132
133 // Adjust wallpaper before we pull the lower/upper target, since pending changes
134 // (like the clearAnimatingFlags() above) might affect wallpaper target result.
135 // Or, the opening app window should be a wallpaper target.
wilsonshihc32538e2018-11-07 17:27:34 +0800136 mWallpaperControllerLocked.adjustWallpaperWindowsForAppTransitionIfNeeded(
Evan Rosky2289ba12018-11-19 18:28:18 -0800137 mDisplayContent.mOpeningApps, mDisplayContent.mChangingApps);
lumark588a3e82018-07-20 18:53:54 +0800138
139 // Determine if closing and opening app token sets are wallpaper targets, in which case
140 // special animations are needed.
141 final boolean hasWallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget() != null;
142 final boolean openingAppHasWallpaper = canBeWallpaperTarget(mDisplayContent.mOpeningApps)
143 && hasWallpaperTarget;
144 final boolean closingAppHasWallpaper = canBeWallpaperTarget(mDisplayContent.mClosingApps)
145 && hasWallpaperTarget;
146
147 transit = maybeUpdateTransitToTranslucentAnim(transit);
148 transit = maybeUpdateTransitToWallpaper(transit, openingAppHasWallpaper,
149 closingAppHasWallpaper);
150
151 // Find the layout params of the top-most application window in the tokens, which is
152 // what will control the animation theme. If all closing windows are obscured, then there is
153 // no need to do an animation. This is the case, for example, when this transition is being
154 // done behind a dream window.
155 final ArraySet<Integer> activityTypes = collectActivityTypes(mDisplayContent.mOpeningApps,
Evan Rosky2289ba12018-11-19 18:28:18 -0800156 mDisplayContent.mClosingApps, mDisplayContent.mChangingApps);
Tiger Huang7c610aa2018-10-27 00:01:01 +0800157 final boolean allowAnimations = mDisplayContent.getDisplayPolicy().allowAppAnimationsLw();
Garfield Tane8d84ab2019-10-11 09:49:40 -0700158 final ActivityRecord animLpActivity = allowAnimations
lumark588a3e82018-07-20 18:53:54 +0800159 ? findAnimLayoutParamsToken(transit, activityTypes)
160 : null;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700161 final ActivityRecord topOpeningApp = allowAnimations
lumark588a3e82018-07-20 18:53:54 +0800162 ? getTopApp(mDisplayContent.mOpeningApps, false /* ignoreHidden */)
163 : null;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700164 final ActivityRecord topClosingApp = allowAnimations
lumark588a3e82018-07-20 18:53:54 +0800165 ? getTopApp(mDisplayContent.mClosingApps, false /* ignoreHidden */)
166 : null;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700167 final ActivityRecord topChangingApp = allowAnimations
Evan Rosky2289ba12018-11-19 18:28:18 -0800168 ? getTopApp(mDisplayContent.mChangingApps, false /* ignoreHidden */)
169 : null;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700170 final WindowManager.LayoutParams animLp = getAnimLp(animLpActivity);
171 overrideWithRemoteAnimationIfSet(animLpActivity, transit, activityTypes);
lumark588a3e82018-07-20 18:53:54 +0800172
173 final boolean voiceInteraction = containsVoiceInteraction(mDisplayContent.mOpeningApps)
Evan Rosky2289ba12018-11-19 18:28:18 -0800174 || containsVoiceInteraction(mDisplayContent.mOpeningApps)
175 || containsVoiceInteraction(mDisplayContent.mChangingApps);
lumark588a3e82018-07-20 18:53:54 +0800176
177 final int layoutRedo;
178 mService.mSurfaceAnimationRunner.deferStartingAnimations();
179 try {
lumark588a3e82018-07-20 18:53:54 +0800180 handleClosingApps(transit, animLp, voiceInteraction);
181 handleOpeningApps(transit, animLp, voiceInteraction);
Evan Rosky2289ba12018-11-19 18:28:18 -0800182 handleChangingApps(transit, animLp, voiceInteraction);
lumark588a3e82018-07-20 18:53:54 +0800183
Tiger Huang7c610aa2018-10-27 00:01:01 +0800184 appTransition.setLastAppTransition(transit, topOpeningApp,
Evan Rosky2289ba12018-11-19 18:28:18 -0800185 topClosingApp, topChangingApp);
lumark588a3e82018-07-20 18:53:54 +0800186
Tiger Huang7c610aa2018-10-27 00:01:01 +0800187 final int flags = appTransition.getTransitFlags();
188 layoutRedo = appTransition.goodToGo(transit, topOpeningApp,
Evan Rosky2289ba12018-11-19 18:28:18 -0800189 mDisplayContent.mOpeningApps);
lumark588a3e82018-07-20 18:53:54 +0800190 handleNonAppWindowsInTransition(transit, flags);
Tiger Huang7c610aa2018-10-27 00:01:01 +0800191 appTransition.postAnimationCallback();
192 appTransition.clear();
lumark588a3e82018-07-20 18:53:54 +0800193 } finally {
194 mService.mSurfaceAnimationRunner.continueStartingAnimations();
195 }
196
197 mService.mTaskSnapshotController.onTransitionStarting(mDisplayContent);
198
199 mDisplayContent.mOpeningApps.clear();
200 mDisplayContent.mClosingApps.clear();
Evan Rosky2289ba12018-11-19 18:28:18 -0800201 mDisplayContent.mChangingApps.clear();
lumark588a3e82018-07-20 18:53:54 +0800202 mDisplayContent.mUnknownAppVisibilityController.clear();
203
204 // This has changed the visibility of windows, so perform
205 // a new layout to get them all up-to-date.
206 mDisplayContent.setLayoutNeeded();
207
208 mDisplayContent.computeImeTarget(true /* updateImeTarget */);
209
Riddle Hsufd66d4d2019-11-14 10:35:55 +0800210 mService.mAtmService.mStackSupervisor.getActivityMetricsLogger().notifyTransitionStarting(
211 mTempTransitionReasons);
lumark588a3e82018-07-20 18:53:54 +0800212
Issei Suzukicac2a502019-04-16 16:52:50 +0200213 if (transit == TRANSIT_SHOW_SINGLE_TASK_DISPLAY) {
214 mService.mAnimator.addAfterPrepareSurfacesRunnable(() -> {
215 mService.mAtmInternal.notifySingleTaskDisplayDrawn(mDisplayContent.getDisplayId());
216 });
217 }
218
lumark588a3e82018-07-20 18:53:54 +0800219 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
220
221 mDisplayContent.pendingLayoutChanges |=
222 layoutRedo | FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_CONFIG;
223 }
224
Garfield Tane8d84ab2019-10-11 09:49:40 -0700225 private static WindowManager.LayoutParams getAnimLp(ActivityRecord activity) {
226 final WindowState mainWindow = activity != null ? activity.findMainWindow() : null;
lumark588a3e82018-07-20 18:53:54 +0800227 return mainWindow != null ? mainWindow.mAttrs : null;
228 }
229
Garfield Tane8d84ab2019-10-11 09:49:40 -0700230 RemoteAnimationAdapter getRemoteAnimationOverride(ActivityRecord animLpActivity, int transit,
Evan Rosky966759f2019-01-15 10:33:58 -0800231 ArraySet<Integer> activityTypes) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700232 final RemoteAnimationDefinition definition = animLpActivity.getRemoteAnimationDefinition();
Evan Rosky966759f2019-01-15 10:33:58 -0800233 if (definition != null) {
234 final RemoteAnimationAdapter adapter = definition.getAdapter(transit, activityTypes);
235 if (adapter != null) {
236 return adapter;
237 }
238 }
239 if (mRemoteAnimationDefinition == null) {
240 return null;
241 }
242 return mRemoteAnimationDefinition.getAdapter(transit, activityTypes);
243 }
244
lumark588a3e82018-07-20 18:53:54 +0800245 /**
246 * Overrides the pending transition with the remote animation defined for the transition in the
247 * set of defined remote animations in the app window token.
248 */
Garfield Tane8d84ab2019-10-11 09:49:40 -0700249 private void overrideWithRemoteAnimationIfSet(ActivityRecord animLpActivity, int transit,
lumark588a3e82018-07-20 18:53:54 +0800250 ArraySet<Integer> activityTypes) {
251 if (transit == TRANSIT_CRASHING_ACTIVITY_CLOSE) {
252 // The crash transition has higher priority than any involved remote animations.
253 return;
254 }
Garfield Tane8d84ab2019-10-11 09:49:40 -0700255 if (animLpActivity == null) {
lumark588a3e82018-07-20 18:53:54 +0800256 return;
257 }
Evan Rosky966759f2019-01-15 10:33:58 -0800258 final RemoteAnimationAdapter adapter =
Garfield Tane8d84ab2019-10-11 09:49:40 -0700259 getRemoteAnimationOverride(animLpActivity, transit, activityTypes);
lumark588a3e82018-07-20 18:53:54 +0800260 if (adapter != null) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700261 animLpActivity.getDisplayContent().mAppTransition.overridePendingAppTransitionRemote(
lumark588a3e82018-07-20 18:53:54 +0800262 adapter);
263 }
264 }
265
266 /**
267 * @return The window token that determines the animation theme.
268 */
Garfield Tane8d84ab2019-10-11 09:49:40 -0700269 private ActivityRecord findAnimLayoutParamsToken(@WindowManager.TransitionType int transit,
lumark588a3e82018-07-20 18:53:54 +0800270 ArraySet<Integer> activityTypes) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700271 ActivityRecord result;
272 final ArraySet<ActivityRecord> closingApps = mDisplayContent.mClosingApps;
273 final ArraySet<ActivityRecord> openingApps = mDisplayContent.mOpeningApps;
274 final ArraySet<ActivityRecord> changingApps = mDisplayContent.mChangingApps;
lumark588a3e82018-07-20 18:53:54 +0800275
276 // Remote animations always win, but fullscreen tokens override non-fullscreen tokens.
Evan Rosky2289ba12018-11-19 18:28:18 -0800277 result = lookForHighestTokenWithFilter(closingApps, openingApps, changingApps,
lumark588a3e82018-07-20 18:53:54 +0800278 w -> w.getRemoteAnimationDefinition() != null
279 && w.getRemoteAnimationDefinition().hasTransition(transit, activityTypes));
280 if (result != null) {
281 return result;
282 }
Evan Rosky2289ba12018-11-19 18:28:18 -0800283 result = lookForHighestTokenWithFilter(closingApps, openingApps, changingApps,
lumark588a3e82018-07-20 18:53:54 +0800284 w -> w.fillsParent() && w.findMainWindow() != null);
285 if (result != null) {
286 return result;
287 }
Evan Rosky2289ba12018-11-19 18:28:18 -0800288 return lookForHighestTokenWithFilter(closingApps, openingApps, changingApps,
lumark588a3e82018-07-20 18:53:54 +0800289 w -> w.findMainWindow() != null);
290 }
291
292 /**
Tiger Huang7c610aa2018-10-27 00:01:01 +0800293 * @return The set of {@link android.app.WindowConfiguration.ActivityType}s contained in the set
Evan Rosky2289ba12018-11-19 18:28:18 -0800294 * of apps in {@code array1}, {@code array2}, and {@code array3}.
lumark588a3e82018-07-20 18:53:54 +0800295 */
Garfield Tane8d84ab2019-10-11 09:49:40 -0700296 private static ArraySet<Integer> collectActivityTypes(ArraySet<ActivityRecord> array1,
297 ArraySet<ActivityRecord> array2, ArraySet<ActivityRecord> array3) {
lumark588a3e82018-07-20 18:53:54 +0800298 final ArraySet<Integer> result = new ArraySet<>();
299 for (int i = array1.size() - 1; i >= 0; i--) {
300 result.add(array1.valueAt(i).getActivityType());
301 }
302 for (int i = array2.size() - 1; i >= 0; i--) {
303 result.add(array2.valueAt(i).getActivityType());
304 }
Evan Rosky2289ba12018-11-19 18:28:18 -0800305 for (int i = array3.size() - 1; i >= 0; i--) {
306 result.add(array3.valueAt(i).getActivityType());
307 }
lumark588a3e82018-07-20 18:53:54 +0800308 return result;
309 }
310
Garfield Tane8d84ab2019-10-11 09:49:40 -0700311 private static ActivityRecord lookForHighestTokenWithFilter(ArraySet<ActivityRecord> array1,
312 ArraySet<ActivityRecord> array2, ArraySet<ActivityRecord> array3,
313 Predicate<ActivityRecord> filter) {
Evan Rosky2289ba12018-11-19 18:28:18 -0800314 final int array2base = array1.size();
315 final int array3base = array2.size() + array2base;
316 final int count = array3base + array3.size();
lumark588a3e82018-07-20 18:53:54 +0800317 int bestPrefixOrderIndex = Integer.MIN_VALUE;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700318 ActivityRecord bestToken = null;
lumark588a3e82018-07-20 18:53:54 +0800319 for (int i = 0; i < count; i++) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700320 final ActivityRecord wtoken = i < array2base
lumark588a3e82018-07-20 18:53:54 +0800321 ? array1.valueAt(i)
Evan Rosky2289ba12018-11-19 18:28:18 -0800322 : (i < array3base
323 ? array2.valueAt(i - array2base)
324 : array3.valueAt(i - array3base));
lumark588a3e82018-07-20 18:53:54 +0800325 final int prefixOrderIndex = wtoken.getPrefixOrderIndex();
326 if (filter.test(wtoken) && prefixOrderIndex > bestPrefixOrderIndex) {
327 bestPrefixOrderIndex = prefixOrderIndex;
328 bestToken = wtoken;
329 }
330 }
331 return bestToken;
332 }
333
Garfield Tane8d84ab2019-10-11 09:49:40 -0700334 private boolean containsVoiceInteraction(ArraySet<ActivityRecord> apps) {
lumark588a3e82018-07-20 18:53:54 +0800335 for (int i = apps.size() - 1; i >= 0; i--) {
336 if (apps.valueAt(i).mVoiceInteraction) {
337 return true;
338 }
339 }
340 return false;
341 }
342
343 private void handleOpeningApps(int transit, LayoutParams animLp, boolean voiceInteraction) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700344 final ArraySet<ActivityRecord> openingApps = mDisplayContent.mOpeningApps;
lumark588a3e82018-07-20 18:53:54 +0800345 final int appsCount = openingApps.size();
346 for (int i = 0; i < appsCount; i++) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700347 ActivityRecord wtoken = openingApps.valueAt(i);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200348 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now opening app %s", wtoken);
lumark588a3e82018-07-20 18:53:54 +0800349
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800350 if (!wtoken.commitVisibility(animLp, true, transit, false, voiceInteraction)) {
lumark588a3e82018-07-20 18:53:54 +0800351 // This token isn't going to be animating. Add it to the list of tokens to
352 // be notified of app transition complete since the notification will not be
353 // sent be the app window animator.
354 mDisplayContent.mNoAnimationNotifyOnTransitionFinished.add(wtoken.token);
355 }
356 wtoken.updateReportedVisibilityLocked();
357 wtoken.waitingToShow = false;
358 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
359 ">>> OPEN TRANSACTION handleAppTransitionReady()");
360 mService.openSurfaceTransaction();
361 try {
362 wtoken.showAllWindowsLocked();
363 } finally {
364 mService.closeSurfaceTransaction("handleAppTransitionReady");
365 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
366 "<<< CLOSE TRANSACTION handleAppTransitionReady()");
367 }
368
369 if (mDisplayContent.mAppTransition.isNextAppTransitionThumbnailUp()) {
370 wtoken.attachThumbnailAnimation();
371 } else if (mDisplayContent.mAppTransition.isNextAppTransitionOpenCrossProfileApps()) {
372 wtoken.attachCrossProfileAppsThumbnailAnimation();
373 }
374 }
375 }
376
377 private void handleClosingApps(int transit, LayoutParams animLp, boolean voiceInteraction) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700378 final ArraySet<ActivityRecord> closingApps = mDisplayContent.mClosingApps;
lumark588a3e82018-07-20 18:53:54 +0800379 final int appsCount = closingApps.size();
380 for (int i = 0; i < appsCount; i++) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700381 ActivityRecord wtoken = closingApps.valueAt(i);
lumark588a3e82018-07-20 18:53:54 +0800382
Adrian Roosb125e0b2019-10-02 14:55:14 +0200383 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now closing app %s", wtoken);
lumark588a3e82018-07-20 18:53:54 +0800384 // TODO: Do we need to add to mNoAnimationNotifyOnTransitionFinished like above if not
385 // animating?
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800386 wtoken.commitVisibility(animLp, false, transit, false, voiceInteraction);
lumark588a3e82018-07-20 18:53:54 +0800387 wtoken.updateReportedVisibilityLocked();
388 // Force the allDrawn flag, because we want to start
389 // this guy's animations regardless of whether it's
390 // gotten drawn.
391 wtoken.allDrawn = true;
392 wtoken.deferClearAllDrawn = false;
393 // Ensure that apps that are mid-starting are also scheduled to have their
394 // starting windows removed after the animation is complete
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800395 if (wtoken.startingWindow != null && !wtoken.startingWindow.mAnimatingExit) {
396 wtoken.removeStartingWindow();
lumark588a3e82018-07-20 18:53:54 +0800397 }
398
399 if (mDisplayContent.mAppTransition.isNextAppTransitionThumbnailDown()) {
400 wtoken.attachThumbnailAnimation();
401 }
402 }
403 }
404
Evan Rosky2289ba12018-11-19 18:28:18 -0800405 private void handleChangingApps(int transit, LayoutParams animLp, boolean voiceInteraction) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700406 final ArraySet<ActivityRecord> apps = mDisplayContent.mChangingApps;
Evan Rosky2289ba12018-11-19 18:28:18 -0800407 final int appsCount = apps.size();
408 for (int i = 0; i < appsCount; i++) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700409 ActivityRecord activity = apps.valueAt(i);
410 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now changing app %s", activity);
411 activity.cancelAnimationOnly();
lumark19a5d2e2019-10-11 16:19:30 +0800412 activity.applyAnimation(null, transit, true, false);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700413 activity.updateReportedVisibilityLocked();
Evan Rosky2289ba12018-11-19 18:28:18 -0800414 mService.openSurfaceTransaction();
415 try {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700416 activity.showAllWindowsLocked();
Evan Rosky2289ba12018-11-19 18:28:18 -0800417 } finally {
418 mService.closeSurfaceTransaction("handleChangingApps");
419 }
420 }
421 }
422
lumark588a3e82018-07-20 18:53:54 +0800423 private void handleNonAppWindowsInTransition(int transit, int flags) {
424 if (transit == TRANSIT_KEYGUARD_GOING_AWAY) {
425 if ((flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0
Issei Suzuki5609ccb2019-06-13 15:04:08 +0200426 && (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION) == 0
427 && (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION) == 0) {
lumark588a3e82018-07-20 18:53:54 +0800428 Animation anim = mService.mPolicy.createKeyguardWallpaperExit(
429 (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE) != 0);
430 if (anim != null) {
431 mDisplayContent.mWallpaperController.startWallpaperAnimation(anim);
432 }
433 }
434 }
435 if (transit == TRANSIT_KEYGUARD_GOING_AWAY
436 || transit == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER) {
437 mDisplayContent.startKeyguardExitOnNonAppWindows(
438 transit == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
Issei Suzuki5609ccb2019-06-13 15:04:08 +0200439 (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE) != 0,
440 (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION) != 0);
lumark588a3e82018-07-20 18:53:54 +0800441 }
442 }
443
Riddle Hsufd66d4d2019-11-14 10:35:55 +0800444 private boolean transitionGoodToGo(ArraySet<ActivityRecord> apps,
445 ArrayMap<ActivityRecord, Integer> outReasons) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200446 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
447 "Checking %d opening apps (frozen=%b timeout=%b)...", apps.size(),
448 mService.mDisplayFrozen, mDisplayContent.mAppTransition.isTimeout());
Vadim Caenb3715832019-08-13 17:06:38 +0200449
450 final ScreenRotationAnimation screenRotationAnimation = mService.mRoot.getDisplayContent(
451 Display.DEFAULT_DISPLAY).getRotationAnimation();
lumark588a3e82018-07-20 18:53:54 +0800452
lumark588a3e82018-07-20 18:53:54 +0800453 if (!mDisplayContent.mAppTransition.isTimeout()) {
454 // Imagine the case where we are changing orientation due to an app transition, but a
455 // previous orientation change is still in progress. We won't process the orientation
456 // change for our transition because we need to wait for the rotation animation to
457 // finish.
458 // If we start the app transition at this point, we will interrupt it halfway with a
459 // new rotation animation after the old one finally finishes. It's better to defer the
460 // app transition.
461 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating() &&
Riddle Hsuccf09402019-08-13 00:33:06 +0800462 mDisplayContent.getDisplayRotation().needsUpdate()) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200463 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
464 "Delaying app transition for screen rotation animation to finish");
lumark588a3e82018-07-20 18:53:54 +0800465 return false;
466 }
Evan Rosky2289ba12018-11-19 18:28:18 -0800467 for (int i = 0; i < apps.size(); i++) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700468 ActivityRecord activity = apps.valueAt(i);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200469 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
470 "Check opening app=%s: allDrawn=%b startingDisplayed=%b "
471 + "startingMoved=%b isRelaunching()=%b startingWindow=%s",
Garfield Tane8d84ab2019-10-11 09:49:40 -0700472 activity, activity.allDrawn, activity.startingDisplayed,
473 activity.startingMoved, activity.isRelaunching(),
474 activity.startingWindow);
lumark588a3e82018-07-20 18:53:54 +0800475
476
Garfield Tane8d84ab2019-10-11 09:49:40 -0700477 final boolean allDrawn = activity.allDrawn && !activity.isRelaunching();
478 if (!allDrawn && !activity.startingDisplayed && !activity.startingMoved) {
lumark588a3e82018-07-20 18:53:54 +0800479 return false;
480 }
lumark588a3e82018-07-20 18:53:54 +0800481 if (allDrawn) {
Riddle Hsufd66d4d2019-11-14 10:35:55 +0800482 outReasons.put(activity, APP_TRANSITION_WINDOWS_DRAWN);
lumark588a3e82018-07-20 18:53:54 +0800483 } else {
Riddle Hsufd66d4d2019-11-14 10:35:55 +0800484 outReasons.put(activity,
Garfield Tane8d84ab2019-10-11 09:49:40 -0700485 activity.mStartingData instanceof SplashScreenStartingData
lumark588a3e82018-07-20 18:53:54 +0800486 ? APP_TRANSITION_SPLASH_SCREEN
487 : APP_TRANSITION_SNAPSHOT);
488 }
489 }
490
491 // We also need to wait for the specs to be fetched, if needed.
492 if (mDisplayContent.mAppTransition.isFetchingAppTransitionsSpecs()) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200493 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "isFetchingAppTransitionSpecs=true");
lumark588a3e82018-07-20 18:53:54 +0800494 return false;
495 }
496
497 if (!mDisplayContent.mUnknownAppVisibilityController.allResolved()) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200498 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "unknownApps is not empty: %s",
499 mDisplayContent.mUnknownAppVisibilityController.getDebugMessage());
lumark588a3e82018-07-20 18:53:54 +0800500 return false;
501 }
502
503 // If the wallpaper is visible, we need to check it's ready too.
504 boolean wallpaperReady = !mWallpaperControllerLocked.isWallpaperVisible() ||
505 mWallpaperControllerLocked.wallpaperTransitionReady();
506 if (wallpaperReady) {
507 return true;
508 }
509 return false;
510 }
511 return true;
512 }
513
514 private int maybeUpdateTransitToWallpaper(int transit, boolean openingAppHasWallpaper,
515 boolean closingAppHasWallpaper) {
516 // Given no app transition pass it through instead of a wallpaper transition.
517 // Never convert the crashing transition.
518 // Never update the transition for the wallpaper if we are just docking from recents
Evan Roskyec9488c2019-03-01 19:32:12 -0800519 // Never convert a change transition since the top activity isn't changing and will likely
520 // still be above an opening wallpaper.
lumark588a3e82018-07-20 18:53:54 +0800521 if (transit == TRANSIT_NONE || transit == TRANSIT_CRASHING_ACTIVITY_CLOSE
Evan Roskyec9488c2019-03-01 19:32:12 -0800522 || transit == TRANSIT_DOCK_TASK_FROM_RECENTS
523 || AppTransition.isChangeTransit(transit)) {
lumark588a3e82018-07-20 18:53:54 +0800524 return transit;
525 }
526
527 final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
528 final boolean showWallpaper = wallpaperTarget != null
529 && (wallpaperTarget.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
530 // If wallpaper is animating or wallpaperTarget doesn't have SHOW_WALLPAPER flag set,
531 // don't consider upgrading to wallpaper transition.
532 final WindowState oldWallpaper =
533 (mWallpaperControllerLocked.isWallpaperTargetAnimating() || !showWallpaper)
534 ? null
535 : wallpaperTarget;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700536 final ArraySet<ActivityRecord> openingApps = mDisplayContent.mOpeningApps;
537 final ArraySet<ActivityRecord> closingApps = mDisplayContent.mClosingApps;
538 final ActivityRecord topOpeningApp = getTopApp(mDisplayContent.mOpeningApps,
lumark588a3e82018-07-20 18:53:54 +0800539 false /* ignoreHidden */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700540 final ActivityRecord topClosingApp = getTopApp(mDisplayContent.mClosingApps,
lumark588a3e82018-07-20 18:53:54 +0800541 true /* ignoreHidden */);
542
543 boolean openingCanBeWallpaperTarget = canBeWallpaperTarget(openingApps);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200544 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
545 "New wallpaper target=%s, oldWallpaper=%s, openingApps=%s, closingApps=%s",
546 wallpaperTarget, oldWallpaper, openingApps, closingApps);
lumark588a3e82018-07-20 18:53:54 +0800547
548 if (openingCanBeWallpaperTarget && transit == TRANSIT_KEYGUARD_GOING_AWAY) {
549 transit = TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200550 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
551 "New transit: %s", AppTransition.appTransitionToString(transit));
lumark588a3e82018-07-20 18:53:54 +0800552 }
553 // We never want to change from a Keyguard transit to a non-Keyguard transit, as our logic
554 // relies on the fact that we always execute a Keyguard transition after preparing one.
555 else if (!isKeyguardGoingAwayTransit(transit)) {
556 if (closingAppHasWallpaper && openingAppHasWallpaper) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200557 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Wallpaper animation!");
lumark588a3e82018-07-20 18:53:54 +0800558 switch (transit) {
559 case TRANSIT_ACTIVITY_OPEN:
560 case TRANSIT_TASK_OPEN:
561 case TRANSIT_TASK_TO_FRONT:
562 transit = TRANSIT_WALLPAPER_INTRA_OPEN;
563 break;
564 case TRANSIT_ACTIVITY_CLOSE:
565 case TRANSIT_TASK_CLOSE:
566 case TRANSIT_TASK_TO_BACK:
567 transit = TRANSIT_WALLPAPER_INTRA_CLOSE;
568 break;
569 }
Adrian Roosb125e0b2019-10-02 14:55:14 +0200570 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
571 "New transit: %s", AppTransition.appTransitionToString(transit));
lumark588a3e82018-07-20 18:53:54 +0800572 } else if (oldWallpaper != null && !mDisplayContent.mOpeningApps.isEmpty()
Garfield Tane8d84ab2019-10-11 09:49:40 -0700573 && !openingApps.contains(oldWallpaper.mActivityRecord)
574 && closingApps.contains(oldWallpaper.mActivityRecord)
575 && topClosingApp == oldWallpaper.mActivityRecord) {
lumark588a3e82018-07-20 18:53:54 +0800576 // We are transitioning from an activity with a wallpaper to one without.
577 transit = TRANSIT_WALLPAPER_CLOSE;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200578 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
579 "New transit away from wallpaper: %s",
580 AppTransition.appTransitionToString(transit));
lumark588a3e82018-07-20 18:53:54 +0800581 } else if (wallpaperTarget != null && wallpaperTarget.isVisibleLw()
Garfield Tane8d84ab2019-10-11 09:49:40 -0700582 && openingApps.contains(wallpaperTarget.mActivityRecord)
583 && topOpeningApp == wallpaperTarget.mActivityRecord
lumark588a3e82018-07-20 18:53:54 +0800584 && transit != TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE) {
585 // We are transitioning from an activity without
586 // a wallpaper to now showing the wallpaper
587 transit = TRANSIT_WALLPAPER_OPEN;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200588 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "New transit into wallpaper: %s",
589 AppTransition.appTransitionToString(transit));
lumark588a3e82018-07-20 18:53:54 +0800590 }
591 }
592 return transit;
593 }
594
595 /**
596 * There are cases where we open/close a new task/activity, but in reality only a translucent
597 * activity on top of existing activities is opening/closing. For that one, we have a different
598 * animation because non of the task/activity animations actually work well with translucent
599 * apps.
600 *
601 * @param transit The current transition type.
602 * @return The current transition type or
603 * {@link WindowManager#TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE}/
604 * {@link WindowManager#TRANSIT_TRANSLUCENT_ACTIVITY_OPEN} if appropriate for the
605 * situation.
606 */
607 @VisibleForTesting
608 int maybeUpdateTransitToTranslucentAnim(int transit) {
Evan Roskyec9488c2019-03-01 19:32:12 -0800609 if (AppTransition.isChangeTransit(transit)) {
610 // There's no special animation to handle change animations with translucent apps
611 return transit;
612 }
lumark588a3e82018-07-20 18:53:54 +0800613 final boolean taskOrActivity = AppTransition.isTaskTransit(transit)
614 || AppTransition.isActivityTransit(transit);
615 boolean allOpeningVisible = true;
616 boolean allTranslucentOpeningApps = !mDisplayContent.mOpeningApps.isEmpty();
617 for (int i = mDisplayContent.mOpeningApps.size() - 1; i >= 0; i--) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700618 final ActivityRecord activity = mDisplayContent.mOpeningApps.valueAt(i);
619 if (!activity.isVisible()) {
lumark588a3e82018-07-20 18:53:54 +0800620 allOpeningVisible = false;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700621 if (activity.fillsParent()) {
lumark588a3e82018-07-20 18:53:54 +0800622 allTranslucentOpeningApps = false;
623 }
624 }
625 }
626 boolean allTranslucentClosingApps = !mDisplayContent.mClosingApps.isEmpty();
627 for (int i = mDisplayContent.mClosingApps.size() - 1; i >= 0; i--) {
628 if (mDisplayContent.mClosingApps.valueAt(i).fillsParent()) {
629 allTranslucentClosingApps = false;
630 break;
631 }
632 }
633
634 if (taskOrActivity && allTranslucentClosingApps && allOpeningVisible) {
635 return TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE;
636 }
637 if (taskOrActivity && allTranslucentOpeningApps && mDisplayContent.mClosingApps.isEmpty()) {
638 return TRANSIT_TRANSLUCENT_ACTIVITY_OPEN;
639 }
640 return transit;
641 }
642
Evan Rosky7735d352019-03-18 17:27:27 -0700643 /**
644 * Identifies whether the current transition occurs within a single task or not. This is used
645 * to determine whether animations should be clipped to the task bounds instead of stack bounds.
646 */
647 @VisibleForTesting
648 boolean isTransitWithinTask(int transit, Task task) {
649 if (task == null
650 || !mDisplayContent.mChangingApps.isEmpty()) {
651 // if there is no task, then we can't constrain to the task.
652 // if anything is changing, it can animate outside its task.
653 return false;
654 }
655 if (!(transit == TRANSIT_ACTIVITY_OPEN
656 || transit == TRANSIT_ACTIVITY_CLOSE
657 || transit == TRANSIT_ACTIVITY_RELAUNCH)) {
658 // only activity-level transitions will be within-task.
659 return false;
660 }
661 // check that all components are in the task.
Garfield Tane8d84ab2019-10-11 09:49:40 -0700662 for (ActivityRecord activity : mDisplayContent.mOpeningApps) {
Evan Rosky7735d352019-03-18 17:27:27 -0700663 Task activityTask = activity.getTask();
664 if (activityTask != task) {
665 return false;
666 }
667 }
Garfield Tane8d84ab2019-10-11 09:49:40 -0700668 for (ActivityRecord activity : mDisplayContent.mClosingApps) {
Evan Rosky7735d352019-03-18 17:27:27 -0700669 if (activity.getTask() != task) {
670 return false;
671 }
672 }
673 return true;
674 }
675
Garfield Tane8d84ab2019-10-11 09:49:40 -0700676 private boolean canBeWallpaperTarget(ArraySet<ActivityRecord> apps) {
lumark588a3e82018-07-20 18:53:54 +0800677 for (int i = apps.size() - 1; i >= 0; i--) {
678 if (apps.valueAt(i).windowsCanBeWallpaperTarget()) {
679 return true;
680 }
681 }
682 return false;
683 }
684
685 /**
Garfield Tane8d84ab2019-10-11 09:49:40 -0700686 * Finds the top app in a list of apps, using its {@link ActivityRecord#getPrefixOrderIndex} to
lumark588a3e82018-07-20 18:53:54 +0800687 * compare z-order.
688 *
689 * @param apps The list of apps to search.
Issei Suzukif2f6c912019-11-08 11:24:18 +0100690 * @param ignoreInvisible If set to true, ignores apps that are not
691 * {@link ActivityRecord#isVisible}.
Garfield Tane8d84ab2019-10-11 09:49:40 -0700692 * @return The top {@link ActivityRecord}.
lumark588a3e82018-07-20 18:53:54 +0800693 */
Issei Suzukif2f6c912019-11-08 11:24:18 +0100694 private ActivityRecord getTopApp(ArraySet<ActivityRecord> apps, boolean ignoreInvisible) {
lumark588a3e82018-07-20 18:53:54 +0800695 int topPrefixOrderIndex = Integer.MIN_VALUE;
Garfield Tane8d84ab2019-10-11 09:49:40 -0700696 ActivityRecord topApp = null;
lumark588a3e82018-07-20 18:53:54 +0800697 for (int i = apps.size() - 1; i >= 0; i--) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700698 final ActivityRecord app = apps.valueAt(i);
Issei Suzukif2f6c912019-11-08 11:24:18 +0100699 if (ignoreInvisible && !app.isVisible()) {
lumark588a3e82018-07-20 18:53:54 +0800700 continue;
701 }
702 final int prefixOrderIndex = app.getPrefixOrderIndex();
703 if (prefixOrderIndex > topPrefixOrderIndex) {
704 topPrefixOrderIndex = prefixOrderIndex;
705 topApp = app;
706 }
707 }
708 return topApp;
709 }
lumark588a3e82018-07-20 18:53:54 +0800710}