blob: 9770947ff2c349d645f40fe87614f542947a4b5e [file] [log] [blame]
Winson Chunge2d72172018-01-25 17:46:20 +00001/*
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
Wale Ogunwale59507092018-10-29 09:00:30 -070017package com.android.server.wm;
Winson Chunge2d72172018-01-25 17:46:20 +000018
Jorim Jaggi54cff642018-03-15 15:51:32 +010019import static android.app.ActivityManager.START_TASK_TO_FRONT;
Winson Chunge2d72172018-01-25 17:46:20 +000020import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
Winson Chung3e2980e2018-03-29 17:28:57 -070021import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
22import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Winson Chunge2d72172018-01-25 17:46:20 +000023import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
24import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
Riddle Hsu2ca561b2019-10-08 21:58:58 +080025import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
Winson Chunge2d72172018-01-25 17:46:20 +000026import static android.view.WindowManager.TRANSIT_NONE;
Winson Chungfbbb1582018-11-13 16:09:01 -080027
Wale Ogunwale59507092018-10-29 09:00:30 -070028import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
Tracy Zhou9c675d42019-04-08 00:32:40 -070029import static com.android.server.wm.BoundsAnimationController.BOUNDS;
30import static com.android.server.wm.BoundsAnimationController.FADE_IN;
Adrian Roosb125e0b2019-10-02 14:55:14 +020031import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
Winson Chung3e2980e2018-03-29 17:28:57 -070032import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
33import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
34import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_TOP;
Winson Chunge2d72172018-01-25 17:46:20 +000035
Jorim Jaggi589c5ba2019-07-30 16:50:13 +020036import android.annotation.Nullable;
Winson Chunge2d72172018-01-25 17:46:20 +000037import android.app.ActivityOptions;
38import android.content.ComponentName;
39import android.content.Intent;
Winson Chungddf62972018-02-12 11:10:04 -080040import android.os.RemoteException;
Winson Chung584d6522018-02-07 23:57:38 +000041import android.os.Trace;
Winson Chungddf62972018-02-12 11:10:04 -080042import android.util.Slog;
Winson Chunge2d72172018-01-25 17:46:20 +000043import android.view.IRecentsAnimationRunner;
lumark588a3e82018-07-20 18:53:54 +080044
Wale Ogunwalea38654f2019-11-17 20:37:15 -080045import com.android.internal.util.function.pooled.PooledLambda;
46import com.android.internal.util.function.pooled.PooledPredicate;
Adrian Roosb125e0b2019-10-02 14:55:14 +020047import com.android.server.protolog.common.ProtoLog;
Riddle Hsufd66d4d2019-11-14 10:35:55 +080048import com.android.server.wm.ActivityMetricsLogger.LaunchingState;
Winson Chunge2d72172018-01-25 17:46:20 +000049import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
Winson Chunge2d72172018-01-25 17:46:20 +000050
51/**
52 * Manages the recents animation, including the reordering of the stacks for the transition and
53 * cleanup. See {@link com.android.server.wm.RecentsAnimationController}.
54 */
Winson Chung0f7ec962018-05-03 18:03:15 -070055class RecentsAnimation implements RecentsAnimationCallbacks,
Louis Chang677921f2019-12-06 16:44:24 +080056 DisplayContent.OnStackOrderChangedListener {
Winson Chunge2d72172018-01-25 17:46:20 +000057 private static final String TAG = RecentsAnimation.class.getSimpleName();
58
Wale Ogunwalea6191b42018-05-09 07:41:32 -070059 private final ActivityTaskManagerService mService;
Winson Chunge2d72172018-01-25 17:46:20 +000060 private final ActivityStackSupervisor mStackSupervisor;
61 private final ActivityStartController mActivityStartController;
62 private final WindowManagerService mWindowManager;
Louis Chang677921f2019-12-06 16:44:24 +080063 private final DisplayContent mDefaultDisplay;
Riddle Hsu609a8e22019-06-27 16:46:29 -060064 private final Intent mTargetIntent;
65 private final ComponentName mRecentsComponent;
66 private final int mRecentsUid;
Jorim Jaggi589c5ba2019-07-30 16:50:13 +020067 private final @Nullable WindowProcessController mCaller;
Riddle Hsu609a8e22019-06-27 16:46:29 -060068 private final int mUserId;
69 private final int mTargetActivityType;
Winson Chunge2d72172018-01-25 17:46:20 +000070
Riddle Hsu43233b72019-04-24 23:55:11 +080071 /**
72 * The activity which has been launched behind. We need to remember the activity because the
73 * target stack may have other activities, then we are able to restore the launch-behind state
74 * for the exact activity.
75 */
76 private ActivityRecord mLaunchedTargetActivity;
Winson Chung3e2980e2018-03-29 17:28:57 -070077
78 // The stack to restore the target stack behind when the animation is finished
79 private ActivityStack mRestoreTargetBehindStack;
Winson Chunge2d72172018-01-25 17:46:20 +000080
Wale Ogunwalea6191b42018-05-09 07:41:32 -070081 RecentsAnimation(ActivityTaskManagerService atm, ActivityStackSupervisor stackSupervisor,
Winson Chunge2d72172018-01-25 17:46:20 +000082 ActivityStartController activityStartController, WindowManagerService wm,
Jorim Jaggi589c5ba2019-07-30 16:50:13 +020083 Intent targetIntent, ComponentName recentsComponent, int recentsUid,
84 @Nullable WindowProcessController caller) {
Wale Ogunwalea6191b42018-05-09 07:41:32 -070085 mService = atm;
Winson Chunge2d72172018-01-25 17:46:20 +000086 mStackSupervisor = stackSupervisor;
Louis Chang149d5c82019-12-30 09:47:39 +080087 mDefaultDisplay = mService.mRootWindowContainer.getDefaultDisplay();
Winson Chunge2d72172018-01-25 17:46:20 +000088 mActivityStartController = activityStartController;
Winson Chunge2d72172018-01-25 17:46:20 +000089 mWindowManager = wm;
Riddle Hsu609a8e22019-06-27 16:46:29 -060090 mTargetIntent = targetIntent;
91 mRecentsComponent = recentsComponent;
92 mRecentsUid = recentsUid;
Jorim Jaggi589c5ba2019-07-30 16:50:13 +020093 mCaller = caller;
Riddle Hsu609a8e22019-06-27 16:46:29 -060094 mUserId = atm.getCurrentUserId();
95 mTargetActivityType = targetIntent.getComponent() != null
96 && recentsComponent.equals(targetIntent.getComponent())
97 ? ACTIVITY_TYPE_RECENTS
98 : ACTIVITY_TYPE_HOME;
Winson Chunge2d72172018-01-25 17:46:20 +000099 }
100
Riddle Hsu609a8e22019-06-27 16:46:29 -0600101 /**
102 * Starts the recents activity in background without animation if the record doesn't exist or
103 * the client isn't launched. If the recents activity is already alive, ensure its configuration
104 * is updated to the current one.
105 */
106 void preloadRecentsActivity() {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200107 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Preload recents with %s",
108 mTargetIntent);
Riddle Hsu609a8e22019-06-27 16:46:29 -0600109 ActivityStack targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
110 mTargetActivityType);
111 ActivityRecord targetActivity = getTargetActivity(targetStack);
112 if (targetActivity != null) {
Issei Suzuki1669ea42019-11-06 14:20:59 +0100113 if (targetActivity.mVisibleRequested || targetActivity.isTopRunningActivity()) {
Riddle Hsu609a8e22019-06-27 16:46:29 -0600114 // The activity is ready.
115 return;
116 }
117 if (targetActivity.attachedToProcess()) {
118 // The activity may be relaunched if it cannot handle the current configuration
119 // changes. The activity will be paused state if it is relaunched, otherwise it
120 // keeps the original stopped state.
121 targetActivity.ensureActivityConfiguration(0 /* globalChanges */,
122 false /* preserveWindow */, true /* ignoreVisibility */);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200123 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Updated config=%s",
124 targetActivity.getConfiguration());
Riddle Hsu609a8e22019-06-27 16:46:29 -0600125 }
126 } else {
127 // Create the activity record. Because the activity is invisible, this doesn't really
128 // start the client.
129 startRecentsActivityInBackground("preloadRecents");
130 targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED, mTargetActivityType);
131 targetActivity = getTargetActivity(targetStack);
132 if (targetActivity == null) {
133 Slog.w(TAG, "Cannot start " + mTargetIntent);
134 return;
135 }
136 }
137
138 if (!targetActivity.attachedToProcess()) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200139 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Real start recents");
Wale Ogunwale076c3b12019-11-20 12:17:22 -0800140 mStackSupervisor.startSpecificActivity(targetActivity, false /* andResume */,
Riddle Hsu609a8e22019-06-27 16:46:29 -0600141 false /* checkConfig */);
142 // Make sure the activity won't be involved in transition.
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800143 if (targetActivity.getDisplayContent() != null) {
144 targetActivity.getDisplayContent().mUnknownAppVisibilityController
145 .appRemovedOrHidden(targetActivity);
Riddle Hsu609a8e22019-06-27 16:46:29 -0600146 }
147 }
148
149 // Invisible activity should be stopped. If the recents activity is alive and its doesn't
150 // need to relaunch by current configuration, then it may be already in stopped state.
151 if (!targetActivity.isState(ActivityStack.ActivityState.STOPPING,
152 ActivityStack.ActivityState.STOPPED)) {
153 // Add to stopping instead of stop immediately. So the client has the chance to perform
154 // traversal in non-stopped state (ViewRootImpl.mStopped) that would initialize more
155 // things (e.g. the measure can be done earlier). The actual stop will be performed when
156 // it reports idle.
Andrii Kulian79d67982019-08-19 11:56:16 -0700157 targetActivity.addToStopping(true /* scheduleIdle */, true /* idleDelayed */,
158 "preloadRecents");
Riddle Hsu609a8e22019-06-27 16:46:29 -0600159 }
160 }
161
162 void startRecentsActivity(IRecentsAnimationRunner recentsAnimationRunner) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200163 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "startRecentsActivity(): intent=%s", mTargetIntent);
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800164 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "RecentsAnimation#startRecentsActivity");
Winson Chungddf62972018-02-12 11:10:04 -0800165
lumark588a3e82018-07-20 18:53:54 +0800166 // TODO(multi-display) currently only support recents animation in default display.
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800167 final DisplayContent dc =
Louis Chang149d5c82019-12-30 09:47:39 +0800168 mService.mRootWindowContainer.getDefaultDisplay().mDisplayContent;
Winson Chungddf62972018-02-12 11:10:04 -0800169 if (!mWindowManager.canStartRecentsAnimation()) {
170 notifyAnimationCancelBeforeStart(recentsAnimationRunner);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200171 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
172 "Can't start recents animation, nextAppTransition=%s",
173 dc.mAppTransition.getAppTransition());
Winson Chungddf62972018-02-12 11:10:04 -0800174 return;
175 }
176
Winson Chung3e2980e2018-03-29 17:28:57 -0700177 // If the activity is associated with the recents stack, then try and get that first
Winson Chung93442032018-12-04 13:24:29 -0800178 ActivityStack targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
Winson Chung3e2980e2018-03-29 17:28:57 -0700179 mTargetActivityType);
Riddle Hsu609a8e22019-06-27 16:46:29 -0600180 ActivityRecord targetActivity = getTargetActivity(targetStack);
Winson Chung3e2980e2018-03-29 17:28:57 -0700181 final boolean hasExistingActivity = targetActivity != null;
182 if (hasExistingActivity) {
Louis Chang677921f2019-12-06 16:44:24 +0800183 final DisplayContent display = targetActivity.getDisplay();
Winson Chung3e2980e2018-03-29 17:28:57 -0700184 mRestoreTargetBehindStack = display.getStackAbove(targetStack);
185 if (mRestoreTargetBehindStack == null) {
Winson Chungddf62972018-02-12 11:10:04 -0800186 notifyAnimationCancelBeforeStart(recentsAnimationRunner);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200187 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
188 "No stack above target stack=%s", targetStack);
Winson Chungddf62972018-02-12 11:10:04 -0800189 return;
190 }
191 }
192
Winson Chung3e2980e2018-03-29 17:28:57 -0700193 // Send launch hint if we are actually launching the target. If it's already visible
194 // (shouldn't happen in general) we don't need to send it.
Issei Suzuki1669ea42019-11-06 14:20:59 +0100195 if (targetActivity == null || !targetActivity.mVisibleRequested) {
Louis Chang149d5c82019-12-30 09:47:39 +0800196 mService.mRootWindowContainer.sendPowerHintForLaunchStartIfNeeded(
Wale Ogunwaled32da472018-11-16 07:19:28 -0800197 true /* forceSend */, targetActivity);
Jorim Jaggiac960522018-03-22 23:20:36 +0100198 }
199
Riddle Hsufd66d4d2019-11-14 10:35:55 +0800200 final LaunchingState launchingState =
201 mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching(mTargetIntent);
Jorim Jaggi54cff642018-03-15 15:51:32 +0100202
Jorim Jaggi589c5ba2019-07-30 16:50:13 +0200203 if (mCaller != null) {
204 mCaller.setRunningRecentsAnimation(true);
205 }
Jorim Jaggibc2aabe2018-03-08 17:27:43 +0100206
Riddle Hsua0022cd2019-09-09 21:12:41 +0800207 mService.deferWindowLayout();
Winson Chung1e6d4a92018-01-26 10:04:20 -0800208 try {
Winson Chung3e2980e2018-03-29 17:28:57 -0700209 if (hasExistingActivity) {
210 // Move the recents activity into place for the animation if it is not top most
Winson Chung0f7ec962018-05-03 18:03:15 -0700211 mDefaultDisplay.moveStackBehindBottomMostVisibleStack(targetStack);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200212 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Moved stack=%s behind stack=%s",
213 targetStack, mDefaultDisplay.getStackAbove(targetStack));
Winson Chung00a09692018-04-19 16:14:09 -0700214
215 // If there are multiple tasks in the target stack (ie. the home stack, with 3p
216 // and default launchers coexisting), then move the task to the top as a part of
217 // moving the stack to the front
Louis Changcdec0802019-11-11 11:45:07 +0800218 final Task task = targetActivity.getTask();
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900219 if (targetStack.getTopMostTask() != task) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700220 targetStack.positionChildAtTop(task);
Winson Chung00a09692018-04-19 16:14:09 -0700221 }
Winson Chungddf62972018-02-12 11:10:04 -0800222 } else {
Winson Chung93442032018-12-04 13:24:29 -0800223 // No recents activity, create the new recents activity bottom most
Riddle Hsu609a8e22019-06-27 16:46:29 -0600224 startRecentsActivityInBackground("startRecentsActivity_noTargetActivity");
Winson Chung93442032018-12-04 13:24:29 -0800225
226 // Move the recents activity into place for the animation
Winson Chung2bc60c02019-05-16 17:36:05 -0700227 targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
228 mTargetActivityType);
Riddle Hsu609a8e22019-06-27 16:46:29 -0600229 targetActivity = getTargetActivity(targetStack);
Winson Chung93442032018-12-04 13:24:29 -0800230 mDefaultDisplay.moveStackBehindBottomMostVisibleStack(targetStack);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200231 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Moved stack=%s behind stack=%s",
232 targetStack, mDefaultDisplay.getStackAbove(targetStack));
Winson Chung93442032018-12-04 13:24:29 -0800233
Winson Chung1e6d4a92018-01-26 10:04:20 -0800234 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
Winson Chungba40d3a2018-05-16 09:40:16 -0700235 mWindowManager.executeAppTransition();
Winson Chunge2d72172018-01-25 17:46:20 +0000236
Winson Chung1e6d4a92018-01-26 10:04:20 -0800237 // TODO: Maybe wait for app to draw in this particular case?
Winson Chungc6c3f852018-04-09 15:41:03 -0700238
Adrian Roosb125e0b2019-10-02 14:55:14 +0200239 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Started intent=%s", mTargetIntent);
Winson Chung1e6d4a92018-01-26 10:04:20 -0800240 }
Winson Chunge2d72172018-01-25 17:46:20 +0000241
Winson Chung3e2980e2018-03-29 17:28:57 -0700242 // Mark the target activity as launch-behind to bump its visibility for the
Winson Chung1e6d4a92018-01-26 10:04:20 -0800243 // duration of the gesture that is driven by the recents component
Winson Chung3e2980e2018-03-29 17:28:57 -0700244 targetActivity.mLaunchTaskBehind = true;
Riddle Hsu43233b72019-04-24 23:55:11 +0800245 mLaunchedTargetActivity = targetActivity;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800246
247 // Fetch all the surface controls and pass them to the client to get the animation
Winson Chung65c5f992018-04-20 14:58:57 -0700248 // started. Cancel any existing recents animation running synchronously (do not hold the
249 // WM lock)
Wale Ogunwalea441b922019-06-27 19:21:44 -0700250 mWindowManager.cancelRecentsAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION,
Winson Chungc6c3f852018-04-09 15:41:03 -0700251 "startRecentsActivity");
Winson Chung3e2980e2018-03-29 17:28:57 -0700252 mWindowManager.initializeRecentsAnimation(mTargetActivityType, recentsAnimationRunner,
Louis Chang677921f2019-12-06 16:44:24 +0800253 this, mDefaultDisplay.getDisplayId(),
wilsonshih417b70c12019-10-16 16:12:02 +0800254 mStackSupervisor.mRecentTasks.getRecentTaskIds(), targetActivity);
Winson Chung1e6d4a92018-01-26 10:04:20 -0800255
256 // If we updated the launch-behind state, update the visibility of the activities after
257 // we fetch the visible tasks to be controlled by the animation
Louis Chang149d5c82019-12-30 09:47:39 +0800258 mService.mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
Jorim Jaggi54cff642018-03-15 15:51:32 +0100259
Riddle Hsufd66d4d2019-11-14 10:35:55 +0800260 mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState,
261 START_TASK_TO_FRONT, targetActivity);
Winson Chung0f7ec962018-05-03 18:03:15 -0700262
263 // Register for stack order changes
264 mDefaultDisplay.registerStackOrderChangedListener(this);
Winson Chungc6c3f852018-04-09 15:41:03 -0700265 } catch (Exception e) {
266 Slog.e(TAG, "Failed to start recents activity", e);
267 throw e;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800268 } finally {
Riddle Hsua0022cd2019-09-09 21:12:41 +0800269 mService.continueWindowLayout();
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800270 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Winson Chunge2d72172018-01-25 17:46:20 +0000271 }
Winson Chunge2d72172018-01-25 17:46:20 +0000272 }
273
Tracy Zhou9c675d42019-04-08 00:32:40 -0700274 private void finishAnimation(@RecentsAnimationController.ReorderMode int reorderMode,
275 boolean sendUserLeaveHint) {
Wale Ogunwalea6191b42018-05-09 07:41:32 -0700276 synchronized (mService.mGlobalLock) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200277 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
278 "onAnimationFinished(): controller=%s reorderMode=%d",
279 mWindowManager.getRecentsAnimationController(), reorderMode);
Winson Chungf9930162018-02-12 14:51:46 -0800280
Winson Chung0f7ec962018-05-03 18:03:15 -0700281 // Unregister for stack order changes
282 mDefaultDisplay.unregisterStackOrderChangedListener(this);
283
Riddle Hsu0e591722019-05-03 22:22:36 +0800284 final RecentsAnimationController controller =
285 mWindowManager.getRecentsAnimationController();
286 if (controller == null) return;
Winson Chunge2d72172018-01-25 17:46:20 +0000287
Winson Chung3e2980e2018-03-29 17:28:57 -0700288 // Just to be sure end the launch hint in case the target activity was never launched.
289 // However, if we're keeping the activity and making it visible, we can leave it on.
290 if (reorderMode != REORDER_KEEP_IN_PLACE) {
Louis Chang149d5c82019-12-30 09:47:39 +0800291 mService.mRootWindowContainer.sendPowerHintForLaunchEndIfNeeded();
Jorim Jaggiac960522018-03-22 23:20:36 +0100292 }
293
Winson Chung751579d2019-05-28 14:09:09 -0700294 // Once the target is shown, prevent spurious background app switches
295 if (reorderMode == REORDER_MOVE_TO_TOP) {
296 mService.stopAppSwitches();
297 }
298
Jorim Jaggi589c5ba2019-07-30 16:50:13 +0200299 if (mCaller != null) {
300 mCaller.setRunningRecentsAnimation(false);
301 }
Jorim Jaggibc2aabe2018-03-08 17:27:43 +0100302
Winson Chunge2d72172018-01-25 17:46:20 +0000303 mWindowManager.inSurfaceTransaction(() -> {
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800304 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
Winson Chung584d6522018-02-07 23:57:38 +0000305 "RecentsAnimation#onAnimationFinished_inSurfaceTransaction");
Riddle Hsua0022cd2019-09-09 21:12:41 +0800306 mService.deferWindowLayout();
Winson Chung1e6d4a92018-01-26 10:04:20 -0800307 try {
Winson Chung6a38fca2018-03-28 17:57:09 -0700308 mWindowManager.cleanupRecentsAnimation(reorderMode);
Winson Chunge2d72172018-01-25 17:46:20 +0000309
Winson Chung3e2980e2018-03-29 17:28:57 -0700310 final ActivityStack targetStack = mDefaultDisplay.getStack(
311 WINDOWING_MODE_UNDEFINED, mTargetActivityType);
Riddle Hsu43233b72019-04-24 23:55:11 +0800312 // Prefer to use the original target activity instead of top activity because
313 // we may have moved another task to top (starting 3p launcher).
Winson Chung82389a92018-05-03 10:43:51 -0700314 final ActivityRecord targetActivity = targetStack != null
Riddle Hsu43233b72019-04-24 23:55:11 +0800315 ? targetStack.isInStackLocked(mLaunchedTargetActivity)
Winson Chung82389a92018-05-03 10:43:51 -0700316 : null;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200317 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
318 "onAnimationFinished(): targetStack=%s targetActivity=%s "
319 + "mRestoreTargetBehindStack=%s",
320 targetStack, targetActivity, mRestoreTargetBehindStack);
Winson Chung3e2980e2018-03-29 17:28:57 -0700321 if (targetActivity == null) {
Winson Chung1e6d4a92018-01-26 10:04:20 -0800322 return;
323 }
324
325 // Restore the launched-behind state
Winson Chung3e2980e2018-03-29 17:28:57 -0700326 targetActivity.mLaunchTaskBehind = false;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800327
Winson Chung3e2980e2018-03-29 17:28:57 -0700328 if (reorderMode == REORDER_MOVE_TO_TOP) {
329 // Bring the target stack to the front
330 mStackSupervisor.mNoAnimActivities.add(targetActivity);
Tracy Zhou9c675d42019-04-08 00:32:40 -0700331
332 if (sendUserLeaveHint) {
333 // Setting this allows the previous app to PiP.
334 mStackSupervisor.mUserLeaving = true;
Louis Changcdec0802019-11-11 11:45:07 +0800335 targetStack.moveTaskToFrontLocked(targetActivity.getTask(),
Tracy Zhou9c675d42019-04-08 00:32:40 -0700336 true /* noAnimation */, null /* activityOptions */,
337 targetActivity.appTimeTracker,
338 "RecentsAnimation.onAnimationFinished()");
339 } else {
340 targetStack.moveToFront("RecentsAnimation.onAnimationFinished()");
341 }
342
Adrian Roosb125e0b2019-10-02 14:55:14 +0200343 if (WM_DEBUG_RECENTS_ANIMATIONS.isLogToAny()) {
Winson Chungc6c3f852018-04-09 15:41:03 -0700344 final ActivityStack topStack = getTopNonAlwaysOnTopStack();
345 if (topStack != targetStack) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200346 ProtoLog.w(WM_DEBUG_RECENTS_ANIMATIONS,
347 "Expected target stack=%s"
348 + " to be top most but found stack=%s",
349 targetStack, topStack);
Winson Chungc6c3f852018-04-09 15:41:03 -0700350 }
351 }
Winson Chung3e2980e2018-03-29 17:28:57 -0700352 } else if (reorderMode == REORDER_MOVE_TO_ORIGINAL_POSITION){
353 // Restore the target stack to its previous position
Louis Chang677921f2019-12-06 16:44:24 +0800354 final DisplayContent display = targetActivity.getDisplay();
Winson Chung3e2980e2018-03-29 17:28:57 -0700355 display.moveStackBehindStack(targetStack, mRestoreTargetBehindStack);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200356 if (WM_DEBUG_RECENTS_ANIMATIONS.isLogToAny()) {
Winson Chungc6c3f852018-04-09 15:41:03 -0700357 final ActivityStack aboveTargetStack =
358 mDefaultDisplay.getStackAbove(targetStack);
359 if (mRestoreTargetBehindStack != null
360 && aboveTargetStack != mRestoreTargetBehindStack) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200361 ProtoLog.w(WM_DEBUG_RECENTS_ANIMATIONS,
362 "Expected target stack=%s to restored behind stack=%s but"
363 + " it is behind stack=%s",
364 targetStack, mRestoreTargetBehindStack, aboveTargetStack);
Winson Chungc6c3f852018-04-09 15:41:03 -0700365 }
366 }
Winson Chung6a38fca2018-03-28 17:57:09 -0700367 } else {
Riddle Hsu0e591722019-05-03 22:22:36 +0800368 // If there is no recents screenshot animation, we can update the visibility
369 // of target stack immediately because it is visually invisible and the
370 // launch-behind state is restored. That also prevents the next transition
371 // type being disturbed if the visibility is updated after setting the next
372 // transition (the target activity will be one of closing apps).
Winson Chung7a545ae2019-07-16 14:52:13 -0700373 if (!controller.shouldDeferCancelWithScreenshot()
Riddle Hsu0e591722019-05-03 22:22:36 +0800374 && !targetStack.isFocusedStackOnDisplay()) {
Wale Ogunwale076c3b12019-11-20 12:17:22 -0800375 targetStack.ensureActivitiesVisible(null /* starting */,
Riddle Hsu0e591722019-05-03 22:22:36 +0800376 0 /* starting */, false /* preserveWindows */);
377 }
Winson Chung3e2980e2018-03-29 17:28:57 -0700378 // Keep target stack in place, nothing changes, so ignore the transition
379 // logic below
Winson Chung6a38fca2018-03-28 17:57:09 -0700380 return;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800381 }
382
383 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
Louis Chang149d5c82019-12-30 09:47:39 +0800384 mService.mRootWindowContainer.ensureActivitiesVisible(null, 0, false);
385 mService.mRootWindowContainer.resumeFocusedStacksTopActivities();
Winson Chung1e6d4a92018-01-26 10:04:20 -0800386
387 // No reason to wait for the pausing activity in this case, as the hiding of
388 // surfaces needs to be done immediately.
389 mWindowManager.executeAppTransition();
Winson Chungf557c3b2018-03-16 10:55:20 -0700390
Evan Rosky0037e5f2019-11-05 10:26:24 -0800391 if (targetStack.getTile() != null) {
392 // Client state may have changed during the recents animation, so force
393 // send task info so the client can synchronize its state.
394 mService.mTaskOrganizerController.dispatchTaskInfoChanged(
395 targetStack.mTile, true /* force */);
396 }
Winson Chungc6c3f852018-04-09 15:41:03 -0700397 } catch (Exception e) {
398 Slog.e(TAG, "Failed to clean up recents activity", e);
399 throw e;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800400 } finally {
Riddle Hsua0022cd2019-09-09 21:12:41 +0800401 mService.continueWindowLayout();
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800402 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Winson Chunge2d72172018-01-25 17:46:20 +0000403 }
Winson Chunge2d72172018-01-25 17:46:20 +0000404 });
405 }
406 }
Winson Chungddf62972018-02-12 11:10:04 -0800407
Winson Chung65c5f992018-04-20 14:58:57 -0700408 @Override
409 public void onAnimationFinished(@RecentsAnimationController.ReorderMode int reorderMode,
Wale Ogunwalea441b922019-06-27 19:21:44 -0700410 boolean sendUserLeaveHint) {
411 finishAnimation(reorderMode, sendUserLeaveHint);
Winson Chung65c5f992018-04-20 14:58:57 -0700412 }
413
Winson Chung0f7ec962018-05-03 18:03:15 -0700414 @Override
Winson Chung65d66d32018-12-13 17:48:39 -0800415 public void onStackOrderChanged(ActivityStack stack) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200416 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "onStackOrderChanged(): stack=%s", stack);
Winson Chung65d66d32018-12-13 17:48:39 -0800417 if (mDefaultDisplay.getIndexOf(stack) == -1 || !stack.shouldBeVisible(null)) {
418 // The stack is not visible, so ignore this change
419 return;
420 }
lumark54284462019-03-05 20:44:27 +0800421 final RecentsAnimationController controller =
422 mWindowManager.getRecentsAnimationController();
lumarkf6f34942019-04-29 16:56:50 +0800423 if (controller == null) {
424 return;
425 }
426
Tracy Zhou9c675d42019-04-08 00:32:40 -0700427 final DisplayContent dc =
Louis Chang149d5c82019-12-30 09:47:39 +0800428 mService.mRootWindowContainer.getDefaultDisplay().mDisplayContent;
Tracy Zhou9c675d42019-04-08 00:32:40 -0700429 dc.mBoundsAnimationController.setAnimationType(
Winson Chung7a545ae2019-07-16 14:52:13 -0700430 controller.shouldDeferCancelUntilNextTransition() ? FADE_IN : BOUNDS);
Winson Chung65d66d32018-12-13 17:48:39 -0800431
Winson Chung7a545ae2019-07-16 14:52:13 -0700432 // We defer canceling the recents animation until the next app transition in the following
433 // cases:
434 // 1) The next launching task is not being animated by the recents animation
lumark54284462019-03-05 20:44:27 +0800435 // 2) The next task is home activity. (i.e. pressing home key to back home in recents).
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900436 if ((!controller.isAnimatingTask(stack.getTopMostTask())
Wale Ogunwale21e06482019-11-18 05:14:15 -0800437 || controller.isTargetApp(stack.getTopNonFinishingActivity()))
Winson Chung7a545ae2019-07-16 14:52:13 -0700438 && controller.shouldDeferCancelUntilNextTransition()) {
439 // Always prepare an app transition since we rely on the transition callbacks to cleanup
440 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
441 controller.setCancelOnNextTransitionStart();
lumark54284462019-03-05 20:44:27 +0800442 } else {
443 // Just cancel directly to unleash from launcher when the next launching task is the
444 // current top task.
Wale Ogunwalea441b922019-06-27 19:21:44 -0700445 mWindowManager.cancelRecentsAnimation(REORDER_KEEP_IN_PLACE, "stackOrderChanged");
lumark54284462019-03-05 20:44:27 +0800446 }
Winson Chung0f7ec962018-05-03 18:03:15 -0700447 }
448
Riddle Hsu609a8e22019-06-27 16:46:29 -0600449 private void startRecentsActivityInBackground(String reason) {
450 final ActivityOptions options = ActivityOptions.makeBasic();
451 options.setLaunchActivityType(mTargetActivityType);
452 options.setAvoidMoveToFront();
453 mTargetIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NO_ANIMATION);
454
455 mActivityStartController
456 .obtainStarter(mTargetIntent, reason)
457 .setCallingUid(mRecentsUid)
458 .setCallingPackage(mRecentsComponent.getPackageName())
459 .setActivityOptions(new SafeActivityOptions(options))
Louis Chang54fbb052019-10-16 17:10:17 +0800460 .setUserId(mUserId)
Riddle Hsu609a8e22019-06-27 16:46:29 -0600461 .execute();
462 }
463
Winson Chungddf62972018-02-12 11:10:04 -0800464 /**
465 * Called only when the animation should be canceled prior to starting.
466 */
Jorim Jaggi589c5ba2019-07-30 16:50:13 +0200467 static void notifyAnimationCancelBeforeStart(IRecentsAnimationRunner recentsAnimationRunner) {
Winson Chungddf62972018-02-12 11:10:04 -0800468 try {
Tracy Zhou8089ffa2019-07-30 17:30:43 -0700469 recentsAnimationRunner.onAnimationCanceled(null /* taskSnapshot */);
Winson Chungddf62972018-02-12 11:10:04 -0800470 } catch (RemoteException e) {
471 Slog.e(TAG, "Failed to cancel recents animation before start", e);
472 }
473 }
Winson Chungc6c3f852018-04-09 15:41:03 -0700474
475 /**
476 * @return The top stack that is not always-on-top.
477 */
478 private ActivityStack getTopNonAlwaysOnTopStack() {
Louis Chang2453d062019-11-19 22:30:48 +0800479 for (int i = mDefaultDisplay.getStackCount() - 1; i >= 0; i--) {
480 final ActivityStack s = mDefaultDisplay.getStackAt(i);
Winson Chungc6c3f852018-04-09 15:41:03 -0700481 if (s.getWindowConfiguration().isAlwaysOnTop()) {
482 continue;
483 }
484 return s;
485 }
486 return null;
487 }
Winson Chung00a09692018-04-19 16:14:09 -0700488
489 /**
490 * @return the top activity in the {@param targetStack} matching the {@param component}, or just
491 * the top activity of the top task if no task matches the component.
492 */
Riddle Hsu609a8e22019-06-27 16:46:29 -0600493 private ActivityRecord getTargetActivity(ActivityStack targetStack) {
Winson Chung00a09692018-04-19 16:14:09 -0700494 if (targetStack == null) {
495 return null;
496 }
497
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800498 final PooledPredicate p = PooledLambda.obtainPredicate(RecentsAnimation::matchesTarget,
499 this, PooledLambda.__(Task.class));
500 final Task task = targetStack.getTask(p);
501 p.recycle();
502 return task != null ? task.getTopNonFinishingActivity() : null;
503 }
504
505 private boolean matchesTarget(Task task) {
506 return task.mUserId == mUserId
507 && task.getBaseIntent().getComponent().equals(mTargetIntent.getComponent());
Winson Chung00a09692018-04-19 16:14:09 -0700508 }
Winson Chunge2d72172018-01-25 17:46:20 +0000509}