blob: f2ed6a29e412beb61486ff89b25b43cc5e3e5947 [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 Chungf9930162018-02-12 14:51:46 -080020import static android.app.AppOpsManager.OP_ASSIST_STRUCTURE;
21import static android.app.AppOpsManager.OP_NONE;
Winson Chunge2d72172018-01-25 17:46:20 +000022import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
Winson Chung3e2980e2018-03-29 17:28:57 -070023import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
24import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Winson Chunge2d72172018-01-25 17:46:20 +000025import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
26import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
Winson Chung584d6522018-02-07 23:57:38 +000027import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
Winson Chunge2d72172018-01-25 17:46:20 +000028import static android.view.WindowManager.TRANSIT_NONE;
29import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
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;
Winson Chunge2d72172018-01-25 17:46:20 +000033
34import android.app.ActivityOptions;
Winson Chungf9930162018-02-12 14:51:46 -080035import android.app.AppOpsManager;
36import android.app.IAssistDataReceiver;
Winson Chunge2d72172018-01-25 17:46:20 +000037import android.content.ComponentName;
Winson Chungf9930162018-02-12 14:51:46 -080038import android.content.Context;
Winson Chunge2d72172018-01-25 17:46:20 +000039import 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;
Winson Chung6a38fca2018-03-28 17:57:09 -070044import com.android.server.wm.RecentsAnimationController;
Winson Chunge2d72172018-01-25 17:46:20 +000045import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
46import com.android.server.wm.WindowManagerService;
47
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 */
52class RecentsAnimation implements RecentsAnimationCallbacks {
53 private static final String TAG = RecentsAnimation.class.getSimpleName();
Winson Chungc6c3f852018-04-09 15:41:03 -070054 // TODO (b/73188263): Reset debugging flags
55 private static final boolean DEBUG = true;
Winson Chunge2d72172018-01-25 17:46:20 +000056
Winson Chunge2d72172018-01-25 17:46:20 +000057 private final ActivityManagerService mService;
58 private final ActivityStackSupervisor mStackSupervisor;
59 private final ActivityStartController mActivityStartController;
60 private final WindowManagerService mWindowManager;
61 private final UserController mUserController;
Winson Chung3e2980e2018-03-29 17:28:57 -070062 private final ActivityDisplay mDefaultDisplay;
Jorim Jaggibc2aabe2018-03-08 17:27:43 +010063 private final int mCallingPid;
Winson Chunge2d72172018-01-25 17:46:20 +000064
Winson Chung3e2980e2018-03-29 17:28:57 -070065 private int mTargetActivityType;
Winson Chungf9930162018-02-12 14:51:46 -080066 private AssistDataRequester mAssistDataRequester;
Winson Chung3e2980e2018-03-29 17:28:57 -070067
68 // The stack to restore the target stack behind when the animation is finished
69 private ActivityStack mRestoreTargetBehindStack;
Winson Chunge2d72172018-01-25 17:46:20 +000070
71 RecentsAnimation(ActivityManagerService am, ActivityStackSupervisor stackSupervisor,
72 ActivityStartController activityStartController, WindowManagerService wm,
Jorim Jaggibc2aabe2018-03-08 17:27:43 +010073 UserController userController, int callingPid) {
Winson Chunge2d72172018-01-25 17:46:20 +000074 mService = am;
75 mStackSupervisor = stackSupervisor;
Winson Chung3e2980e2018-03-29 17:28:57 -070076 mDefaultDisplay = stackSupervisor.getDefaultDisplay();
Winson Chunge2d72172018-01-25 17:46:20 +000077 mActivityStartController = activityStartController;
Winson Chunge2d72172018-01-25 17:46:20 +000078 mWindowManager = wm;
79 mUserController = userController;
Jorim Jaggibc2aabe2018-03-08 17:27:43 +010080 mCallingPid = callingPid;
Winson Chunge2d72172018-01-25 17:46:20 +000081 }
82
83 void startRecentsActivity(Intent intent, IRecentsAnimationRunner recentsAnimationRunner,
Winson Chungf9930162018-02-12 14:51:46 -080084 ComponentName recentsComponent, int recentsUid,
85 IAssistDataReceiver assistDataReceiver) {
86 if (DEBUG) Slog.d(TAG, "startRecentsActivity(): intent=" + intent
87 + " assistDataReceiver=" + assistDataReceiver);
Winson Chung584d6522018-02-07 23:57:38 +000088 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "RecentsAnimation#startRecentsActivity");
Winson Chungddf62972018-02-12 11:10:04 -080089
90 if (!mWindowManager.canStartRecentsAnimation()) {
91 notifyAnimationCancelBeforeStart(recentsAnimationRunner);
Winson Chungc6c3f852018-04-09 15:41:03 -070092 if (DEBUG) Slog.d(TAG, "Can't start recents animation, nextAppTransition="
93 + mWindowManager.getPendingAppTransition());
Winson Chungddf62972018-02-12 11:10:04 -080094 return;
95 }
96
Winson Chung3e2980e2018-03-29 17:28:57 -070097 // If the activity is associated with the recents stack, then try and get that first
98 mTargetActivityType = intent.getComponent() != null
99 && recentsComponent.equals(intent.getComponent())
100 ? ACTIVITY_TYPE_RECENTS
101 : ACTIVITY_TYPE_HOME;
102 final ActivityStack targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
103 mTargetActivityType);
104 ActivityRecord targetActivity = targetStack != null
105 ? targetStack.getTopActivity()
106 : null;
107 final boolean hasExistingActivity = targetActivity != null;
108 if (hasExistingActivity) {
109 final ActivityDisplay display = targetActivity.getDisplay();
110 mRestoreTargetBehindStack = display.getStackAbove(targetStack);
111 if (mRestoreTargetBehindStack == null) {
Winson Chungddf62972018-02-12 11:10:04 -0800112 notifyAnimationCancelBeforeStart(recentsAnimationRunner);
Winson Chungc6c3f852018-04-09 15:41:03 -0700113 if (DEBUG) Slog.d(TAG, "No stack above target stack=" + targetStack);
Winson Chungddf62972018-02-12 11:10:04 -0800114 return;
115 }
116 }
117
Winson Chung3e2980e2018-03-29 17:28:57 -0700118 // Send launch hint if we are actually launching the target. If it's already visible
119 // (shouldn't happen in general) we don't need to send it.
120 if (targetActivity == null || !targetActivity.visible) {
Jorim Jaggiac960522018-03-22 23:20:36 +0100121 mStackSupervisor.sendPowerHintForLaunchStartIfNeeded(true /* forceSend */,
Winson Chung3e2980e2018-03-29 17:28:57 -0700122 targetActivity);
Jorim Jaggiac960522018-03-22 23:20:36 +0100123 }
124
Jorim Jaggi54cff642018-03-15 15:51:32 +0100125 mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching();
126
Jorim Jaggibc2aabe2018-03-08 17:27:43 +0100127 mService.setRunningRemoteAnimation(mCallingPid, true);
128
Winson Chung1e6d4a92018-01-26 10:04:20 -0800129 mWindowManager.deferSurfaceLayout();
130 try {
Winson Chungf9930162018-02-12 14:51:46 -0800131 // Kick off the assist data request in the background before showing the target activity
132 if (assistDataReceiver != null) {
133 final AppOpsManager appOpsManager = (AppOpsManager)
134 mService.mContext.getSystemService(Context.APP_OPS_SERVICE);
135 final AssistDataReceiverProxy proxy = new AssistDataReceiverProxy(
136 assistDataReceiver, recentsComponent.getPackageName());
137 mAssistDataRequester = new AssistDataRequester(mService.mContext, mService,
138 mWindowManager, appOpsManager, proxy, this, OP_ASSIST_STRUCTURE, OP_NONE);
139 mAssistDataRequester.requestAssistData(mStackSupervisor.getTopVisibleActivities(),
140 true /* fetchData */, false /* fetchScreenshots */,
141 true /* allowFetchData */, false /* allowFetchScreenshots */,
142 recentsUid, recentsComponent.getPackageName());
143 }
144
Winson Chungddf62972018-02-12 11:10:04 -0800145 final ActivityDisplay display;
Winson Chung3e2980e2018-03-29 17:28:57 -0700146 if (hasExistingActivity) {
147 // Move the recents activity into place for the animation if it is not top most
148 display = targetActivity.getDisplay();
149 display.moveStackBehindBottomMostVisibleStack(targetStack);
Winson Chungc6c3f852018-04-09 15:41:03 -0700150 if (DEBUG) Slog.d(TAG, "Moved stack=" + targetStack + " behind stack="
151 + display.getStackAbove(targetStack));
Winson Chungddf62972018-02-12 11:10:04 -0800152 } else {
Winson Chung3e2980e2018-03-29 17:28:57 -0700153 // No recents activity
154 ActivityOptions options = ActivityOptions.makeBasic();
155 options.setLaunchActivityType(mTargetActivityType);
156 options.setAvoidMoveToFront();
Winson Chung1e6d4a92018-01-26 10:04:20 -0800157 intent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NO_ANIMATION);
Winson Chunge2d72172018-01-25 17:46:20 +0000158
Winson Chung1e6d4a92018-01-26 10:04:20 -0800159 mActivityStartController
Winson Chung3e2980e2018-03-29 17:28:57 -0700160 .obtainStarter(intent, "startRecentsActivity_noTargetActivity")
Winson Chung1e6d4a92018-01-26 10:04:20 -0800161 .setCallingUid(recentsUid)
162 .setCallingPackage(recentsComponent.getPackageName())
Winson Chung3e2980e2018-03-29 17:28:57 -0700163 .setActivityOptions(SafeActivityOptions.fromBundle(options.toBundle()))
Winson Chung1e6d4a92018-01-26 10:04:20 -0800164 .setMayWait(mUserController.getCurrentUserId())
165 .execute();
166 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
Winson Chunge2d72172018-01-25 17:46:20 +0000167
Winson Chung3e2980e2018-03-29 17:28:57 -0700168 targetActivity = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
169 mTargetActivityType).getTopActivity();
170 display = targetActivity.getDisplay();
Winson Chungddf62972018-02-12 11:10:04 -0800171
Winson Chung1e6d4a92018-01-26 10:04:20 -0800172 // TODO: Maybe wait for app to draw in this particular case?
Winson Chungc6c3f852018-04-09 15:41:03 -0700173
174 if (DEBUG) Slog.d(TAG, "Started intent=" + intent);
Winson Chung1e6d4a92018-01-26 10:04:20 -0800175 }
Winson Chunge2d72172018-01-25 17:46:20 +0000176
Winson Chung3e2980e2018-03-29 17:28:57 -0700177 // Mark the target activity as launch-behind to bump its visibility for the
Winson Chung1e6d4a92018-01-26 10:04:20 -0800178 // duration of the gesture that is driven by the recents component
Winson Chung3e2980e2018-03-29 17:28:57 -0700179 targetActivity.mLaunchTaskBehind = true;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800180
181 // Fetch all the surface controls and pass them to the client to get the animation
182 // started
Winson Chungc6c3f852018-04-09 15:41:03 -0700183 mWindowManager.cancelRecentsAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION,
184 "startRecentsActivity");
Winson Chung3e2980e2018-03-29 17:28:57 -0700185 mWindowManager.initializeRecentsAnimation(mTargetActivityType, recentsAnimationRunner,
186 this, display.mDisplayId, mStackSupervisor.mRecentTasks.getRecentTaskIds());
Winson Chung1e6d4a92018-01-26 10:04:20 -0800187
188 // If we updated the launch-behind state, update the visibility of the activities after
189 // we fetch the visible tasks to be controlled by the animation
190 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
Jorim Jaggi54cff642018-03-15 15:51:32 +0100191
192 mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunched(START_TASK_TO_FRONT,
Winson Chung3e2980e2018-03-29 17:28:57 -0700193 targetActivity);
Winson Chungc6c3f852018-04-09 15:41:03 -0700194 } catch (Exception e) {
195 Slog.e(TAG, "Failed to start recents activity", e);
196 throw e;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800197 } finally {
198 mWindowManager.continueSurfaceLayout();
Winson Chung584d6522018-02-07 23:57:38 +0000199 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
Winson Chunge2d72172018-01-25 17:46:20 +0000200 }
Winson Chunge2d72172018-01-25 17:46:20 +0000201 }
202
203 @Override
Winson Chung6a38fca2018-03-28 17:57:09 -0700204 public void onAnimationFinished(@RecentsAnimationController.ReorderMode int reorderMode) {
Winson Chunge2d72172018-01-25 17:46:20 +0000205 synchronized (mService) {
Winson Chungc6c3f852018-04-09 15:41:03 -0700206 if (DEBUG) Slog.d(TAG, "onAnimationFinished(): controller="
207 + mWindowManager.getRecentsAnimationController()
208 + " reorderMode=" + reorderMode);
Winson Chungf9930162018-02-12 14:51:46 -0800209
210 // Cancel the associated assistant data request
211 if (mAssistDataRequester != null) {
212 mAssistDataRequester.cancel();
213 mAssistDataRequester = null;
214 }
215
Winson Chunge2d72172018-01-25 17:46:20 +0000216 if (mWindowManager.getRecentsAnimationController() == null) return;
217
Winson Chung3e2980e2018-03-29 17:28:57 -0700218 // Just to be sure end the launch hint in case the target activity was never launched.
219 // However, if we're keeping the activity and making it visible, we can leave it on.
220 if (reorderMode != REORDER_KEEP_IN_PLACE) {
Jorim Jaggiac960522018-03-22 23:20:36 +0100221 mStackSupervisor.sendPowerHintForLaunchEndIfNeeded();
222 }
223
Jorim Jaggibc2aabe2018-03-08 17:27:43 +0100224 mService.setRunningRemoteAnimation(mCallingPid, false);
225
Winson Chunge2d72172018-01-25 17:46:20 +0000226 mWindowManager.inSurfaceTransaction(() -> {
Winson Chung584d6522018-02-07 23:57:38 +0000227 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER,
228 "RecentsAnimation#onAnimationFinished_inSurfaceTransaction");
Winson Chung1e6d4a92018-01-26 10:04:20 -0800229 mWindowManager.deferSurfaceLayout();
230 try {
Winson Chung6a38fca2018-03-28 17:57:09 -0700231 mWindowManager.cleanupRecentsAnimation(reorderMode);
Winson Chunge2d72172018-01-25 17:46:20 +0000232
Winson Chung3e2980e2018-03-29 17:28:57 -0700233 final ActivityStack targetStack = mDefaultDisplay.getStack(
234 WINDOWING_MODE_UNDEFINED, mTargetActivityType);
235 final ActivityRecord targetActivity = targetStack.getTopActivity();
Winson Chungc6c3f852018-04-09 15:41:03 -0700236 if (DEBUG) Slog.d(TAG, "onAnimationFinished(): targetStack=" + targetStack
237 + " targetActivity=" + targetActivity
238 + " mRestoreTargetBehindStack=" + mRestoreTargetBehindStack);
Winson Chung3e2980e2018-03-29 17:28:57 -0700239 if (targetActivity == null) {
Winson Chung1e6d4a92018-01-26 10:04:20 -0800240 return;
241 }
242
243 // Restore the launched-behind state
Winson Chung3e2980e2018-03-29 17:28:57 -0700244 targetActivity.mLaunchTaskBehind = false;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800245
Winson Chung3e2980e2018-03-29 17:28:57 -0700246 if (reorderMode == REORDER_MOVE_TO_TOP) {
247 // Bring the target stack to the front
248 mStackSupervisor.mNoAnimActivities.add(targetActivity);
249 targetStack.moveToFront("RecentsAnimation.onAnimationFinished()");
Winson Chungc6c3f852018-04-09 15:41:03 -0700250 if (DEBUG) {
251 final ActivityStack topStack = getTopNonAlwaysOnTopStack();
252 if (topStack != targetStack) {
253 Slog.w(TAG, "Expected target stack=" + targetStack
254 + " to be top most but found stack=" + topStack);
255 }
256 }
Winson Chung3e2980e2018-03-29 17:28:57 -0700257 } else if (reorderMode == REORDER_MOVE_TO_ORIGINAL_POSITION){
258 // Restore the target stack to its previous position
259 final ActivityDisplay display = targetActivity.getDisplay();
260 display.moveStackBehindStack(targetStack, mRestoreTargetBehindStack);
Winson Chungc6c3f852018-04-09 15:41:03 -0700261 if (DEBUG) {
262 final ActivityStack aboveTargetStack =
263 mDefaultDisplay.getStackAbove(targetStack);
264 if (mRestoreTargetBehindStack != null
265 && aboveTargetStack != mRestoreTargetBehindStack) {
266 Slog.w(TAG, "Expected target stack=" + targetStack
267 + " to restored behind stack=" + mRestoreTargetBehindStack
268 + " but it is behind stack=" + aboveTargetStack);
269 }
270 }
Winson Chung6a38fca2018-03-28 17:57:09 -0700271 } else {
Winson Chung3e2980e2018-03-29 17:28:57 -0700272 // Keep target stack in place, nothing changes, so ignore the transition
273 // logic below
Winson Chung6a38fca2018-03-28 17:57:09 -0700274 return;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800275 }
276
277 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
278 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, false);
279 mStackSupervisor.resumeFocusedStackTopActivityLocked();
280
281 // No reason to wait for the pausing activity in this case, as the hiding of
282 // surfaces needs to be done immediately.
283 mWindowManager.executeAppTransition();
Winson Chungf557c3b2018-03-16 10:55:20 -0700284
285 // After reordering the stacks, reset the minimized state. At this point, either
Winson Chung3e2980e2018-03-29 17:28:57 -0700286 // the target activity is now top-most and we will stay minimized (if in
287 // split-screen), or we will have returned to the app, and the minimized state
288 // should be reset
Winson Chungf557c3b2018-03-16 10:55:20 -0700289 mWindowManager.checkSplitScreenMinimizedChanged(true /* animate */);
Winson Chungc6c3f852018-04-09 15:41:03 -0700290 } catch (Exception e) {
291 Slog.e(TAG, "Failed to clean up recents activity", e);
292 throw e;
Winson Chung1e6d4a92018-01-26 10:04:20 -0800293 } finally {
294 mWindowManager.continueSurfaceLayout();
Winson Chung584d6522018-02-07 23:57:38 +0000295 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
Winson Chunge2d72172018-01-25 17:46:20 +0000296 }
Winson Chunge2d72172018-01-25 17:46:20 +0000297 });
298 }
299 }
Winson Chungddf62972018-02-12 11:10:04 -0800300
301 /**
302 * Called only when the animation should be canceled prior to starting.
303 */
304 private void notifyAnimationCancelBeforeStart(IRecentsAnimationRunner recentsAnimationRunner) {
305 try {
306 recentsAnimationRunner.onAnimationCanceled();
307 } catch (RemoteException e) {
308 Slog.e(TAG, "Failed to cancel recents animation before start", e);
309 }
310 }
Winson Chungc6c3f852018-04-09 15:41:03 -0700311
312 /**
313 * @return The top stack that is not always-on-top.
314 */
315 private ActivityStack getTopNonAlwaysOnTopStack() {
316 for (int i = mDefaultDisplay.getChildCount() - 1; i >= 0; i--) {
317 final ActivityStack s = mDefaultDisplay.getChildAt(i);
318 if (s.getWindowConfiguration().isAlwaysOnTop()) {
319 continue;
320 }
321 return s;
322 }
323 return null;
324 }
Winson Chunge2d72172018-01-25 17:46:20 +0000325}