blob: e7b067b1ab7334d56a88d3e95eaa3656e66d7175 [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
19import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
20import 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;
23import static android.view.WindowManager.TRANSIT_NONE;
24import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
25
26import android.app.ActivityOptions;
27import android.content.ComponentName;
28import android.content.Intent;
29import android.os.Handler;
30import android.view.IRecentsAnimationRunner;
31import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
32import com.android.server.wm.WindowManagerService;
33
34/**
35 * Manages the recents animation, including the reordering of the stacks for the transition and
36 * cleanup. See {@link com.android.server.wm.RecentsAnimationController}.
37 */
38class RecentsAnimation implements RecentsAnimationCallbacks {
39 private static final String TAG = RecentsAnimation.class.getSimpleName();
40
41 private static final int RECENTS_ANIMATION_TIMEOUT = 10 * 1000;
42
43 private final ActivityManagerService mService;
44 private final ActivityStackSupervisor mStackSupervisor;
45 private final ActivityStartController mActivityStartController;
46 private final WindowManagerService mWindowManager;
47 private final UserController mUserController;
48 private final Handler mHandler;
49
50 private final Runnable mCancelAnimationRunnable;
51
52 // The stack to restore the home stack behind when the animation is finished
53 private ActivityStack mRestoreHomeBehindStack;
54
55 RecentsAnimation(ActivityManagerService am, ActivityStackSupervisor stackSupervisor,
56 ActivityStartController activityStartController, WindowManagerService wm,
57 UserController userController) {
58 mService = am;
59 mStackSupervisor = stackSupervisor;
60 mActivityStartController = activityStartController;
61 mHandler = new Handler(mStackSupervisor.mLooper);
62 mWindowManager = wm;
63 mUserController = userController;
64 mCancelAnimationRunnable = () -> {
65 // The caller has not finished the animation in a predefined amount of time, so
66 // force-cancel the animation
67 mWindowManager.cancelRecentsAnimation();
68 };
69 }
70
71 void startRecentsActivity(Intent intent, IRecentsAnimationRunner recentsAnimationRunner,
72 ComponentName recentsComponent, int recentsUid) {
Winson Chung1e6d4a92018-01-26 10:04:20 -080073 mWindowManager.deferSurfaceLayout();
74 try {
75 // Cancel the previous recents animation if necessary
76 mWindowManager.cancelRecentsAnimation();
Winson Chunge2d72172018-01-25 17:46:20 +000077
Winson Chung1e6d4a92018-01-26 10:04:20 -080078 final boolean hasExistingHomeActivity = mStackSupervisor.getHomeActivity() != null;
79 if (!hasExistingHomeActivity) {
80 // No home activity
81 final ActivityOptions opts = ActivityOptions.makeBasic();
82 opts.setLaunchActivityType(ACTIVITY_TYPE_HOME);
83 opts.setAvoidMoveToFront();
84 intent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NO_ANIMATION);
Winson Chunge2d72172018-01-25 17:46:20 +000085
Winson Chung1e6d4a92018-01-26 10:04:20 -080086 mActivityStartController
87 .obtainStarter(intent, "startRecentsActivity_noHomeActivity")
88 .setCallingUid(recentsUid)
89 .setCallingPackage(recentsComponent.getPackageName())
90 .setActivityOptions(SafeActivityOptions.fromBundle(opts.toBundle()))
91 .setMayWait(mUserController.getCurrentUserId())
92 .execute();
93 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
Winson Chunge2d72172018-01-25 17:46:20 +000094
Winson Chung1e6d4a92018-01-26 10:04:20 -080095 // TODO: Maybe wait for app to draw in this particular case?
96 }
Winson Chunge2d72172018-01-25 17:46:20 +000097
Winson Chung1e6d4a92018-01-26 10:04:20 -080098 final ActivityRecord homeActivity = mStackSupervisor.getHomeActivity();
99 final ActivityDisplay display = homeActivity.getDisplay();
100
101 // Save the initial position of the home activity stack to be restored to after the
102 // animation completes
103 mRestoreHomeBehindStack = hasExistingHomeActivity
104 ? display.getStackAboveHome()
105 : null;
106
107 // Move the home activity into place for the animation
108 display.moveHomeStackBehindBottomMostVisibleStack();
109
110 // Mark the home activity as launch-behind to bump its visibility for the
111 // duration of the gesture that is driven by the recents component
112 homeActivity.mLaunchTaskBehind = true;
113
114 // Fetch all the surface controls and pass them to the client to get the animation
115 // started
116 mWindowManager.initializeRecentsAnimation(recentsAnimationRunner, this,
117 display.mDisplayId);
118
119 // If we updated the launch-behind state, update the visibility of the activities after
120 // we fetch the visible tasks to be controlled by the animation
121 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
122
123 // Post a timeout for the animation
124 mHandler.postDelayed(mCancelAnimationRunnable, RECENTS_ANIMATION_TIMEOUT);
125 } finally {
126 mWindowManager.continueSurfaceLayout();
Winson Chunge2d72172018-01-25 17:46:20 +0000127 }
Winson Chunge2d72172018-01-25 17:46:20 +0000128 }
129
130 @Override
131 public void onAnimationFinished(boolean moveHomeToTop) {
132 mHandler.removeCallbacks(mCancelAnimationRunnable);
133 synchronized (mService) {
134 if (mWindowManager.getRecentsAnimationController() == null) return;
135
136 mWindowManager.inSurfaceTransaction(() -> {
Winson Chung1e6d4a92018-01-26 10:04:20 -0800137 mWindowManager.deferSurfaceLayout();
138 try {
139 mWindowManager.cleanupRecentsAnimation();
Winson Chunge2d72172018-01-25 17:46:20 +0000140
Winson Chung1e6d4a92018-01-26 10:04:20 -0800141 // Move the home stack to the front
142 final ActivityRecord homeActivity = mStackSupervisor.getHomeActivity();
143 if (homeActivity == null) {
144 return;
145 }
146
147 // Restore the launched-behind state
148 homeActivity.mLaunchTaskBehind = false;
149
150 if (moveHomeToTop) {
151 // Bring the home stack to the front
152 final ActivityStack homeStack = homeActivity.getStack();
Jorim Jaggifa9ed962018-01-25 00:16:49 +0100153 mStackSupervisor.mNoAnimActivities.add(homeActivity);
Winson Chung1e6d4a92018-01-26 10:04:20 -0800154 homeStack.moveToFront("RecentsAnimation.onAnimationFinished()");
155 } else {
156 // Restore the home stack to its previous position
157 final ActivityDisplay display = homeActivity.getDisplay();
158 display.moveHomeStackBehindStack(mRestoreHomeBehindStack);
159 }
160
161 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
162 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, false);
163 mStackSupervisor.resumeFocusedStackTopActivityLocked();
164
165 // No reason to wait for the pausing activity in this case, as the hiding of
166 // surfaces needs to be done immediately.
167 mWindowManager.executeAppTransition();
168 } finally {
169 mWindowManager.continueSurfaceLayout();
Winson Chunge2d72172018-01-25 17:46:20 +0000170 }
Winson Chunge2d72172018-01-25 17:46:20 +0000171 });
172 }
173 }
174}