blob: 5e74619be38344b1e400c613dae7bdc3602d9903 [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
17package com.android.server.am;
18
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;
21import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
22import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
Winson Chung584d6522018-02-07 23:57:38 +000023import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
Winson Chunge2d72172018-01-25 17:46:20 +000024import static android.view.WindowManager.TRANSIT_NONE;
25import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Winson Chung6a38fca2018-03-28 17:57:09 -070026import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_HOME_TO_ORIGINAL_POSITION;
27import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_HOME_TO_TOP;
Winson Chunge2d72172018-01-25 17:46:20 +000028
29import android.app.ActivityOptions;
30import android.content.ComponentName;
31import android.content.Intent;
32import android.os.Handler;
Winson Chungddf62972018-02-12 11:10:04 -080033import android.os.RemoteException;
Winson Chung584d6522018-02-07 23:57:38 +000034import android.os.Trace;
Winson Chungddf62972018-02-12 11:10:04 -080035import android.util.Slog;
Winson Chunge2d72172018-01-25 17:46:20 +000036import android.view.IRecentsAnimationRunner;
Winson Chung6a38fca2018-03-28 17:57:09 -070037import com.android.server.wm.RecentsAnimationController;
Winson Chunge2d72172018-01-25 17:46:20 +000038import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
39import com.android.server.wm.WindowManagerService;
40
41/**
42 * Manages the recents animation, including the reordering of the stacks for the transition and
43 * cleanup. See {@link com.android.server.wm.RecentsAnimationController}.
44 */
45class RecentsAnimation implements RecentsAnimationCallbacks {
46 private static final String TAG = RecentsAnimation.class.getSimpleName();
47
Winson Chunge2d72172018-01-25 17:46:20 +000048 private final ActivityManagerService mService;
49 private final ActivityStackSupervisor mStackSupervisor;
50 private final ActivityStartController mActivityStartController;
51 private final WindowManagerService mWindowManager;
52 private final UserController mUserController;
Jorim Jaggibc2aabe2018-03-08 17:27:43 +010053 private final int mCallingPid;
Winson Chunge2d72172018-01-25 17:46:20 +000054
Winson Chunge2d72172018-01-25 17:46:20 +000055 // The stack to restore the home stack behind when the animation is finished
56 private ActivityStack mRestoreHomeBehindStack;
57
58 RecentsAnimation(ActivityManagerService am, ActivityStackSupervisor stackSupervisor,
59 ActivityStartController activityStartController, WindowManagerService wm,
Jorim Jaggibc2aabe2018-03-08 17:27:43 +010060 UserController userController, int callingPid) {
Winson Chunge2d72172018-01-25 17:46:20 +000061 mService = am;
62 mStackSupervisor = stackSupervisor;
63 mActivityStartController = activityStartController;
Winson Chunge2d72172018-01-25 17:46:20 +000064 mWindowManager = wm;
65 mUserController = userController;
Jorim Jaggibc2aabe2018-03-08 17:27:43 +010066 mCallingPid = callingPid;
Winson Chunge2d72172018-01-25 17:46:20 +000067 }
68
69 void startRecentsActivity(Intent intent, IRecentsAnimationRunner recentsAnimationRunner,
70 ComponentName recentsComponent, int recentsUid) {
Winson Chung584d6522018-02-07 23:57:38 +000071 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "RecentsAnimation#startRecentsActivity");
Winson Chungddf62972018-02-12 11:10:04 -080072
73 if (!mWindowManager.canStartRecentsAnimation()) {
74 notifyAnimationCancelBeforeStart(recentsAnimationRunner);
75 return;
76 }
77
78 // If the existing home activity is already on top, then cancel
79 ActivityRecord homeActivity = mStackSupervisor.getHomeActivity();
80 final boolean hasExistingHomeActivity = homeActivity != null;
81 if (hasExistingHomeActivity) {
82 final ActivityDisplay display = homeActivity.getDisplay();
83 mRestoreHomeBehindStack = display.getStackAboveHome();
84 if (mRestoreHomeBehindStack == null) {
85 notifyAnimationCancelBeforeStart(recentsAnimationRunner);
86 return;
87 }
88 }
89
Jorim Jaggi54cff642018-03-15 15:51:32 +010090 mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching();
91
Jorim Jaggibc2aabe2018-03-08 17:27:43 +010092 mService.setRunningRemoteAnimation(mCallingPid, true);
93
Winson Chung1e6d4a92018-01-26 10:04:20 -080094 mWindowManager.deferSurfaceLayout();
95 try {
Winson Chungddf62972018-02-12 11:10:04 -080096 final ActivityDisplay display;
97 if (hasExistingHomeActivity) {
98 // Move the home activity into place for the animation if it is not already top most
99 display = homeActivity.getDisplay();
100 display.moveHomeStackBehindBottomMostVisibleStack();
101 } else {
Winson Chung1e6d4a92018-01-26 10:04:20 -0800102 // No home activity
103 final ActivityOptions opts = ActivityOptions.makeBasic();
104 opts.setLaunchActivityType(ACTIVITY_TYPE_HOME);
105 opts.setAvoidMoveToFront();
106 intent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NO_ANIMATION);
Winson Chunge2d72172018-01-25 17:46:20 +0000107
Winson Chung1e6d4a92018-01-26 10:04:20 -0800108 mActivityStartController
109 .obtainStarter(intent, "startRecentsActivity_noHomeActivity")
110 .setCallingUid(recentsUid)
111 .setCallingPackage(recentsComponent.getPackageName())
112 .setActivityOptions(SafeActivityOptions.fromBundle(opts.toBundle()))
113 .setMayWait(mUserController.getCurrentUserId())
114 .execute();
115 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
Winson Chunge2d72172018-01-25 17:46:20 +0000116
Winson Chungddf62972018-02-12 11:10:04 -0800117 homeActivity = mStackSupervisor.getHomeActivity();
118 display = homeActivity.getDisplay();
119
Winson Chung1e6d4a92018-01-26 10:04:20 -0800120 // TODO: Maybe wait for app to draw in this particular case?
121 }
Winson Chunge2d72172018-01-25 17:46:20 +0000122
Winson Chung1e6d4a92018-01-26 10:04:20 -0800123 // Mark the home activity as launch-behind to bump its visibility for the
124 // duration of the gesture that is driven by the recents component
125 homeActivity.mLaunchTaskBehind = true;
126
127 // Fetch all the surface controls and pass them to the client to get the animation
128 // started
Winson Chung6a38fca2018-03-28 17:57:09 -0700129 mWindowManager.cancelRecentsAnimation(REORDER_MOVE_HOME_TO_ORIGINAL_POSITION);
Winson Chung1e6d4a92018-01-26 10:04:20 -0800130 mWindowManager.initializeRecentsAnimation(recentsAnimationRunner, this,
Vadim Tryshev593e9562018-03-08 17:15:45 -0800131 display.mDisplayId, mStackSupervisor.mRecentTasks.getRecentTaskIds());
Winson Chung1e6d4a92018-01-26 10:04:20 -0800132
133 // If we updated the launch-behind state, update the visibility of the activities after
134 // we fetch the visible tasks to be controlled by the animation
135 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
Jorim Jaggi54cff642018-03-15 15:51:32 +0100136
137 mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunched(START_TASK_TO_FRONT,
138 homeActivity);
Winson Chung1e6d4a92018-01-26 10:04:20 -0800139 } finally {
140 mWindowManager.continueSurfaceLayout();
Winson Chung584d6522018-02-07 23:57:38 +0000141 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
Winson Chunge2d72172018-01-25 17:46:20 +0000142 }
Winson Chunge2d72172018-01-25 17:46:20 +0000143 }
144
145 @Override
Winson Chung6a38fca2018-03-28 17:57:09 -0700146 public void onAnimationFinished(@RecentsAnimationController.ReorderMode int reorderMode) {
Winson Chunge2d72172018-01-25 17:46:20 +0000147 synchronized (mService) {
148 if (mWindowManager.getRecentsAnimationController() == null) return;
149
Jorim Jaggibc2aabe2018-03-08 17:27:43 +0100150 mService.setRunningRemoteAnimation(mCallingPid, false);
151
Winson Chunge2d72172018-01-25 17:46:20 +0000152 mWindowManager.inSurfaceTransaction(() -> {
Winson Chung584d6522018-02-07 23:57:38 +0000153 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER,
154 "RecentsAnimation#onAnimationFinished_inSurfaceTransaction");
Winson Chung1e6d4a92018-01-26 10:04:20 -0800155 mWindowManager.deferSurfaceLayout();
156 try {
Winson Chung6a38fca2018-03-28 17:57:09 -0700157 mWindowManager.cleanupRecentsAnimation(reorderMode);
Winson Chunge2d72172018-01-25 17:46:20 +0000158
Winson Chung1e6d4a92018-01-26 10:04:20 -0800159 final ActivityRecord homeActivity = mStackSupervisor.getHomeActivity();
160 if (homeActivity == null) {
161 return;
162 }
163
164 // Restore the launched-behind state
165 homeActivity.mLaunchTaskBehind = false;
166
Winson Chung6a38fca2018-03-28 17:57:09 -0700167 if (reorderMode == REORDER_MOVE_HOME_TO_TOP) {
Winson Chung1e6d4a92018-01-26 10:04:20 -0800168 // Bring the home stack to the front
169 final ActivityStack homeStack = homeActivity.getStack();
Jorim Jaggifa9ed962018-01-25 00:16:49 +0100170 mStackSupervisor.mNoAnimActivities.add(homeActivity);
Winson Chung1e6d4a92018-01-26 10:04:20 -0800171 homeStack.moveToFront("RecentsAnimation.onAnimationFinished()");
Winson Chung6a38fca2018-03-28 17:57:09 -0700172 } else if (reorderMode == REORDER_MOVE_HOME_TO_ORIGINAL_POSITION){
Winson Chung1e6d4a92018-01-26 10:04:20 -0800173 // Restore the home stack to its previous position
174 final ActivityDisplay display = homeActivity.getDisplay();
175 display.moveHomeStackBehindStack(mRestoreHomeBehindStack);
Winson Chung6a38fca2018-03-28 17:57:09 -0700176 } else {
177 // Keep home stack in place, nothing changes, so ignore the transition logic
178 // below
179 return;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800180 }
181
182 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
183 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, false);
184 mStackSupervisor.resumeFocusedStackTopActivityLocked();
185
186 // No reason to wait for the pausing activity in this case, as the hiding of
187 // surfaces needs to be done immediately.
188 mWindowManager.executeAppTransition();
189 } finally {
190 mWindowManager.continueSurfaceLayout();
Winson Chung584d6522018-02-07 23:57:38 +0000191 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
Winson Chunge2d72172018-01-25 17:46:20 +0000192 }
Winson Chunge2d72172018-01-25 17:46:20 +0000193 });
194 }
195 }
Winson Chungddf62972018-02-12 11:10:04 -0800196
197 /**
198 * Called only when the animation should be canceled prior to starting.
199 */
200 private void notifyAnimationCancelBeforeStart(IRecentsAnimationRunner recentsAnimationRunner) {
201 try {
202 recentsAnimationRunner.onAnimationCanceled();
203 } catch (RemoteException e) {
204 Slog.e(TAG, "Failed to cancel recents animation before start", e);
205 }
206 }
Winson Chunge2d72172018-01-25 17:46:20 +0000207}