blob: 036bef755a87787fd3be311a7b1541f23465f4ef [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;
Winson Chung584d6522018-02-07 23:57:38 +000025import static android.os.Trace.TRACE_TAG_ACTIVITY_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;
Winson Chung3e2980e2018-03-29 17:28:57 -070031import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
32import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
33import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_TOP;
lumark54284462019-03-05 20:44:27 +080034import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RECENTS_ANIMATIONS;
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
Winson Chunge2d72172018-01-25 17:46:20 +000045import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
Winson Chunge2d72172018-01-25 17:46:20 +000046
47/**
48 * Manages the recents animation, including the reordering of the stacks for the transition and
49 * cleanup. See {@link com.android.server.wm.RecentsAnimationController}.
50 */
Winson Chung0f7ec962018-05-03 18:03:15 -070051class RecentsAnimation implements RecentsAnimationCallbacks,
52 ActivityDisplay.OnStackOrderChangedListener {
Winson Chunge2d72172018-01-25 17:46:20 +000053 private static final String TAG = RecentsAnimation.class.getSimpleName();
lumark54284462019-03-05 20:44:27 +080054 private static final boolean DEBUG = DEBUG_RECENTS_ANIMATIONS;
Winson Chunge2d72172018-01-25 17:46:20 +000055
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() {
104 if (DEBUG) Slog.d(TAG, "Preload recents with " + mTargetIntent);
105 ActivityStack targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
106 mTargetActivityType);
107 ActivityRecord targetActivity = getTargetActivity(targetStack);
108 if (targetActivity != null) {
109 if (targetActivity.visible || targetActivity.isTopRunningActivity()) {
110 // The activity is ready.
111 return;
112 }
113 if (targetActivity.attachedToProcess()) {
114 // The activity may be relaunched if it cannot handle the current configuration
115 // changes. The activity will be paused state if it is relaunched, otherwise it
116 // keeps the original stopped state.
117 targetActivity.ensureActivityConfiguration(0 /* globalChanges */,
118 false /* preserveWindow */, true /* ignoreVisibility */);
119 if (DEBUG) Slog.d(TAG, "Updated config=" + targetActivity.getConfiguration());
120 }
121 } else {
122 // Create the activity record. Because the activity is invisible, this doesn't really
123 // start the client.
124 startRecentsActivityInBackground("preloadRecents");
125 targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED, mTargetActivityType);
126 targetActivity = getTargetActivity(targetStack);
127 if (targetActivity == null) {
128 Slog.w(TAG, "Cannot start " + mTargetIntent);
129 return;
130 }
131 }
132
133 if (!targetActivity.attachedToProcess()) {
134 if (DEBUG) Slog.d(TAG, "Real start recents");
135 mStackSupervisor.startSpecificActivityLocked(targetActivity, false /* andResume */,
136 false /* checkConfig */);
137 // Make sure the activity won't be involved in transition.
138 if (targetActivity.mAppWindowToken != null) {
139 targetActivity.mAppWindowToken.getDisplayContent().mUnknownAppVisibilityController
140 .appRemovedOrHidden(targetActivity.mAppWindowToken);
141 }
142 }
143
144 // Invisible activity should be stopped. If the recents activity is alive and its doesn't
145 // need to relaunch by current configuration, then it may be already in stopped state.
146 if (!targetActivity.isState(ActivityStack.ActivityState.STOPPING,
147 ActivityStack.ActivityState.STOPPED)) {
148 // Add to stopping instead of stop immediately. So the client has the chance to perform
149 // traversal in non-stopped state (ViewRootImpl.mStopped) that would initialize more
150 // things (e.g. the measure can be done earlier). The actual stop will be performed when
151 // it reports idle.
152 targetStack.addToStopping(targetActivity, true /* scheduleIdle */,
153 true /* idleDelayed */, "preloadRecents");
154 }
155 }
156
157 void startRecentsActivity(IRecentsAnimationRunner recentsAnimationRunner) {
158 if (DEBUG) Slog.d(TAG, "startRecentsActivity(): intent=" + mTargetIntent);
Winson Chung584d6522018-02-07 23:57:38 +0000159 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "RecentsAnimation#startRecentsActivity");
Winson Chungddf62972018-02-12 11:10:04 -0800160
lumark588a3e82018-07-20 18:53:54 +0800161 // TODO(multi-display) currently only support recents animation in default display.
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800162 final DisplayContent dc =
163 mService.mRootActivityContainer.getDefaultDisplay().mDisplayContent;
Winson Chungddf62972018-02-12 11:10:04 -0800164 if (!mWindowManager.canStartRecentsAnimation()) {
165 notifyAnimationCancelBeforeStart(recentsAnimationRunner);
Winson Chungc6c3f852018-04-09 15:41:03 -0700166 if (DEBUG) Slog.d(TAG, "Can't start recents animation, nextAppTransition="
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800167 + dc.mAppTransition.getAppTransition());
Winson Chungddf62972018-02-12 11:10:04 -0800168 return;
169 }
170
Winson Chung3e2980e2018-03-29 17:28:57 -0700171 // If the activity is associated with the recents stack, then try and get that first
Winson Chung93442032018-12-04 13:24:29 -0800172 ActivityStack targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
Winson Chung3e2980e2018-03-29 17:28:57 -0700173 mTargetActivityType);
Riddle Hsu609a8e22019-06-27 16:46:29 -0600174 ActivityRecord targetActivity = getTargetActivity(targetStack);
Winson Chung3e2980e2018-03-29 17:28:57 -0700175 final boolean hasExistingActivity = targetActivity != null;
176 if (hasExistingActivity) {
177 final ActivityDisplay display = targetActivity.getDisplay();
178 mRestoreTargetBehindStack = display.getStackAbove(targetStack);
179 if (mRestoreTargetBehindStack == null) {
Winson Chungddf62972018-02-12 11:10:04 -0800180 notifyAnimationCancelBeforeStart(recentsAnimationRunner);
Winson Chungc6c3f852018-04-09 15:41:03 -0700181 if (DEBUG) Slog.d(TAG, "No stack above target stack=" + targetStack);
Winson Chungddf62972018-02-12 11:10:04 -0800182 return;
183 }
184 }
185
Winson Chung3e2980e2018-03-29 17:28:57 -0700186 // Send launch hint if we are actually launching the target. If it's already visible
187 // (shouldn't happen in general) we don't need to send it.
188 if (targetActivity == null || !targetActivity.visible) {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800189 mService.mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded(
190 true /* forceSend */, targetActivity);
Jorim Jaggiac960522018-03-22 23:20:36 +0100191 }
192
Riddle Hsu609a8e22019-06-27 16:46:29 -0600193 mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching(mTargetIntent);
Jorim Jaggi54cff642018-03-15 15:51:32 +0100194
Jorim Jaggi589c5ba2019-07-30 16:50:13 +0200195 if (mCaller != null) {
196 mCaller.setRunningRecentsAnimation(true);
197 }
Jorim Jaggibc2aabe2018-03-08 17:27:43 +0100198
Winson Chung1e6d4a92018-01-26 10:04:20 -0800199 mWindowManager.deferSurfaceLayout();
200 try {
Winson Chung3e2980e2018-03-29 17:28:57 -0700201 if (hasExistingActivity) {
202 // Move the recents activity into place for the animation if it is not top most
Winson Chung0f7ec962018-05-03 18:03:15 -0700203 mDefaultDisplay.moveStackBehindBottomMostVisibleStack(targetStack);
Winson Chungc6c3f852018-04-09 15:41:03 -0700204 if (DEBUG) Slog.d(TAG, "Moved stack=" + targetStack + " behind stack="
Winson Chung0f7ec962018-05-03 18:03:15 -0700205 + mDefaultDisplay.getStackAbove(targetStack));
Winson Chung00a09692018-04-19 16:14:09 -0700206
207 // If there are multiple tasks in the target stack (ie. the home stack, with 3p
208 // and default launchers coexisting), then move the task to the top as a part of
209 // moving the stack to the front
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800210 if (targetStack.topTask() != targetActivity.getTaskRecord()) {
211 targetStack.addTask(targetActivity.getTaskRecord(), true /* toTop */,
Winson Chung00a09692018-04-19 16:14:09 -0700212 "startRecentsActivity");
213 }
Winson Chungddf62972018-02-12 11:10:04 -0800214 } else {
Winson Chung93442032018-12-04 13:24:29 -0800215 // No recents activity, create the new recents activity bottom most
Riddle Hsu609a8e22019-06-27 16:46:29 -0600216 startRecentsActivityInBackground("startRecentsActivity_noTargetActivity");
Winson Chung93442032018-12-04 13:24:29 -0800217
218 // Move the recents activity into place for the animation
Winson Chung2bc60c02019-05-16 17:36:05 -0700219 targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
220 mTargetActivityType);
Riddle Hsu609a8e22019-06-27 16:46:29 -0600221 targetActivity = getTargetActivity(targetStack);
Winson Chung93442032018-12-04 13:24:29 -0800222 mDefaultDisplay.moveStackBehindBottomMostVisibleStack(targetStack);
223 if (DEBUG) {
224 Slog.d(TAG, "Moved stack=" + targetStack + " behind stack="
225 + mDefaultDisplay.getStackAbove(targetStack));
226 }
227
Winson Chung1e6d4a92018-01-26 10:04:20 -0800228 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
Winson Chungba40d3a2018-05-16 09:40:16 -0700229 mWindowManager.executeAppTransition();
Winson Chunge2d72172018-01-25 17:46:20 +0000230
Winson Chung1e6d4a92018-01-26 10:04:20 -0800231 // TODO: Maybe wait for app to draw in this particular case?
Winson Chungc6c3f852018-04-09 15:41:03 -0700232
Riddle Hsu609a8e22019-06-27 16:46:29 -0600233 if (DEBUG) Slog.d(TAG, "Started intent=" + mTargetIntent);
Winson Chung1e6d4a92018-01-26 10:04:20 -0800234 }
Winson Chunge2d72172018-01-25 17:46:20 +0000235
Winson Chung3e2980e2018-03-29 17:28:57 -0700236 // Mark the target activity as launch-behind to bump its visibility for the
Winson Chung1e6d4a92018-01-26 10:04:20 -0800237 // duration of the gesture that is driven by the recents component
Winson Chung3e2980e2018-03-29 17:28:57 -0700238 targetActivity.mLaunchTaskBehind = true;
Riddle Hsu43233b72019-04-24 23:55:11 +0800239 mLaunchedTargetActivity = targetActivity;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800240
241 // Fetch all the surface controls and pass them to the client to get the animation
Winson Chung65c5f992018-04-20 14:58:57 -0700242 // started. Cancel any existing recents animation running synchronously (do not hold the
243 // WM lock)
244 mWindowManager.cancelRecentsAnimationSynchronously(REORDER_MOVE_TO_ORIGINAL_POSITION,
Winson Chungc6c3f852018-04-09 15:41:03 -0700245 "startRecentsActivity");
Winson Chung3e2980e2018-03-29 17:28:57 -0700246 mWindowManager.initializeRecentsAnimation(mTargetActivityType, recentsAnimationRunner,
Winson Chung0f7ec962018-05-03 18:03:15 -0700247 this, mDefaultDisplay.mDisplayId,
248 mStackSupervisor.mRecentTasks.getRecentTaskIds());
Winson Chung1e6d4a92018-01-26 10:04:20 -0800249
250 // If we updated the launch-behind state, update the visibility of the activities after
251 // we fetch the visible tasks to be controlled by the animation
Wale Ogunwaled32da472018-11-16 07:19:28 -0800252 mService.mRootActivityContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
Jorim Jaggi54cff642018-03-15 15:51:32 +0100253
254 mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunched(START_TASK_TO_FRONT,
Winson Chung3e2980e2018-03-29 17:28:57 -0700255 targetActivity);
Winson Chung0f7ec962018-05-03 18:03:15 -0700256
257 // Register for stack order changes
258 mDefaultDisplay.registerStackOrderChangedListener(this);
Winson Chungc6c3f852018-04-09 15:41:03 -0700259 } catch (Exception e) {
260 Slog.e(TAG, "Failed to start recents activity", e);
261 throw e;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800262 } finally {
263 mWindowManager.continueSurfaceLayout();
Winson Chung584d6522018-02-07 23:57:38 +0000264 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
Winson Chunge2d72172018-01-25 17:46:20 +0000265 }
Winson Chunge2d72172018-01-25 17:46:20 +0000266 }
267
Tracy Zhou9c675d42019-04-08 00:32:40 -0700268 private void finishAnimation(@RecentsAnimationController.ReorderMode int reorderMode,
269 boolean sendUserLeaveHint) {
Wale Ogunwalea6191b42018-05-09 07:41:32 -0700270 synchronized (mService.mGlobalLock) {
Winson Chungc6c3f852018-04-09 15:41:03 -0700271 if (DEBUG) Slog.d(TAG, "onAnimationFinished(): controller="
Winson Chung65c5f992018-04-20 14:58:57 -0700272 + mWindowManager.getRecentsAnimationController()
273 + " reorderMode=" + reorderMode);
Winson Chungf9930162018-02-12 14:51:46 -0800274
Winson Chung0f7ec962018-05-03 18:03:15 -0700275 // Unregister for stack order changes
276 mDefaultDisplay.unregisterStackOrderChangedListener(this);
277
Riddle Hsu0e591722019-05-03 22:22:36 +0800278 final RecentsAnimationController controller =
279 mWindowManager.getRecentsAnimationController();
280 if (controller == null) return;
Winson Chunge2d72172018-01-25 17:46:20 +0000281
Winson Chung3e2980e2018-03-29 17:28:57 -0700282 // Just to be sure end the launch hint in case the target activity was never launched.
283 // However, if we're keeping the activity and making it visible, we can leave it on.
284 if (reorderMode != REORDER_KEEP_IN_PLACE) {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800285 mService.mRootActivityContainer.sendPowerHintForLaunchEndIfNeeded();
Jorim Jaggiac960522018-03-22 23:20:36 +0100286 }
287
Winson Chung751579d2019-05-28 14:09:09 -0700288 // Once the target is shown, prevent spurious background app switches
289 if (reorderMode == REORDER_MOVE_TO_TOP) {
290 mService.stopAppSwitches();
291 }
292
Jorim Jaggi589c5ba2019-07-30 16:50:13 +0200293 if (mCaller != null) {
294 mCaller.setRunningRecentsAnimation(false);
295 }
Jorim Jaggibc2aabe2018-03-08 17:27:43 +0100296
Winson Chunge2d72172018-01-25 17:46:20 +0000297 mWindowManager.inSurfaceTransaction(() -> {
Winson Chung584d6522018-02-07 23:57:38 +0000298 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER,
299 "RecentsAnimation#onAnimationFinished_inSurfaceTransaction");
Winson Chung1e6d4a92018-01-26 10:04:20 -0800300 mWindowManager.deferSurfaceLayout();
301 try {
Winson Chung6a38fca2018-03-28 17:57:09 -0700302 mWindowManager.cleanupRecentsAnimation(reorderMode);
Winson Chunge2d72172018-01-25 17:46:20 +0000303
Winson Chung3e2980e2018-03-29 17:28:57 -0700304 final ActivityStack targetStack = mDefaultDisplay.getStack(
305 WINDOWING_MODE_UNDEFINED, mTargetActivityType);
Riddle Hsu43233b72019-04-24 23:55:11 +0800306 // Prefer to use the original target activity instead of top activity because
307 // we may have moved another task to top (starting 3p launcher).
Winson Chung82389a92018-05-03 10:43:51 -0700308 final ActivityRecord targetActivity = targetStack != null
Riddle Hsu43233b72019-04-24 23:55:11 +0800309 ? targetStack.isInStackLocked(mLaunchedTargetActivity)
Winson Chung82389a92018-05-03 10:43:51 -0700310 : null;
Winson Chungc6c3f852018-04-09 15:41:03 -0700311 if (DEBUG) Slog.d(TAG, "onAnimationFinished(): targetStack=" + targetStack
312 + " targetActivity=" + targetActivity
313 + " mRestoreTargetBehindStack=" + mRestoreTargetBehindStack);
Winson Chung3e2980e2018-03-29 17:28:57 -0700314 if (targetActivity == null) {
Winson Chung1e6d4a92018-01-26 10:04:20 -0800315 return;
316 }
317
318 // Restore the launched-behind state
Winson Chung3e2980e2018-03-29 17:28:57 -0700319 targetActivity.mLaunchTaskBehind = false;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800320
Winson Chung3e2980e2018-03-29 17:28:57 -0700321 if (reorderMode == REORDER_MOVE_TO_TOP) {
322 // Bring the target stack to the front
323 mStackSupervisor.mNoAnimActivities.add(targetActivity);
Tracy Zhou9c675d42019-04-08 00:32:40 -0700324
325 if (sendUserLeaveHint) {
326 // Setting this allows the previous app to PiP.
327 mStackSupervisor.mUserLeaving = true;
328 targetStack.moveTaskToFrontLocked(targetActivity.getTaskRecord(),
329 true /* noAnimation */, null /* activityOptions */,
330 targetActivity.appTimeTracker,
331 "RecentsAnimation.onAnimationFinished()");
332 } else {
333 targetStack.moveToFront("RecentsAnimation.onAnimationFinished()");
334 }
335
Winson Chungc6c3f852018-04-09 15:41:03 -0700336 if (DEBUG) {
337 final ActivityStack topStack = getTopNonAlwaysOnTopStack();
338 if (topStack != targetStack) {
339 Slog.w(TAG, "Expected target stack=" + targetStack
340 + " to be top most but found stack=" + topStack);
341 }
342 }
Winson Chung3e2980e2018-03-29 17:28:57 -0700343 } else if (reorderMode == REORDER_MOVE_TO_ORIGINAL_POSITION){
344 // Restore the target stack to its previous position
345 final ActivityDisplay display = targetActivity.getDisplay();
346 display.moveStackBehindStack(targetStack, mRestoreTargetBehindStack);
Winson Chungc6c3f852018-04-09 15:41:03 -0700347 if (DEBUG) {
348 final ActivityStack aboveTargetStack =
349 mDefaultDisplay.getStackAbove(targetStack);
350 if (mRestoreTargetBehindStack != null
351 && aboveTargetStack != mRestoreTargetBehindStack) {
352 Slog.w(TAG, "Expected target stack=" + targetStack
353 + " to restored behind stack=" + mRestoreTargetBehindStack
354 + " but it is behind stack=" + aboveTargetStack);
355 }
356 }
Winson Chung6a38fca2018-03-28 17:57:09 -0700357 } else {
Riddle Hsu0e591722019-05-03 22:22:36 +0800358 // If there is no recents screenshot animation, we can update the visibility
359 // of target stack immediately because it is visually invisible and the
360 // launch-behind state is restored. That also prevents the next transition
361 // type being disturbed if the visibility is updated after setting the next
362 // transition (the target activity will be one of closing apps).
Winson Chung7a545ae2019-07-16 14:52:13 -0700363 if (!controller.shouldDeferCancelWithScreenshot()
Riddle Hsu0e591722019-05-03 22:22:36 +0800364 && !targetStack.isFocusedStackOnDisplay()) {
365 targetStack.ensureActivitiesVisibleLocked(null /* starting */,
366 0 /* starting */, false /* preserveWindows */);
367 }
Winson Chung3e2980e2018-03-29 17:28:57 -0700368 // Keep target stack in place, nothing changes, so ignore the transition
369 // logic below
Winson Chung6a38fca2018-03-28 17:57:09 -0700370 return;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800371 }
372
373 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
Wale Ogunwaled32da472018-11-16 07:19:28 -0800374 mService.mRootActivityContainer.ensureActivitiesVisible(null, 0, false);
375 mService.mRootActivityContainer.resumeFocusedStacksTopActivities();
Winson Chung1e6d4a92018-01-26 10:04:20 -0800376
377 // No reason to wait for the pausing activity in this case, as the hiding of
378 // surfaces needs to be done immediately.
379 mWindowManager.executeAppTransition();
Winson Chungf557c3b2018-03-16 10:55:20 -0700380
381 // After reordering the stacks, reset the minimized state. At this point, either
Winson Chung3e2980e2018-03-29 17:28:57 -0700382 // the target activity is now top-most and we will stay minimized (if in
383 // split-screen), or we will have returned to the app, and the minimized state
384 // should be reset
Winson Chungf557c3b2018-03-16 10:55:20 -0700385 mWindowManager.checkSplitScreenMinimizedChanged(true /* animate */);
Winson Chungc6c3f852018-04-09 15:41:03 -0700386 } catch (Exception e) {
387 Slog.e(TAG, "Failed to clean up recents activity", e);
388 throw e;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800389 } finally {
390 mWindowManager.continueSurfaceLayout();
Winson Chung584d6522018-02-07 23:57:38 +0000391 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
Winson Chunge2d72172018-01-25 17:46:20 +0000392 }
Winson Chunge2d72172018-01-25 17:46:20 +0000393 });
394 }
395 }
Winson Chungddf62972018-02-12 11:10:04 -0800396
Winson Chung65c5f992018-04-20 14:58:57 -0700397 @Override
398 public void onAnimationFinished(@RecentsAnimationController.ReorderMode int reorderMode,
Tracy Zhou9c675d42019-04-08 00:32:40 -0700399 boolean runSychronously, boolean sendUserLeaveHint) {
Winson Chung65c5f992018-04-20 14:58:57 -0700400 if (runSychronously) {
Tracy Zhou9c675d42019-04-08 00:32:40 -0700401 finishAnimation(reorderMode, sendUserLeaveHint);
Winson Chung65c5f992018-04-20 14:58:57 -0700402 } else {
Tracy Zhou9c675d42019-04-08 00:32:40 -0700403 mService.mH.post(() -> finishAnimation(reorderMode, sendUserLeaveHint));
Winson Chung65c5f992018-04-20 14:58:57 -0700404 }
405 }
406
Winson Chung0f7ec962018-05-03 18:03:15 -0700407 @Override
Winson Chung65d66d32018-12-13 17:48:39 -0800408 public void onStackOrderChanged(ActivityStack stack) {
409 if (DEBUG) Slog.d(TAG, "onStackOrderChanged(): stack=" + stack);
410 if (mDefaultDisplay.getIndexOf(stack) == -1 || !stack.shouldBeVisible(null)) {
411 // The stack is not visible, so ignore this change
412 return;
413 }
lumark54284462019-03-05 20:44:27 +0800414 final RecentsAnimationController controller =
415 mWindowManager.getRecentsAnimationController();
lumarkf6f34942019-04-29 16:56:50 +0800416 if (controller == null) {
417 return;
418 }
419
Tracy Zhou9c675d42019-04-08 00:32:40 -0700420 final DisplayContent dc =
421 mService.mRootActivityContainer.getDefaultDisplay().mDisplayContent;
422 dc.mBoundsAnimationController.setAnimationType(
Winson Chung7a545ae2019-07-16 14:52:13 -0700423 controller.shouldDeferCancelUntilNextTransition() ? FADE_IN : BOUNDS);
Winson Chung65d66d32018-12-13 17:48:39 -0800424
Winson Chung7a545ae2019-07-16 14:52:13 -0700425 // We defer canceling the recents animation until the next app transition in the following
426 // cases:
427 // 1) The next launching task is not being animated by the recents animation
lumark54284462019-03-05 20:44:27 +0800428 // 2) The next task is home activity. (i.e. pressing home key to back home in recents).
429 if ((!controller.isAnimatingTask(stack.getTaskStack().getTopChild())
430 || controller.isTargetApp(stack.getTopActivity().mAppWindowToken))
Winson Chung7a545ae2019-07-16 14:52:13 -0700431 && controller.shouldDeferCancelUntilNextTransition()) {
432 // Always prepare an app transition since we rely on the transition callbacks to cleanup
433 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
434 controller.setCancelOnNextTransitionStart();
lumark54284462019-03-05 20:44:27 +0800435 } else {
436 // Just cancel directly to unleash from launcher when the next launching task is the
437 // current top task.
438 mWindowManager.cancelRecentsAnimationSynchronously(REORDER_KEEP_IN_PLACE,
439 "stackOrderChanged");
440 }
Winson Chung0f7ec962018-05-03 18:03:15 -0700441 }
442
Riddle Hsu609a8e22019-06-27 16:46:29 -0600443 private void startRecentsActivityInBackground(String reason) {
444 final ActivityOptions options = ActivityOptions.makeBasic();
445 options.setLaunchActivityType(mTargetActivityType);
446 options.setAvoidMoveToFront();
447 mTargetIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NO_ANIMATION);
448
449 mActivityStartController
450 .obtainStarter(mTargetIntent, reason)
451 .setCallingUid(mRecentsUid)
452 .setCallingPackage(mRecentsComponent.getPackageName())
453 .setActivityOptions(new SafeActivityOptions(options))
454 .setMayWait(mUserId)
455 .execute();
456 }
457
Winson Chungddf62972018-02-12 11:10:04 -0800458 /**
459 * Called only when the animation should be canceled prior to starting.
460 */
Jorim Jaggi589c5ba2019-07-30 16:50:13 +0200461 static void notifyAnimationCancelBeforeStart(IRecentsAnimationRunner recentsAnimationRunner) {
Winson Chungddf62972018-02-12 11:10:04 -0800462 try {
lumark54284462019-03-05 20:44:27 +0800463 recentsAnimationRunner.onAnimationCanceled(false /* deferredWithScreenshot */);
Winson Chungddf62972018-02-12 11:10:04 -0800464 } catch (RemoteException e) {
465 Slog.e(TAG, "Failed to cancel recents animation before start", e);
466 }
467 }
Winson Chungc6c3f852018-04-09 15:41:03 -0700468
469 /**
470 * @return The top stack that is not always-on-top.
471 */
472 private ActivityStack getTopNonAlwaysOnTopStack() {
473 for (int i = mDefaultDisplay.getChildCount() - 1; i >= 0; i--) {
474 final ActivityStack s = mDefaultDisplay.getChildAt(i);
475 if (s.getWindowConfiguration().isAlwaysOnTop()) {
476 continue;
477 }
478 return s;
479 }
480 return null;
481 }
Winson Chung00a09692018-04-19 16:14:09 -0700482
483 /**
484 * @return the top activity in the {@param targetStack} matching the {@param component}, or just
485 * the top activity of the top task if no task matches the component.
486 */
Riddle Hsu609a8e22019-06-27 16:46:29 -0600487 private ActivityRecord getTargetActivity(ActivityStack targetStack) {
Winson Chung00a09692018-04-19 16:14:09 -0700488 if (targetStack == null) {
489 return null;
490 }
491
492 for (int i = targetStack.getChildCount() - 1; i >= 0; i--) {
Winson Chung65d66d32018-12-13 17:48:39 -0800493 final TaskRecord task = targetStack.getChildAt(i);
Riddle Hsu609a8e22019-06-27 16:46:29 -0600494 if (task.userId == mUserId
495 && task.getBaseIntent().getComponent().equals(mTargetIntent.getComponent())) {
Winson Chung00a09692018-04-19 16:14:09 -0700496 return task.getTopActivity();
497 }
498 }
Winson Chung2bc60c02019-05-16 17:36:05 -0700499 return null;
Winson Chung00a09692018-04-19 16:14:09 -0700500 }
Winson Chunge2d72172018-01-25 17:46:20 +0000501}