blob: a17bd24294c5b840a217debd11fd1b8813c3a94f [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
Adrian Roosb125e0b2019-10-02 14:55:14 +020045import com.android.server.protolog.common.ProtoLog;
Winson Chunge2d72172018-01-25 17:46:20 +000046import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
Winson Chunge2d72172018-01-25 17:46:20 +000047
48/**
49 * Manages the recents animation, including the reordering of the stacks for the transition and
50 * cleanup. See {@link com.android.server.wm.RecentsAnimationController}.
51 */
Winson Chung0f7ec962018-05-03 18:03:15 -070052class RecentsAnimation implements RecentsAnimationCallbacks,
53 ActivityDisplay.OnStackOrderChangedListener {
Winson Chunge2d72172018-01-25 17:46:20 +000054 private static final String TAG = RecentsAnimation.class.getSimpleName();
55
Wale Ogunwalea6191b42018-05-09 07:41:32 -070056 private final ActivityTaskManagerService mService;
Winson Chunge2d72172018-01-25 17:46:20 +000057 private final ActivityStackSupervisor mStackSupervisor;
58 private final ActivityStartController mActivityStartController;
59 private final WindowManagerService mWindowManager;
Winson Chung3e2980e2018-03-29 17:28:57 -070060 private final ActivityDisplay mDefaultDisplay;
Riddle Hsu609a8e22019-06-27 16:46:29 -060061 private final Intent mTargetIntent;
62 private final ComponentName mRecentsComponent;
63 private final int mRecentsUid;
Jorim Jaggi589c5ba2019-07-30 16:50:13 +020064 private final @Nullable WindowProcessController mCaller;
Riddle Hsu609a8e22019-06-27 16:46:29 -060065 private final int mUserId;
66 private final int mTargetActivityType;
Winson Chunge2d72172018-01-25 17:46:20 +000067
Riddle Hsu43233b72019-04-24 23:55:11 +080068 /**
69 * The activity which has been launched behind. We need to remember the activity because the
70 * target stack may have other activities, then we are able to restore the launch-behind state
71 * for the exact activity.
72 */
73 private ActivityRecord mLaunchedTargetActivity;
Winson Chung3e2980e2018-03-29 17:28:57 -070074
75 // The stack to restore the target stack behind when the animation is finished
76 private ActivityStack mRestoreTargetBehindStack;
Winson Chunge2d72172018-01-25 17:46:20 +000077
Wale Ogunwalea6191b42018-05-09 07:41:32 -070078 RecentsAnimation(ActivityTaskManagerService atm, ActivityStackSupervisor stackSupervisor,
Winson Chunge2d72172018-01-25 17:46:20 +000079 ActivityStartController activityStartController, WindowManagerService wm,
Jorim Jaggi589c5ba2019-07-30 16:50:13 +020080 Intent targetIntent, ComponentName recentsComponent, int recentsUid,
81 @Nullable WindowProcessController caller) {
Wale Ogunwalea6191b42018-05-09 07:41:32 -070082 mService = atm;
Winson Chunge2d72172018-01-25 17:46:20 +000083 mStackSupervisor = stackSupervisor;
Wale Ogunwaled32da472018-11-16 07:19:28 -080084 mDefaultDisplay = mService.mRootActivityContainer.getDefaultDisplay();
Winson Chunge2d72172018-01-25 17:46:20 +000085 mActivityStartController = activityStartController;
Winson Chunge2d72172018-01-25 17:46:20 +000086 mWindowManager = wm;
Riddle Hsu609a8e22019-06-27 16:46:29 -060087 mTargetIntent = targetIntent;
88 mRecentsComponent = recentsComponent;
89 mRecentsUid = recentsUid;
Jorim Jaggi589c5ba2019-07-30 16:50:13 +020090 mCaller = caller;
Riddle Hsu609a8e22019-06-27 16:46:29 -060091 mUserId = atm.getCurrentUserId();
92 mTargetActivityType = targetIntent.getComponent() != null
93 && recentsComponent.equals(targetIntent.getComponent())
94 ? ACTIVITY_TYPE_RECENTS
95 : ACTIVITY_TYPE_HOME;
Winson Chunge2d72172018-01-25 17:46:20 +000096 }
97
Riddle Hsu609a8e22019-06-27 16:46:29 -060098 /**
99 * Starts the recents activity in background without animation if the record doesn't exist or
100 * the client isn't launched. If the recents activity is already alive, ensure its configuration
101 * is updated to the current one.
102 */
103 void preloadRecentsActivity() {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200104 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Preload recents with %s",
105 mTargetIntent);
Riddle Hsu609a8e22019-06-27 16:46:29 -0600106 ActivityStack targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
107 mTargetActivityType);
108 ActivityRecord targetActivity = getTargetActivity(targetStack);
109 if (targetActivity != null) {
Issei Suzuki1669ea42019-11-06 14:20:59 +0100110 if (targetActivity.mVisibleRequested || targetActivity.isTopRunningActivity()) {
Riddle Hsu609a8e22019-06-27 16:46:29 -0600111 // The activity is ready.
112 return;
113 }
114 if (targetActivity.attachedToProcess()) {
115 // The activity may be relaunched if it cannot handle the current configuration
116 // changes. The activity will be paused state if it is relaunched, otherwise it
117 // keeps the original stopped state.
118 targetActivity.ensureActivityConfiguration(0 /* globalChanges */,
119 false /* preserveWindow */, true /* ignoreVisibility */);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200120 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Updated config=%s",
121 targetActivity.getConfiguration());
Riddle Hsu609a8e22019-06-27 16:46:29 -0600122 }
123 } else {
124 // Create the activity record. Because the activity is invisible, this doesn't really
125 // start the client.
126 startRecentsActivityInBackground("preloadRecents");
127 targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED, mTargetActivityType);
128 targetActivity = getTargetActivity(targetStack);
129 if (targetActivity == null) {
130 Slog.w(TAG, "Cannot start " + mTargetIntent);
131 return;
132 }
133 }
134
135 if (!targetActivity.attachedToProcess()) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200136 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Real start recents");
Riddle Hsu609a8e22019-06-27 16:46:29 -0600137 mStackSupervisor.startSpecificActivityLocked(targetActivity, false /* andResume */,
138 false /* checkConfig */);
139 // Make sure the activity won't be involved in transition.
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800140 if (targetActivity.getDisplayContent() != null) {
141 targetActivity.getDisplayContent().mUnknownAppVisibilityController
142 .appRemovedOrHidden(targetActivity);
Riddle Hsu609a8e22019-06-27 16:46:29 -0600143 }
144 }
145
146 // Invisible activity should be stopped. If the recents activity is alive and its doesn't
147 // need to relaunch by current configuration, then it may be already in stopped state.
148 if (!targetActivity.isState(ActivityStack.ActivityState.STOPPING,
149 ActivityStack.ActivityState.STOPPED)) {
150 // Add to stopping instead of stop immediately. So the client has the chance to perform
151 // traversal in non-stopped state (ViewRootImpl.mStopped) that would initialize more
152 // things (e.g. the measure can be done earlier). The actual stop will be performed when
153 // it reports idle.
Andrii Kulian79d67982019-08-19 11:56:16 -0700154 targetActivity.addToStopping(true /* scheduleIdle */, true /* idleDelayed */,
155 "preloadRecents");
Riddle Hsu609a8e22019-06-27 16:46:29 -0600156 }
157 }
158
159 void startRecentsActivity(IRecentsAnimationRunner recentsAnimationRunner) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200160 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "startRecentsActivity(): intent=%s", mTargetIntent);
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800161 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "RecentsAnimation#startRecentsActivity");
Winson Chungddf62972018-02-12 11:10:04 -0800162
lumark588a3e82018-07-20 18:53:54 +0800163 // TODO(multi-display) currently only support recents animation in default display.
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800164 final DisplayContent dc =
165 mService.mRootActivityContainer.getDefaultDisplay().mDisplayContent;
Winson Chungddf62972018-02-12 11:10:04 -0800166 if (!mWindowManager.canStartRecentsAnimation()) {
167 notifyAnimationCancelBeforeStart(recentsAnimationRunner);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200168 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
169 "Can't start recents animation, nextAppTransition=%s",
170 dc.mAppTransition.getAppTransition());
Winson Chungddf62972018-02-12 11:10:04 -0800171 return;
172 }
173
Winson Chung3e2980e2018-03-29 17:28:57 -0700174 // If the activity is associated with the recents stack, then try and get that first
Winson Chung93442032018-12-04 13:24:29 -0800175 ActivityStack targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
Winson Chung3e2980e2018-03-29 17:28:57 -0700176 mTargetActivityType);
Riddle Hsu609a8e22019-06-27 16:46:29 -0600177 ActivityRecord targetActivity = getTargetActivity(targetStack);
Winson Chung3e2980e2018-03-29 17:28:57 -0700178 final boolean hasExistingActivity = targetActivity != null;
179 if (hasExistingActivity) {
180 final ActivityDisplay display = targetActivity.getDisplay();
181 mRestoreTargetBehindStack = display.getStackAbove(targetStack);
182 if (mRestoreTargetBehindStack == null) {
Winson Chungddf62972018-02-12 11:10:04 -0800183 notifyAnimationCancelBeforeStart(recentsAnimationRunner);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200184 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
185 "No stack above target stack=%s", targetStack);
Winson Chungddf62972018-02-12 11:10:04 -0800186 return;
187 }
188 }
189
Winson Chung3e2980e2018-03-29 17:28:57 -0700190 // Send launch hint if we are actually launching the target. If it's already visible
191 // (shouldn't happen in general) we don't need to send it.
Issei Suzuki1669ea42019-11-06 14:20:59 +0100192 if (targetActivity == null || !targetActivity.mVisibleRequested) {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800193 mService.mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded(
194 true /* forceSend */, targetActivity);
Jorim Jaggiac960522018-03-22 23:20:36 +0100195 }
196
Riddle Hsu609a8e22019-06-27 16:46:29 -0600197 mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching(mTargetIntent);
Jorim Jaggi54cff642018-03-15 15:51:32 +0100198
Jorim Jaggi589c5ba2019-07-30 16:50:13 +0200199 if (mCaller != null) {
200 mCaller.setRunningRecentsAnimation(true);
201 }
Jorim Jaggibc2aabe2018-03-08 17:27:43 +0100202
Riddle Hsua0022cd2019-09-09 21:12:41 +0800203 mService.deferWindowLayout();
Winson Chung1e6d4a92018-01-26 10:04:20 -0800204 try {
Winson Chung3e2980e2018-03-29 17:28:57 -0700205 if (hasExistingActivity) {
206 // Move the recents activity into place for the animation if it is not top most
Winson Chung0f7ec962018-05-03 18:03:15 -0700207 mDefaultDisplay.moveStackBehindBottomMostVisibleStack(targetStack);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200208 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Moved stack=%s behind stack=%s",
209 targetStack, mDefaultDisplay.getStackAbove(targetStack));
Winson Chung00a09692018-04-19 16:14:09 -0700210
211 // If there are multiple tasks in the target stack (ie. the home stack, with 3p
212 // and default launchers coexisting), then move the task to the top as a part of
213 // moving the stack to the front
Louis Changcdec0802019-11-11 11:45:07 +0800214 final Task task = targetActivity.getTask();
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200215 if (targetStack.topTask() != task) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700216 targetStack.positionChildAtTop(task);
Winson Chung00a09692018-04-19 16:14:09 -0700217 }
Winson Chungddf62972018-02-12 11:10:04 -0800218 } else {
Winson Chung93442032018-12-04 13:24:29 -0800219 // No recents activity, create the new recents activity bottom most
Riddle Hsu609a8e22019-06-27 16:46:29 -0600220 startRecentsActivityInBackground("startRecentsActivity_noTargetActivity");
Winson Chung93442032018-12-04 13:24:29 -0800221
222 // Move the recents activity into place for the animation
Winson Chung2bc60c02019-05-16 17:36:05 -0700223 targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
224 mTargetActivityType);
Riddle Hsu609a8e22019-06-27 16:46:29 -0600225 targetActivity = getTargetActivity(targetStack);
Winson Chung93442032018-12-04 13:24:29 -0800226 mDefaultDisplay.moveStackBehindBottomMostVisibleStack(targetStack);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200227 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Moved stack=%s behind stack=%s",
228 targetStack, mDefaultDisplay.getStackAbove(targetStack));
Winson Chung93442032018-12-04 13:24:29 -0800229
Winson Chung1e6d4a92018-01-26 10:04:20 -0800230 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
Winson Chungba40d3a2018-05-16 09:40:16 -0700231 mWindowManager.executeAppTransition();
Winson Chunge2d72172018-01-25 17:46:20 +0000232
Winson Chung1e6d4a92018-01-26 10:04:20 -0800233 // TODO: Maybe wait for app to draw in this particular case?
Winson Chungc6c3f852018-04-09 15:41:03 -0700234
Adrian Roosb125e0b2019-10-02 14:55:14 +0200235 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Started intent=%s", mTargetIntent);
Winson Chung1e6d4a92018-01-26 10:04:20 -0800236 }
Winson Chunge2d72172018-01-25 17:46:20 +0000237
Winson Chung3e2980e2018-03-29 17:28:57 -0700238 // Mark the target activity as launch-behind to bump its visibility for the
Winson Chung1e6d4a92018-01-26 10:04:20 -0800239 // duration of the gesture that is driven by the recents component
Winson Chung3e2980e2018-03-29 17:28:57 -0700240 targetActivity.mLaunchTaskBehind = true;
Riddle Hsu43233b72019-04-24 23:55:11 +0800241 mLaunchedTargetActivity = targetActivity;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800242
243 // Fetch all the surface controls and pass them to the client to get the animation
Winson Chung65c5f992018-04-20 14:58:57 -0700244 // started. Cancel any existing recents animation running synchronously (do not hold the
245 // WM lock)
Wale Ogunwalea441b922019-06-27 19:21:44 -0700246 mWindowManager.cancelRecentsAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION,
Winson Chungc6c3f852018-04-09 15:41:03 -0700247 "startRecentsActivity");
Winson Chung3e2980e2018-03-29 17:28:57 -0700248 mWindowManager.initializeRecentsAnimation(mTargetActivityType, recentsAnimationRunner,
Winson Chung0f7ec962018-05-03 18:03:15 -0700249 this, mDefaultDisplay.mDisplayId,
wilsonshih417b70c12019-10-16 16:12:02 +0800250 mStackSupervisor.mRecentTasks.getRecentTaskIds(), targetActivity);
Winson Chung1e6d4a92018-01-26 10:04:20 -0800251
252 // If we updated the launch-behind state, update the visibility of the activities after
253 // we fetch the visible tasks to be controlled by the animation
Wale Ogunwaled32da472018-11-16 07:19:28 -0800254 mService.mRootActivityContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
Jorim Jaggi54cff642018-03-15 15:51:32 +0100255
256 mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunched(START_TASK_TO_FRONT,
Winson Chung3e2980e2018-03-29 17:28:57 -0700257 targetActivity);
Winson Chung0f7ec962018-05-03 18:03:15 -0700258
259 // Register for stack order changes
260 mDefaultDisplay.registerStackOrderChangedListener(this);
Winson Chungc6c3f852018-04-09 15:41:03 -0700261 } catch (Exception e) {
262 Slog.e(TAG, "Failed to start recents activity", e);
263 throw e;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800264 } finally {
Riddle Hsua0022cd2019-09-09 21:12:41 +0800265 mService.continueWindowLayout();
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800266 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Winson Chunge2d72172018-01-25 17:46:20 +0000267 }
Winson Chunge2d72172018-01-25 17:46:20 +0000268 }
269
Tracy Zhou9c675d42019-04-08 00:32:40 -0700270 private void finishAnimation(@RecentsAnimationController.ReorderMode int reorderMode,
271 boolean sendUserLeaveHint) {
Wale Ogunwalea6191b42018-05-09 07:41:32 -0700272 synchronized (mService.mGlobalLock) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200273 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
274 "onAnimationFinished(): controller=%s reorderMode=%d",
275 mWindowManager.getRecentsAnimationController(), reorderMode);
Winson Chungf9930162018-02-12 14:51:46 -0800276
Winson Chung0f7ec962018-05-03 18:03:15 -0700277 // Unregister for stack order changes
278 mDefaultDisplay.unregisterStackOrderChangedListener(this);
279
Riddle Hsu0e591722019-05-03 22:22:36 +0800280 final RecentsAnimationController controller =
281 mWindowManager.getRecentsAnimationController();
282 if (controller == null) return;
Winson Chunge2d72172018-01-25 17:46:20 +0000283
Winson Chung3e2980e2018-03-29 17:28:57 -0700284 // Just to be sure end the launch hint in case the target activity was never launched.
285 // However, if we're keeping the activity and making it visible, we can leave it on.
286 if (reorderMode != REORDER_KEEP_IN_PLACE) {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800287 mService.mRootActivityContainer.sendPowerHintForLaunchEndIfNeeded();
Jorim Jaggiac960522018-03-22 23:20:36 +0100288 }
289
Winson Chung751579d2019-05-28 14:09:09 -0700290 // Once the target is shown, prevent spurious background app switches
291 if (reorderMode == REORDER_MOVE_TO_TOP) {
292 mService.stopAppSwitches();
293 }
294
Jorim Jaggi589c5ba2019-07-30 16:50:13 +0200295 if (mCaller != null) {
296 mCaller.setRunningRecentsAnimation(false);
297 }
Jorim Jaggibc2aabe2018-03-08 17:27:43 +0100298
Winson Chunge2d72172018-01-25 17:46:20 +0000299 mWindowManager.inSurfaceTransaction(() -> {
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800300 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
Winson Chung584d6522018-02-07 23:57:38 +0000301 "RecentsAnimation#onAnimationFinished_inSurfaceTransaction");
Riddle Hsua0022cd2019-09-09 21:12:41 +0800302 mService.deferWindowLayout();
Winson Chung1e6d4a92018-01-26 10:04:20 -0800303 try {
Winson Chung6a38fca2018-03-28 17:57:09 -0700304 mWindowManager.cleanupRecentsAnimation(reorderMode);
Winson Chunge2d72172018-01-25 17:46:20 +0000305
Winson Chung3e2980e2018-03-29 17:28:57 -0700306 final ActivityStack targetStack = mDefaultDisplay.getStack(
307 WINDOWING_MODE_UNDEFINED, mTargetActivityType);
Riddle Hsu43233b72019-04-24 23:55:11 +0800308 // Prefer to use the original target activity instead of top activity because
309 // we may have moved another task to top (starting 3p launcher).
Winson Chung82389a92018-05-03 10:43:51 -0700310 final ActivityRecord targetActivity = targetStack != null
Riddle Hsu43233b72019-04-24 23:55:11 +0800311 ? targetStack.isInStackLocked(mLaunchedTargetActivity)
Winson Chung82389a92018-05-03 10:43:51 -0700312 : null;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200313 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
314 "onAnimationFinished(): targetStack=%s targetActivity=%s "
315 + "mRestoreTargetBehindStack=%s",
316 targetStack, targetActivity, mRestoreTargetBehindStack);
Winson Chung3e2980e2018-03-29 17:28:57 -0700317 if (targetActivity == null) {
Winson Chung1e6d4a92018-01-26 10:04:20 -0800318 return;
319 }
320
321 // Restore the launched-behind state
Winson Chung3e2980e2018-03-29 17:28:57 -0700322 targetActivity.mLaunchTaskBehind = false;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800323
Winson Chung3e2980e2018-03-29 17:28:57 -0700324 if (reorderMode == REORDER_MOVE_TO_TOP) {
325 // Bring the target stack to the front
326 mStackSupervisor.mNoAnimActivities.add(targetActivity);
Tracy Zhou9c675d42019-04-08 00:32:40 -0700327
328 if (sendUserLeaveHint) {
329 // Setting this allows the previous app to PiP.
330 mStackSupervisor.mUserLeaving = true;
Louis Changcdec0802019-11-11 11:45:07 +0800331 targetStack.moveTaskToFrontLocked(targetActivity.getTask(),
Tracy Zhou9c675d42019-04-08 00:32:40 -0700332 true /* noAnimation */, null /* activityOptions */,
333 targetActivity.appTimeTracker,
334 "RecentsAnimation.onAnimationFinished()");
335 } else {
336 targetStack.moveToFront("RecentsAnimation.onAnimationFinished()");
337 }
338
Adrian Roosb125e0b2019-10-02 14:55:14 +0200339 if (WM_DEBUG_RECENTS_ANIMATIONS.isLogToAny()) {
Winson Chungc6c3f852018-04-09 15:41:03 -0700340 final ActivityStack topStack = getTopNonAlwaysOnTopStack();
341 if (topStack != targetStack) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200342 ProtoLog.w(WM_DEBUG_RECENTS_ANIMATIONS,
343 "Expected target stack=%s"
344 + " to be top most but found stack=%s",
345 targetStack, topStack);
Winson Chungc6c3f852018-04-09 15:41:03 -0700346 }
347 }
Winson Chung3e2980e2018-03-29 17:28:57 -0700348 } else if (reorderMode == REORDER_MOVE_TO_ORIGINAL_POSITION){
349 // Restore the target stack to its previous position
350 final ActivityDisplay display = targetActivity.getDisplay();
351 display.moveStackBehindStack(targetStack, mRestoreTargetBehindStack);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200352 if (WM_DEBUG_RECENTS_ANIMATIONS.isLogToAny()) {
Winson Chungc6c3f852018-04-09 15:41:03 -0700353 final ActivityStack aboveTargetStack =
354 mDefaultDisplay.getStackAbove(targetStack);
355 if (mRestoreTargetBehindStack != null
356 && aboveTargetStack != mRestoreTargetBehindStack) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200357 ProtoLog.w(WM_DEBUG_RECENTS_ANIMATIONS,
358 "Expected target stack=%s to restored behind stack=%s but"
359 + " it is behind stack=%s",
360 targetStack, mRestoreTargetBehindStack, aboveTargetStack);
Winson Chungc6c3f852018-04-09 15:41:03 -0700361 }
362 }
Winson Chung6a38fca2018-03-28 17:57:09 -0700363 } else {
Riddle Hsu0e591722019-05-03 22:22:36 +0800364 // If there is no recents screenshot animation, we can update the visibility
365 // of target stack immediately because it is visually invisible and the
366 // launch-behind state is restored. That also prevents the next transition
367 // type being disturbed if the visibility is updated after setting the next
368 // transition (the target activity will be one of closing apps).
Winson Chung7a545ae2019-07-16 14:52:13 -0700369 if (!controller.shouldDeferCancelWithScreenshot()
Riddle Hsu0e591722019-05-03 22:22:36 +0800370 && !targetStack.isFocusedStackOnDisplay()) {
371 targetStack.ensureActivitiesVisibleLocked(null /* starting */,
372 0 /* starting */, false /* preserveWindows */);
373 }
Winson Chung3e2980e2018-03-29 17:28:57 -0700374 // Keep target stack in place, nothing changes, so ignore the transition
375 // logic below
Winson Chung6a38fca2018-03-28 17:57:09 -0700376 return;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800377 }
378
379 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
Wale Ogunwaled32da472018-11-16 07:19:28 -0800380 mService.mRootActivityContainer.ensureActivitiesVisible(null, 0, false);
381 mService.mRootActivityContainer.resumeFocusedStacksTopActivities();
Winson Chung1e6d4a92018-01-26 10:04:20 -0800382
383 // No reason to wait for the pausing activity in this case, as the hiding of
384 // surfaces needs to be done immediately.
385 mWindowManager.executeAppTransition();
Winson Chungf557c3b2018-03-16 10:55:20 -0700386
387 // After reordering the stacks, reset the minimized state. At this point, either
Winson Chung3e2980e2018-03-29 17:28:57 -0700388 // the target activity is now top-most and we will stay minimized (if in
389 // split-screen), or we will have returned to the app, and the minimized state
390 // should be reset
Winson Chungf557c3b2018-03-16 10:55:20 -0700391 mWindowManager.checkSplitScreenMinimizedChanged(true /* animate */);
Winson Chungc6c3f852018-04-09 15:41:03 -0700392 } catch (Exception e) {
393 Slog.e(TAG, "Failed to clean up recents activity", e);
394 throw e;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800395 } finally {
Riddle Hsua0022cd2019-09-09 21:12:41 +0800396 mService.continueWindowLayout();
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800397 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Winson Chunge2d72172018-01-25 17:46:20 +0000398 }
Winson Chunge2d72172018-01-25 17:46:20 +0000399 });
400 }
401 }
Winson Chungddf62972018-02-12 11:10:04 -0800402
Winson Chung65c5f992018-04-20 14:58:57 -0700403 @Override
404 public void onAnimationFinished(@RecentsAnimationController.ReorderMode int reorderMode,
Wale Ogunwalea441b922019-06-27 19:21:44 -0700405 boolean sendUserLeaveHint) {
406 finishAnimation(reorderMode, sendUserLeaveHint);
Winson Chung65c5f992018-04-20 14:58:57 -0700407 }
408
Winson Chung0f7ec962018-05-03 18:03:15 -0700409 @Override
Winson Chung65d66d32018-12-13 17:48:39 -0800410 public void onStackOrderChanged(ActivityStack stack) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200411 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "onStackOrderChanged(): stack=%s", stack);
Winson Chung65d66d32018-12-13 17:48:39 -0800412 if (mDefaultDisplay.getIndexOf(stack) == -1 || !stack.shouldBeVisible(null)) {
413 // The stack is not visible, so ignore this change
414 return;
415 }
lumark54284462019-03-05 20:44:27 +0800416 final RecentsAnimationController controller =
417 mWindowManager.getRecentsAnimationController();
lumarkf6f34942019-04-29 16:56:50 +0800418 if (controller == null) {
419 return;
420 }
421
Tracy Zhou9c675d42019-04-08 00:32:40 -0700422 final DisplayContent dc =
423 mService.mRootActivityContainer.getDefaultDisplay().mDisplayContent;
424 dc.mBoundsAnimationController.setAnimationType(
Winson Chung7a545ae2019-07-16 14:52:13 -0700425 controller.shouldDeferCancelUntilNextTransition() ? FADE_IN : BOUNDS);
Winson Chung65d66d32018-12-13 17:48:39 -0800426
Winson Chung7a545ae2019-07-16 14:52:13 -0700427 // We defer canceling the recents animation until the next app transition in the following
428 // cases:
429 // 1) The next launching task is not being animated by the recents animation
lumark54284462019-03-05 20:44:27 +0800430 // 2) The next task is home activity. (i.e. pressing home key to back home in recents).
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700431 if ((!controller.isAnimatingTask(stack.getTopChild())
Wale Ogunwale21e06482019-11-18 05:14:15 -0800432 || controller.isTargetApp(stack.getTopNonFinishingActivity()))
Winson Chung7a545ae2019-07-16 14:52:13 -0700433 && controller.shouldDeferCancelUntilNextTransition()) {
434 // Always prepare an app transition since we rely on the transition callbacks to cleanup
435 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
436 controller.setCancelOnNextTransitionStart();
lumark54284462019-03-05 20:44:27 +0800437 } else {
438 // Just cancel directly to unleash from launcher when the next launching task is the
439 // current top task.
Wale Ogunwalea441b922019-06-27 19:21:44 -0700440 mWindowManager.cancelRecentsAnimation(REORDER_KEEP_IN_PLACE, "stackOrderChanged");
lumark54284462019-03-05 20:44:27 +0800441 }
Winson Chung0f7ec962018-05-03 18:03:15 -0700442 }
443
Riddle Hsu609a8e22019-06-27 16:46:29 -0600444 private void startRecentsActivityInBackground(String reason) {
445 final ActivityOptions options = ActivityOptions.makeBasic();
446 options.setLaunchActivityType(mTargetActivityType);
447 options.setAvoidMoveToFront();
448 mTargetIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NO_ANIMATION);
449
450 mActivityStartController
451 .obtainStarter(mTargetIntent, reason)
452 .setCallingUid(mRecentsUid)
453 .setCallingPackage(mRecentsComponent.getPackageName())
454 .setActivityOptions(new SafeActivityOptions(options))
Louis Chang54fbb052019-10-16 17:10:17 +0800455 .setUserId(mUserId)
Riddle Hsu609a8e22019-06-27 16:46:29 -0600456 .execute();
457 }
458
Winson Chungddf62972018-02-12 11:10:04 -0800459 /**
460 * Called only when the animation should be canceled prior to starting.
461 */
Jorim Jaggi589c5ba2019-07-30 16:50:13 +0200462 static void notifyAnimationCancelBeforeStart(IRecentsAnimationRunner recentsAnimationRunner) {
Winson Chungddf62972018-02-12 11:10:04 -0800463 try {
Tracy Zhou8089ffa2019-07-30 17:30:43 -0700464 recentsAnimationRunner.onAnimationCanceled(null /* taskSnapshot */);
Winson Chungddf62972018-02-12 11:10:04 -0800465 } catch (RemoteException e) {
466 Slog.e(TAG, "Failed to cancel recents animation before start", e);
467 }
468 }
Winson Chungc6c3f852018-04-09 15:41:03 -0700469
470 /**
471 * @return The top stack that is not always-on-top.
472 */
473 private ActivityStack getTopNonAlwaysOnTopStack() {
474 for (int i = mDefaultDisplay.getChildCount() - 1; i >= 0; i--) {
475 final ActivityStack s = mDefaultDisplay.getChildAt(i);
476 if (s.getWindowConfiguration().isAlwaysOnTop()) {
477 continue;
478 }
479 return s;
480 }
481 return null;
482 }
Winson Chung00a09692018-04-19 16:14:09 -0700483
484 /**
485 * @return the top activity in the {@param targetStack} matching the {@param component}, or just
486 * the top activity of the top task if no task matches the component.
487 */
Riddle Hsu609a8e22019-06-27 16:46:29 -0600488 private ActivityRecord getTargetActivity(ActivityStack targetStack) {
Winson Chung00a09692018-04-19 16:14:09 -0700489 if (targetStack == null) {
490 return null;
491 }
492
493 for (int i = targetStack.getChildCount() - 1; i >= 0; i--) {
Louis Changcdec0802019-11-11 11:45:07 +0800494 final Task task = targetStack.getChildAt(i);
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700495 if (task.mUserId == mUserId
Riddle Hsu609a8e22019-06-27 16:46:29 -0600496 && task.getBaseIntent().getComponent().equals(mTargetIntent.getComponent())) {
Wale Ogunwale21e06482019-11-18 05:14:15 -0800497 return task.getTopNonFinishingActivity();
Winson Chung00a09692018-04-19 16:14:09 -0700498 }
499 }
Winson Chung2bc60c02019-05-16 17:36:05 -0700500 return null;
Winson Chung00a09692018-04-19 16:14:09 -0700501 }
Winson Chunge2d72172018-01-25 17:46:20 +0000502}