blob: 0a9878dd660bb794cd251b08dd69d82595c08a96 [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;
Adrian Roosb125e0b2019-10-02 14:55:14 +020029import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
Winson Chung3e2980e2018-03-29 17:28:57 -070030import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
31import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
32import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_TOP;
Andrii Kulian86d676c2020-03-27 19:34:54 -070033import static com.android.server.wm.TaskDisplayArea.getStackAbove;
Winson Chunge2d72172018-01-25 17:46:20 +000034
Jorim Jaggi589c5ba2019-07-30 16:50:13 +020035import android.annotation.Nullable;
Winson Chunge2d72172018-01-25 17:46:20 +000036import android.app.ActivityOptions;
37import android.content.ComponentName;
38import android.content.Intent;
Winson Chungddf62972018-02-12 11:10:04 -080039import android.os.RemoteException;
Winson Chung584d6522018-02-07 23:57:38 +000040import android.os.Trace;
Winson Chungddf62972018-02-12 11:10:04 -080041import android.util.Slog;
Winson Chunge2d72172018-01-25 17:46:20 +000042import android.view.IRecentsAnimationRunner;
lumark588a3e82018-07-20 18:53:54 +080043
Wale Ogunwalea38654f2019-11-17 20:37:15 -080044import com.android.internal.util.function.pooled.PooledLambda;
45import com.android.internal.util.function.pooled.PooledPredicate;
Adrian Roosb125e0b2019-10-02 14:55:14 +020046import com.android.server.protolog.common.ProtoLog;
Riddle Hsufd66d4d2019-11-14 10:35:55 +080047import com.android.server.wm.ActivityMetricsLogger.LaunchingState;
Winson Chunge2d72172018-01-25 17:46:20 +000048import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
Winson Chunge2d72172018-01-25 17:46:20 +000049
50/**
51 * Manages the recents animation, including the reordering of the stacks for the transition and
52 * cleanup. See {@link com.android.server.wm.RecentsAnimationController}.
53 */
Winson Chung0f7ec962018-05-03 18:03:15 -070054class RecentsAnimation implements RecentsAnimationCallbacks,
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -070055 TaskDisplayArea.OnStackOrderChangedListener {
Winson Chunge2d72172018-01-25 17:46:20 +000056 private static final String TAG = RecentsAnimation.class.getSimpleName();
57
Wale Ogunwalea6191b42018-05-09 07:41:32 -070058 private final ActivityTaskManagerService mService;
Winson Chunge2d72172018-01-25 17:46:20 +000059 private final ActivityStackSupervisor mStackSupervisor;
60 private final ActivityStartController mActivityStartController;
61 private final WindowManagerService mWindowManager;
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -070062 private final TaskDisplayArea mDefaultTaskDisplayArea;
Riddle Hsu609a8e22019-06-27 16:46:29 -060063 private final Intent mTargetIntent;
64 private final ComponentName mRecentsComponent;
Philip P. Moltmannee295092020-02-10 08:46:26 -080065 private final @Nullable String mRecentsFeatureId;
Riddle Hsu609a8e22019-06-27 16:46:29 -060066 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,
Philip P. Moltmannee295092020-02-10 08:46:26 -080083 Intent targetIntent, ComponentName recentsComponent, @Nullable String recentsFeatureId,
84 int recentsUid, @Nullable WindowProcessController caller) {
Wale Ogunwalea6191b42018-05-09 07:41:32 -070085 mService = atm;
Winson Chunge2d72172018-01-25 17:46:20 +000086 mStackSupervisor = stackSupervisor;
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -070087 mDefaultTaskDisplayArea = mService.mRootWindowContainer.getDefaultTaskDisplayArea();
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;
Philip P. Moltmannee295092020-02-10 08:46:26 -080092 mRecentsFeatureId = recentsFeatureId;
Riddle Hsu609a8e22019-06-27 16:46:29 -060093 mRecentsUid = recentsUid;
Jorim Jaggi589c5ba2019-07-30 16:50:13 +020094 mCaller = caller;
Riddle Hsu609a8e22019-06-27 16:46:29 -060095 mUserId = atm.getCurrentUserId();
96 mTargetActivityType = targetIntent.getComponent() != null
97 && recentsComponent.equals(targetIntent.getComponent())
98 ? ACTIVITY_TYPE_RECENTS
99 : ACTIVITY_TYPE_HOME;
Winson Chunge2d72172018-01-25 17:46:20 +0000100 }
101
Riddle Hsu609a8e22019-06-27 16:46:29 -0600102 /**
103 * Starts the recents activity in background without animation if the record doesn't exist or
104 * the client isn't launched. If the recents activity is already alive, ensure its configuration
105 * is updated to the current one.
106 */
107 void preloadRecentsActivity() {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200108 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Preload recents with %s",
109 mTargetIntent);
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700110 ActivityStack targetStack = mDefaultTaskDisplayArea.getStack(WINDOWING_MODE_UNDEFINED,
Riddle Hsu609a8e22019-06-27 16:46:29 -0600111 mTargetActivityType);
112 ActivityRecord targetActivity = getTargetActivity(targetStack);
113 if (targetActivity != null) {
Issei Suzuki1669ea42019-11-06 14:20:59 +0100114 if (targetActivity.mVisibleRequested || targetActivity.isTopRunningActivity()) {
Riddle Hsu609a8e22019-06-27 16:46:29 -0600115 // The activity is ready.
116 return;
117 }
118 if (targetActivity.attachedToProcess()) {
119 // The activity may be relaunched if it cannot handle the current configuration
120 // changes. The activity will be paused state if it is relaunched, otherwise it
121 // keeps the original stopped state.
122 targetActivity.ensureActivityConfiguration(0 /* globalChanges */,
123 false /* preserveWindow */, true /* ignoreVisibility */);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200124 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Updated config=%s",
125 targetActivity.getConfiguration());
Riddle Hsu609a8e22019-06-27 16:46:29 -0600126 }
127 } else {
128 // Create the activity record. Because the activity is invisible, this doesn't really
129 // start the client.
130 startRecentsActivityInBackground("preloadRecents");
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700131 targetStack = mDefaultTaskDisplayArea.getStack(WINDOWING_MODE_UNDEFINED,
132 mTargetActivityType);
Riddle Hsu609a8e22019-06-27 16:46:29 -0600133 targetActivity = getTargetActivity(targetStack);
134 if (targetActivity == null) {
135 Slog.w(TAG, "Cannot start " + mTargetIntent);
136 return;
137 }
138 }
139
140 if (!targetActivity.attachedToProcess()) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200141 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Real start recents");
Wale Ogunwale076c3b12019-11-20 12:17:22 -0800142 mStackSupervisor.startSpecificActivity(targetActivity, false /* andResume */,
Riddle Hsu609a8e22019-06-27 16:46:29 -0600143 false /* checkConfig */);
144 // Make sure the activity won't be involved in transition.
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800145 if (targetActivity.getDisplayContent() != null) {
146 targetActivity.getDisplayContent().mUnknownAppVisibilityController
147 .appRemovedOrHidden(targetActivity);
Riddle Hsu609a8e22019-06-27 16:46:29 -0600148 }
149 }
150
151 // Invisible activity should be stopped. If the recents activity is alive and its doesn't
152 // need to relaunch by current configuration, then it may be already in stopped state.
153 if (!targetActivity.isState(ActivityStack.ActivityState.STOPPING,
154 ActivityStack.ActivityState.STOPPED)) {
155 // Add to stopping instead of stop immediately. So the client has the chance to perform
156 // traversal in non-stopped state (ViewRootImpl.mStopped) that would initialize more
157 // things (e.g. the measure can be done earlier). The actual stop will be performed when
158 // it reports idle.
Andrii Kulian79d67982019-08-19 11:56:16 -0700159 targetActivity.addToStopping(true /* scheduleIdle */, true /* idleDelayed */,
160 "preloadRecents");
Riddle Hsu609a8e22019-06-27 16:46:29 -0600161 }
162 }
163
164 void startRecentsActivity(IRecentsAnimationRunner recentsAnimationRunner) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200165 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "startRecentsActivity(): intent=%s", mTargetIntent);
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800166 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "RecentsAnimation#startRecentsActivity");
Winson Chungddf62972018-02-12 11:10:04 -0800167
lumark588a3e82018-07-20 18:53:54 +0800168 // TODO(multi-display) currently only support recents animation in default display.
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800169 final DisplayContent dc =
Louis Chang149d5c82019-12-30 09:47:39 +0800170 mService.mRootWindowContainer.getDefaultDisplay().mDisplayContent;
Winson Chungddf62972018-02-12 11:10:04 -0800171 if (!mWindowManager.canStartRecentsAnimation()) {
172 notifyAnimationCancelBeforeStart(recentsAnimationRunner);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200173 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
174 "Can't start recents animation, nextAppTransition=%s",
175 dc.mAppTransition.getAppTransition());
Winson Chungddf62972018-02-12 11:10:04 -0800176 return;
177 }
178
Winson Chung3e2980e2018-03-29 17:28:57 -0700179 // If the activity is associated with the recents stack, then try and get that first
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700180 ActivityStack targetStack = mDefaultTaskDisplayArea.getStack(WINDOWING_MODE_UNDEFINED,
Winson Chung3e2980e2018-03-29 17:28:57 -0700181 mTargetActivityType);
Riddle Hsu609a8e22019-06-27 16:46:29 -0600182 ActivityRecord targetActivity = getTargetActivity(targetStack);
Winson Chung3e2980e2018-03-29 17:28:57 -0700183 final boolean hasExistingActivity = targetActivity != null;
184 if (hasExistingActivity) {
Andrii Kulian86d676c2020-03-27 19:34:54 -0700185 mRestoreTargetBehindStack = getStackAbove(targetStack);
Winson Chung3e2980e2018-03-29 17:28:57 -0700186 if (mRestoreTargetBehindStack == null) {
Winson Chungddf62972018-02-12 11:10:04 -0800187 notifyAnimationCancelBeforeStart(recentsAnimationRunner);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200188 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
189 "No stack above target stack=%s", targetStack);
Winson Chungddf62972018-02-12 11:10:04 -0800190 return;
191 }
192 }
193
Winson Chung3e2980e2018-03-29 17:28:57 -0700194 // Send launch hint if we are actually launching the target. If it's already visible
195 // (shouldn't happen in general) we don't need to send it.
Issei Suzuki1669ea42019-11-06 14:20:59 +0100196 if (targetActivity == null || !targetActivity.mVisibleRequested) {
Louis Chang149d5c82019-12-30 09:47:39 +0800197 mService.mRootWindowContainer.sendPowerHintForLaunchStartIfNeeded(
Wale Ogunwaled32da472018-11-16 07:19:28 -0800198 true /* forceSend */, targetActivity);
Jorim Jaggiac960522018-03-22 23:20:36 +0100199 }
200
Riddle Hsufd66d4d2019-11-14 10:35:55 +0800201 final LaunchingState launchingState =
202 mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching(mTargetIntent);
Jorim Jaggi54cff642018-03-15 15:51:32 +0100203
Jorim Jaggi589c5ba2019-07-30 16:50:13 +0200204 if (mCaller != null) {
205 mCaller.setRunningRecentsAnimation(true);
206 }
Jorim Jaggibc2aabe2018-03-08 17:27:43 +0100207
Riddle Hsua0022cd2019-09-09 21:12:41 +0800208 mService.deferWindowLayout();
Winson Chung1e6d4a92018-01-26 10:04:20 -0800209 try {
Winson Chung3e2980e2018-03-29 17:28:57 -0700210 if (hasExistingActivity) {
211 // Move the recents activity into place for the animation if it is not top most
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700212 mDefaultTaskDisplayArea.moveStackBehindBottomMostVisibleStack(targetStack);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200213 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Moved stack=%s behind stack=%s",
Andrii Kulian86d676c2020-03-27 19:34:54 -0700214 targetStack, getStackAbove(targetStack));
Winson Chung00a09692018-04-19 16:14:09 -0700215
216 // If there are multiple tasks in the target stack (ie. the home stack, with 3p
217 // and default launchers coexisting), then move the task to the top as a part of
218 // moving the stack to the front
Louis Changcdec0802019-11-11 11:45:07 +0800219 final Task task = targetActivity.getTask();
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900220 if (targetStack.getTopMostTask() != task) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700221 targetStack.positionChildAtTop(task);
Winson Chung00a09692018-04-19 16:14:09 -0700222 }
Winson Chungddf62972018-02-12 11:10:04 -0800223 } else {
Winson Chung93442032018-12-04 13:24:29 -0800224 // No recents activity, create the new recents activity bottom most
Riddle Hsu609a8e22019-06-27 16:46:29 -0600225 startRecentsActivityInBackground("startRecentsActivity_noTargetActivity");
Winson Chung93442032018-12-04 13:24:29 -0800226
227 // Move the recents activity into place for the animation
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700228 targetStack = mDefaultTaskDisplayArea.getStack(WINDOWING_MODE_UNDEFINED,
Winson Chung2bc60c02019-05-16 17:36:05 -0700229 mTargetActivityType);
Riddle Hsu609a8e22019-06-27 16:46:29 -0600230 targetActivity = getTargetActivity(targetStack);
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700231 mDefaultTaskDisplayArea.moveStackBehindBottomMostVisibleStack(targetStack);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200232 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Moved stack=%s behind stack=%s",
Andrii Kulian86d676c2020-03-27 19:34:54 -0700233 targetStack, getStackAbove(targetStack));
Winson Chung93442032018-12-04 13:24:29 -0800234
Winson Chung1e6d4a92018-01-26 10:04:20 -0800235 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
Winson Chungba40d3a2018-05-16 09:40:16 -0700236 mWindowManager.executeAppTransition();
Winson Chunge2d72172018-01-25 17:46:20 +0000237
Winson Chung1e6d4a92018-01-26 10:04:20 -0800238 // TODO: Maybe wait for app to draw in this particular case?
Winson Chungc6c3f852018-04-09 15:41:03 -0700239
Adrian Roosb125e0b2019-10-02 14:55:14 +0200240 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Started intent=%s", mTargetIntent);
Winson Chung1e6d4a92018-01-26 10:04:20 -0800241 }
Winson Chunge2d72172018-01-25 17:46:20 +0000242
Winson Chung3e2980e2018-03-29 17:28:57 -0700243 // Mark the target activity as launch-behind to bump its visibility for the
Winson Chung1e6d4a92018-01-26 10:04:20 -0800244 // duration of the gesture that is driven by the recents component
Winson Chung3e2980e2018-03-29 17:28:57 -0700245 targetActivity.mLaunchTaskBehind = true;
Riddle Hsu43233b72019-04-24 23:55:11 +0800246 mLaunchedTargetActivity = targetActivity;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800247
248 // Fetch all the surface controls and pass them to the client to get the animation
Winson Chung65c5f992018-04-20 14:58:57 -0700249 // started. Cancel any existing recents animation running synchronously (do not hold the
250 // WM lock)
Wale Ogunwalea441b922019-06-27 19:21:44 -0700251 mWindowManager.cancelRecentsAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION,
Winson Chungc6c3f852018-04-09 15:41:03 -0700252 "startRecentsActivity");
Winson Chung3e2980e2018-03-29 17:28:57 -0700253 mWindowManager.initializeRecentsAnimation(mTargetActivityType, recentsAnimationRunner,
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700254 this, mDefaultTaskDisplayArea.getDisplayId(),
wilsonshih417b70c12019-10-16 16:12:02 +0800255 mStackSupervisor.mRecentTasks.getRecentTaskIds(), targetActivity);
Winson Chung1e6d4a92018-01-26 10:04:20 -0800256
257 // If we updated the launch-behind state, update the visibility of the activities after
258 // we fetch the visible tasks to be controlled by the animation
Louis Chang149d5c82019-12-30 09:47:39 +0800259 mService.mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
Jorim Jaggi54cff642018-03-15 15:51:32 +0100260
Riddle Hsufd66d4d2019-11-14 10:35:55 +0800261 mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState,
262 START_TASK_TO_FRONT, targetActivity);
Winson Chung0f7ec962018-05-03 18:03:15 -0700263
264 // Register for stack order changes
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700265 mDefaultTaskDisplayArea.registerStackOrderChangedListener(this);
Winson Chungc6c3f852018-04-09 15:41:03 -0700266 } catch (Exception e) {
267 Slog.e(TAG, "Failed to start recents activity", e);
268 throw e;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800269 } finally {
Riddle Hsua0022cd2019-09-09 21:12:41 +0800270 mService.continueWindowLayout();
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800271 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Winson Chunge2d72172018-01-25 17:46:20 +0000272 }
Winson Chunge2d72172018-01-25 17:46:20 +0000273 }
274
Tracy Zhou9c675d42019-04-08 00:32:40 -0700275 private void finishAnimation(@RecentsAnimationController.ReorderMode int reorderMode,
276 boolean sendUserLeaveHint) {
Wale Ogunwalea6191b42018-05-09 07:41:32 -0700277 synchronized (mService.mGlobalLock) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200278 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
279 "onAnimationFinished(): controller=%s reorderMode=%d",
280 mWindowManager.getRecentsAnimationController(), reorderMode);
Winson Chungf9930162018-02-12 14:51:46 -0800281
Winson Chung0f7ec962018-05-03 18:03:15 -0700282 // Unregister for stack order changes
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700283 mDefaultTaskDisplayArea.unregisterStackOrderChangedListener(this);
Winson Chung0f7ec962018-05-03 18:03:15 -0700284
Riddle Hsu0e591722019-05-03 22:22:36 +0800285 final RecentsAnimationController controller =
286 mWindowManager.getRecentsAnimationController();
287 if (controller == null) return;
Winson Chunge2d72172018-01-25 17:46:20 +0000288
Winson Chung3e2980e2018-03-29 17:28:57 -0700289 // Just to be sure end the launch hint in case the target activity was never launched.
290 // However, if we're keeping the activity and making it visible, we can leave it on.
291 if (reorderMode != REORDER_KEEP_IN_PLACE) {
Louis Chang149d5c82019-12-30 09:47:39 +0800292 mService.mRootWindowContainer.sendPowerHintForLaunchEndIfNeeded();
Jorim Jaggiac960522018-03-22 23:20:36 +0100293 }
294
Winson Chung751579d2019-05-28 14:09:09 -0700295 // Once the target is shown, prevent spurious background app switches
296 if (reorderMode == REORDER_MOVE_TO_TOP) {
297 mService.stopAppSwitches();
298 }
299
Jorim Jaggi589c5ba2019-07-30 16:50:13 +0200300 if (mCaller != null) {
301 mCaller.setRunningRecentsAnimation(false);
302 }
Jorim Jaggibc2aabe2018-03-08 17:27:43 +0100303
Winson Chunge2d72172018-01-25 17:46:20 +0000304 mWindowManager.inSurfaceTransaction(() -> {
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800305 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
Winson Chung584d6522018-02-07 23:57:38 +0000306 "RecentsAnimation#onAnimationFinished_inSurfaceTransaction");
Riddle Hsua0022cd2019-09-09 21:12:41 +0800307 mService.deferWindowLayout();
Winson Chung1e6d4a92018-01-26 10:04:20 -0800308 try {
Winson Chung6a38fca2018-03-28 17:57:09 -0700309 mWindowManager.cleanupRecentsAnimation(reorderMode);
Winson Chunge2d72172018-01-25 17:46:20 +0000310
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700311 final ActivityStack targetStack = mDefaultTaskDisplayArea.getStack(
Winson Chung3e2980e2018-03-29 17:28:57 -0700312 WINDOWING_MODE_UNDEFINED, mTargetActivityType);
Riddle Hsu43233b72019-04-24 23:55:11 +0800313 // Prefer to use the original target activity instead of top activity because
314 // we may have moved another task to top (starting 3p launcher).
Winson Chung82389a92018-05-03 10:43:51 -0700315 final ActivityRecord targetActivity = targetStack != null
Riddle Hsu43233b72019-04-24 23:55:11 +0800316 ? targetStack.isInStackLocked(mLaunchedTargetActivity)
Winson Chung82389a92018-05-03 10:43:51 -0700317 : null;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200318 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
319 "onAnimationFinished(): targetStack=%s targetActivity=%s "
320 + "mRestoreTargetBehindStack=%s",
321 targetStack, targetActivity, mRestoreTargetBehindStack);
Winson Chung3e2980e2018-03-29 17:28:57 -0700322 if (targetActivity == null) {
Winson Chung1e6d4a92018-01-26 10:04:20 -0800323 return;
324 }
325
326 // Restore the launched-behind state
Winson Chung3e2980e2018-03-29 17:28:57 -0700327 targetActivity.mLaunchTaskBehind = false;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800328
Winson Chung3e2980e2018-03-29 17:28:57 -0700329 if (reorderMode == REORDER_MOVE_TO_TOP) {
330 // Bring the target stack to the front
331 mStackSupervisor.mNoAnimActivities.add(targetActivity);
Tracy Zhou9c675d42019-04-08 00:32:40 -0700332
333 if (sendUserLeaveHint) {
334 // Setting this allows the previous app to PiP.
335 mStackSupervisor.mUserLeaving = true;
Wale Ogunwale0d465192020-01-23 19:14:44 -0800336 targetStack.moveTaskToFront(targetActivity.getTask(),
Tracy Zhou9c675d42019-04-08 00:32:40 -0700337 true /* noAnimation */, null /* activityOptions */,
338 targetActivity.appTimeTracker,
339 "RecentsAnimation.onAnimationFinished()");
340 } else {
341 targetStack.moveToFront("RecentsAnimation.onAnimationFinished()");
342 }
343
Adrian Roosb125e0b2019-10-02 14:55:14 +0200344 if (WM_DEBUG_RECENTS_ANIMATIONS.isLogToAny()) {
Winson Chungc6c3f852018-04-09 15:41:03 -0700345 final ActivityStack topStack = getTopNonAlwaysOnTopStack();
346 if (topStack != targetStack) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200347 ProtoLog.w(WM_DEBUG_RECENTS_ANIMATIONS,
348 "Expected target stack=%s"
349 + " to be top most but found stack=%s",
350 targetStack, topStack);
Winson Chungc6c3f852018-04-09 15:41:03 -0700351 }
352 }
Winson Chung3e2980e2018-03-29 17:28:57 -0700353 } else if (reorderMode == REORDER_MOVE_TO_ORIGINAL_POSITION){
354 // Restore the target stack to its previous position
Andrii Kulian86d676c2020-03-27 19:34:54 -0700355 final TaskDisplayArea taskDisplayArea = targetActivity.getDisplayArea();
356 taskDisplayArea.moveStackBehindStack(targetStack,
Andrii Kulian9ea12da2020-03-27 17:16:38 -0700357 mRestoreTargetBehindStack);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200358 if (WM_DEBUG_RECENTS_ANIMATIONS.isLogToAny()) {
Andrii Kulian86d676c2020-03-27 19:34:54 -0700359 final ActivityStack aboveTargetStack = getStackAbove(targetStack);
Winson Chungc6c3f852018-04-09 15:41:03 -0700360 if (mRestoreTargetBehindStack != null
361 && aboveTargetStack != mRestoreTargetBehindStack) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200362 ProtoLog.w(WM_DEBUG_RECENTS_ANIMATIONS,
363 "Expected target stack=%s to restored behind stack=%s but"
364 + " it is behind stack=%s",
365 targetStack, mRestoreTargetBehindStack, aboveTargetStack);
Winson Chungc6c3f852018-04-09 15:41:03 -0700366 }
367 }
Winson Chung6a38fca2018-03-28 17:57:09 -0700368 } else {
Riddle Hsu0e591722019-05-03 22:22:36 +0800369 // If there is no recents screenshot animation, we can update the visibility
370 // of target stack immediately because it is visually invisible and the
371 // launch-behind state is restored. That also prevents the next transition
372 // type being disturbed if the visibility is updated after setting the next
373 // transition (the target activity will be one of closing apps).
Winson Chung7a545ae2019-07-16 14:52:13 -0700374 if (!controller.shouldDeferCancelWithScreenshot()
Riddle Hsu0e591722019-05-03 22:22:36 +0800375 && !targetStack.isFocusedStackOnDisplay()) {
Wale Ogunwale076c3b12019-11-20 12:17:22 -0800376 targetStack.ensureActivitiesVisible(null /* starting */,
Riddle Hsu0e591722019-05-03 22:22:36 +0800377 0 /* starting */, false /* preserveWindows */);
378 }
Winson Chung3e2980e2018-03-29 17:28:57 -0700379 // Keep target stack in place, nothing changes, so ignore the transition
380 // logic below
Winson Chung6a38fca2018-03-28 17:57:09 -0700381 return;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800382 }
383
384 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
Louis Chang149d5c82019-12-30 09:47:39 +0800385 mService.mRootWindowContainer.ensureActivitiesVisible(null, 0, false);
386 mService.mRootWindowContainer.resumeFocusedStacksTopActivities();
Winson Chung1e6d4a92018-01-26 10:04:20 -0800387
388 // No reason to wait for the pausing activity in this case, as the hiding of
389 // surfaces needs to be done immediately.
390 mWindowManager.executeAppTransition();
Winson Chungf557c3b2018-03-16 10:55:20 -0700391
Louis Changa009c762020-02-26 11:21:31 +0800392 final Task rootTask = targetStack.getRootTask();
393 if (rootTask.isOrganized()) {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800394 // Client state may have changed during the recents animation, so force
395 // send task info so the client can synchronize its state.
396 mService.mTaskOrganizerController.dispatchTaskInfoChanged(
Louis Changa009c762020-02-26 11:21:31 +0800397 rootTask, true /* force */);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800398 }
Winson Chungc6c3f852018-04-09 15:41:03 -0700399 } catch (Exception e) {
400 Slog.e(TAG, "Failed to clean up recents activity", e);
401 throw e;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800402 } finally {
Riddle Hsua0022cd2019-09-09 21:12:41 +0800403 mService.continueWindowLayout();
Riddle Hsu72d6dc32020-03-25 22:58:00 +0800404 // Make sure the surfaces are updated with the latest state. Sometimes the
405 // surface placement may be skipped if display configuration is changed (i.e.
406 // {@link DisplayContent#mWaitingForConfig} is true).
407 if (mWindowManager.mRoot.isLayoutNeeded()) {
408 mWindowManager.mRoot.performSurfacePlacement();
409 }
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800410 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Winson Chunge2d72172018-01-25 17:46:20 +0000411 }
Winson Chunge2d72172018-01-25 17:46:20 +0000412 });
413 }
414 }
Winson Chungddf62972018-02-12 11:10:04 -0800415
Winson Chung65c5f992018-04-20 14:58:57 -0700416 @Override
417 public void onAnimationFinished(@RecentsAnimationController.ReorderMode int reorderMode,
Wale Ogunwalea441b922019-06-27 19:21:44 -0700418 boolean sendUserLeaveHint) {
419 finishAnimation(reorderMode, sendUserLeaveHint);
Winson Chung65c5f992018-04-20 14:58:57 -0700420 }
421
Winson Chung0f7ec962018-05-03 18:03:15 -0700422 @Override
Winson Chung65d66d32018-12-13 17:48:39 -0800423 public void onStackOrderChanged(ActivityStack stack) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200424 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "onStackOrderChanged(): stack=%s", stack);
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700425 if (mDefaultTaskDisplayArea.getIndexOf(stack) == -1 || !stack.shouldBeVisible(null)) {
Winson Chung65d66d32018-12-13 17:48:39 -0800426 // The stack is not visible, so ignore this change
427 return;
428 }
lumark54284462019-03-05 20:44:27 +0800429 final RecentsAnimationController controller =
430 mWindowManager.getRecentsAnimationController();
lumarkf6f34942019-04-29 16:56:50 +0800431 if (controller == null) {
432 return;
433 }
434
Winson Chung7a545ae2019-07-16 14:52:13 -0700435 // We defer canceling the recents animation until the next app transition in the following
436 // cases:
437 // 1) The next launching task is not being animated by the recents animation
lumark54284462019-03-05 20:44:27 +0800438 // 2) The next task is home activity. (i.e. pressing home key to back home in recents).
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900439 if ((!controller.isAnimatingTask(stack.getTopMostTask())
Wale Ogunwale21e06482019-11-18 05:14:15 -0800440 || controller.isTargetApp(stack.getTopNonFinishingActivity()))
Winson Chung7a545ae2019-07-16 14:52:13 -0700441 && controller.shouldDeferCancelUntilNextTransition()) {
442 // Always prepare an app transition since we rely on the transition callbacks to cleanup
443 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
444 controller.setCancelOnNextTransitionStart();
lumark54284462019-03-05 20:44:27 +0800445 }
Winson Chung0f7ec962018-05-03 18:03:15 -0700446 }
447
Riddle Hsu609a8e22019-06-27 16:46:29 -0600448 private void startRecentsActivityInBackground(String reason) {
449 final ActivityOptions options = ActivityOptions.makeBasic();
450 options.setLaunchActivityType(mTargetActivityType);
451 options.setAvoidMoveToFront();
452 mTargetIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NO_ANIMATION);
453
454 mActivityStartController
455 .obtainStarter(mTargetIntent, reason)
456 .setCallingUid(mRecentsUid)
457 .setCallingPackage(mRecentsComponent.getPackageName())
Philip P. Moltmannee295092020-02-10 08:46:26 -0800458 .setCallingFeatureId(mRecentsFeatureId)
Riddle Hsu609a8e22019-06-27 16:46:29 -0600459 .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() {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700479 for (int i = mDefaultTaskDisplayArea.getStackCount() - 1; i >= 0; i--) {
480 final ActivityStack s = mDefaultTaskDisplayArea.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}