blob: 26df832bf3168255e5edb8ce2b3a8bcb0b5119b8 [file] [log] [blame]
Winson Chunge2d72172018-01-25 17:46:20 +00001/*
2 * Copyright (C) 2017 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.wm;
18
Jorim Jaggi54cff642018-03-15 15:51:32 +010019import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Winson Chunge2d72172018-01-25 17:46:20 +000020import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Winson Chung3e2980e2018-03-29 17:28:57 -070021import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Winson Chunge2d72172018-01-25 17:46:20 +000022import static android.view.RemoteAnimationTarget.MODE_CLOSING;
Winson Chung732446a2018-09-19 13:15:17 -070023import static android.view.RemoteAnimationTarget.MODE_OPENING;
Evan Roskyc5abbd82018-10-05 16:02:19 -070024import static android.view.WindowManager.DOCKED_INVALID;
Winson Chunga89ffed2018-01-25 17:46:11 +000025import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
Evan Roskyc5abbd82018-10-05 16:02:19 -070026
Winson Chunge2d72172018-01-25 17:46:20 +000027import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070028import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070029import static com.android.server.wm.AnimationAdapterProto.REMOTE;
Winson Chungc6c3f852018-04-09 15:41:03 -070030import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
31import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RECENTS_ANIMATIONS;
lumark54284462019-03-05 20:44:27 +080032import static com.android.server.wm.WindowManagerInternal.AppTransitionListener;
Winson Chunge2d72172018-01-25 17:46:20 +000033
Winson Chung6a38fca2018-03-28 17:57:09 -070034import android.annotation.IntDef;
Winson Chunge2d72172018-01-25 17:46:20 +000035import android.app.ActivityManager.TaskSnapshot;
36import android.app.WindowConfiguration;
Winson Chunge2d72172018-01-25 17:46:20 +000037import android.graphics.Point;
38import android.graphics.Rect;
39import android.os.Binder;
Adrian Roos842e7882018-03-26 17:34:06 +020040import android.os.IBinder.DeathRecipient;
Winson Chunge2d72172018-01-25 17:46:20 +000041import android.os.RemoteException;
42import android.os.SystemClock;
Winson Chung23aa7b12018-02-01 11:41:43 -080043import android.util.ArraySet;
Winson Chungc6c3f852018-04-09 15:41:03 -070044import android.util.Slog;
Vadim Tryshev593e9562018-03-08 17:15:45 -080045import android.util.SparseBooleanArray;
Jorim Jaggi54cff642018-03-15 15:51:32 +010046import android.util.SparseIntArray;
Winson Chungc6c3f852018-04-09 15:41:03 -070047import android.util.proto.ProtoOutputStream;
Winson Chunge2d72172018-01-25 17:46:20 +000048import android.view.IRecentsAnimationController;
49import android.view.IRecentsAnimationRunner;
Evan Roskyc5abbd82018-10-05 16:02:19 -070050import android.view.InputWindowHandle;
Winson Chunge2d72172018-01-25 17:46:20 +000051import android.view.RemoteAnimationTarget;
52import android.view.SurfaceControl;
53import android.view.SurfaceControl.Transaction;
Evan Roskyc5abbd82018-10-05 16:02:19 -070054
Winson Chungda876c92018-04-05 18:31:06 -070055import com.android.internal.annotations.VisibleForTesting;
Winson Chunga840c322018-04-20 15:58:18 -070056import com.android.server.LocalServices;
Yohei Yukawac3de83e2018-08-28 16:09:34 -070057import com.android.server.inputmethod.InputMethodManagerInternal;
Jorim Jaggif75d1612018-02-27 15:05:21 +010058import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
Jorim Jaggi817ebdd2018-03-26 15:46:01 +020059import com.android.server.wm.utils.InsetUtils;
Evan Roskyc5abbd82018-10-05 16:02:19 -070060
Vadim Tryshev257f86b2018-08-23 16:45:02 -070061import com.google.android.collect.Sets;
Evan Roskyc5abbd82018-10-05 16:02:19 -070062
Winson Chunge2d72172018-01-25 17:46:20 +000063import java.io.PrintWriter;
64import java.util.ArrayList;
Winson Chungc6c3f852018-04-09 15:41:03 -070065
Winson Chunge2d72172018-01-25 17:46:20 +000066/**
67 * Controls a single instance of the remote driven recents animation. In particular, this allows
68 * the calling SystemUI to animate the visible task windows as a part of the transition. The remote
69 * runner is provided an animation controller which allows it to take screenshots and to notify
70 * window manager when the animation is completed. In addition, window manager may also notify the
71 * app if it requires the animation to be canceled at any time (ie. due to timeout, etc.)
72 */
Adrian Roos842e7882018-03-26 17:34:06 +020073public class RecentsAnimationController implements DeathRecipient {
Winson Chungc6c3f852018-04-09 15:41:03 -070074 private static final String TAG = RecentsAnimationController.class.getSimpleName();
Adrian Roos842e7882018-03-26 17:34:06 +020075 private static final long FAILSAFE_DELAY = 1000;
Winson Chunge2d72172018-01-25 17:46:20 +000076
Winson Chung3e2980e2018-03-29 17:28:57 -070077 public static final int REORDER_KEEP_IN_PLACE = 0;
78 public static final int REORDER_MOVE_TO_TOP = 1;
79 public static final int REORDER_MOVE_TO_ORIGINAL_POSITION = 2;
Winson Chung6a38fca2018-03-28 17:57:09 -070080
81 @IntDef(prefix = { "REORDER_MODE_" }, value = {
Winson Chung3e2980e2018-03-29 17:28:57 -070082 REORDER_KEEP_IN_PLACE,
83 REORDER_MOVE_TO_TOP,
84 REORDER_MOVE_TO_ORIGINAL_POSITION
Winson Chung6a38fca2018-03-28 17:57:09 -070085 })
86 public @interface ReorderMode {}
87
Winson Chunge2d72172018-01-25 17:46:20 +000088 private final WindowManagerService mService;
Winson Chung5c91e8f2018-05-07 10:06:55 -070089 private IRecentsAnimationRunner mRunner;
Winson Chunge2d72172018-01-25 17:46:20 +000090 private final RecentsAnimationCallbacks mCallbacks;
91 private final ArrayList<TaskAnimationAdapter> mPendingAnimations = new ArrayList<>();
Winson Chungddf62972018-02-12 11:10:04 -080092 private final int mDisplayId;
Winson Chung65c5f992018-04-20 14:58:57 -070093 private final Runnable mFailsafeRunnable = () ->
94 cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "failSafeRunnable");
Winson Chunge2d72172018-01-25 17:46:20 +000095
lumark54284462019-03-05 20:44:27 +080096 final Object mLock = new Object();
97
Winson Chunge2d72172018-01-25 17:46:20 +000098 // The recents component app token that is shown behind the visibile tasks
Winson Chung3e2980e2018-03-29 17:28:57 -070099 private AppWindowToken mTargetAppToken;
Winson Chung732446a2018-09-19 13:15:17 -0700100 private int mTargetActivityType;
Winson Chung584d6522018-02-07 23:57:38 +0000101 private Rect mMinimizedHomeBounds = new Rect();
Winson Chunge2d72172018-01-25 17:46:20 +0000102
103 // We start the RecentsAnimationController in a pending-start state since we need to wait for
104 // the wallpaper/activity to draw before we can give control to the handler to start animating
105 // the visible task surfaces
106 private boolean mPendingStart = true;
107
108 // Set when the animation has been canceled
Winson Chungf557c3b2018-03-16 10:55:20 -0700109 private boolean mCanceled;
Winson Chunge2d72172018-01-25 17:46:20 +0000110
111 // Whether or not the input consumer is enabled. The input consumer must be both registered and
112 // enabled for it to start intercepting touch events.
113 private boolean mInputConsumerEnabled;
114
Winson Chungf557c3b2018-03-16 10:55:20 -0700115 // Whether or not the recents animation should cause the primary split-screen stack to be
116 // minimized
117 private boolean mSplitScreenMinimized;
118
Adrian Roos653c6c12018-04-09 14:12:46 -0700119 private final Rect mTmpRect = new Rect();
120
121 private boolean mLinkedToDeathOfRunner;
Winson Chunga89ffed2018-01-25 17:46:11 +0000122
lumark54284462019-03-05 20:44:27 +0800123 private boolean mCancelWithDeferredScreenshot;
124
125 private boolean mCancelOnNextTransitionStart;
126
127 /**
128 * Animates the screenshot of task that used to be controlled by RecentsAnimation.
129 * @see {@link #cancelOnNextTransitionStart}
130 */
131 SurfaceAnimator mRecentScreenshotAnimator;
132
133 final AppTransitionListener mAppTransitionListener = new AppTransitionListener() {
134 @Override
135 public int onAppTransitionStartingLocked(int transit, long duration,
136 long statusBarAnimationStartTime, long statusBarAnimationDuration) {
137 onTransitionStart();
138 mService.mRoot.getDisplayContent(mDisplayId).mAppTransition
139 .unregisterListener(this);
140 return 0;
141 }
142 };
143
Winson Chunge2d72172018-01-25 17:46:20 +0000144 public interface RecentsAnimationCallbacks {
Winson Chung65c5f992018-04-20 14:58:57 -0700145 void onAnimationFinished(@ReorderMode int reorderMode, boolean runSychronously);
Winson Chunge2d72172018-01-25 17:46:20 +0000146 }
147
148 private final IRecentsAnimationController mController =
149 new IRecentsAnimationController.Stub() {
150
151 @Override
152 public TaskSnapshot screenshotTask(int taskId) {
Winson Chungc6c3f852018-04-09 15:41:03 -0700153 if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "screenshotTask(" + taskId + "):"
154 + " mCanceled=" + mCanceled);
Winson Chungf557c3b2018-03-16 10:55:20 -0700155 final long token = Binder.clearCallingIdentity();
Winson Chunge2d72172018-01-25 17:46:20 +0000156 try {
157 synchronized (mService.getWindowManagerLock()) {
158 if (mCanceled) {
159 return null;
160 }
161 for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
162 final TaskAnimationAdapter adapter = mPendingAnimations.get(i);
163 final Task task = adapter.mTask;
164 if (task.mTaskId == taskId) {
Winson Chung23aa7b12018-02-01 11:41:43 -0800165 final TaskSnapshotController snapshotController =
166 mService.mTaskSnapshotController;
167 final ArraySet<Task> tasks = Sets.newArraySet(task);
168 snapshotController.snapshotTasks(tasks);
169 snapshotController.addSkipClosingAppSnapshotTasks(tasks);
170 return snapshotController.getSnapshot(taskId, 0 /* userId */,
171 false /* restoreFromDisk */, false /* reducedResolution */);
Winson Chunge2d72172018-01-25 17:46:20 +0000172 }
173 }
174 return null;
175 }
176 } finally {
177 Binder.restoreCallingIdentity(token);
178 }
179 }
180
181 @Override
182 public void finish(boolean moveHomeToTop) {
Winson Chungc6c3f852018-04-09 15:41:03 -0700183 if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "finish(" + moveHomeToTop + "):"
184 + " mCanceled=" + mCanceled);
Winson Chungf557c3b2018-03-16 10:55:20 -0700185 final long token = Binder.clearCallingIdentity();
Winson Chunge2d72172018-01-25 17:46:20 +0000186 try {
187 synchronized (mService.getWindowManagerLock()) {
188 if (mCanceled) {
189 return;
190 }
191 }
192
193 // Note, the callback will handle its own synchronization, do not lock on WM lock
194 // prior to calling the callback
Winson Chung6a38fca2018-03-28 17:57:09 -0700195 mCallbacks.onAnimationFinished(moveHomeToTop
Winson Chung3e2980e2018-03-29 17:28:57 -0700196 ? REORDER_MOVE_TO_TOP
Winson Chung65c5f992018-04-20 14:58:57 -0700197 : REORDER_MOVE_TO_ORIGINAL_POSITION,
198 true /* runSynchronously */);
Winson Chunge2d72172018-01-25 17:46:20 +0000199 } finally {
200 Binder.restoreCallingIdentity(token);
201 }
202 }
203
204 @Override
Jorim Jaggi50bf59c2018-03-09 17:29:48 +0100205 public void setAnimationTargetsBehindSystemBars(boolean behindSystemBars)
206 throws RemoteException {
Winson Chungf557c3b2018-03-16 10:55:20 -0700207 final long token = Binder.clearCallingIdentity();
Jorim Jaggi50bf59c2018-03-09 17:29:48 +0100208 try {
209 synchronized (mService.getWindowManagerLock()) {
210 for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
211 mPendingAnimations.get(i).mTask.setCanAffectSystemUiFlags(behindSystemBars);
212 }
213 mService.mWindowPlacerLocked.requestTraversal();
214 }
215 } finally {
216 Binder.restoreCallingIdentity(token);
217 }
218 }
219
220 @Override
Winson Chunge2d72172018-01-25 17:46:20 +0000221 public void setInputConsumerEnabled(boolean enabled) {
Winson Chungc6c3f852018-04-09 15:41:03 -0700222 if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "setInputConsumerEnabled(" + enabled + "):"
223 + " mCanceled=" + mCanceled);
Winson Chungf557c3b2018-03-16 10:55:20 -0700224 final long token = Binder.clearCallingIdentity();
Winson Chunge2d72172018-01-25 17:46:20 +0000225 try {
226 synchronized (mService.getWindowManagerLock()) {
227 if (mCanceled) {
228 return;
229 }
230
231 mInputConsumerEnabled = enabled;
Arthur Hung95b38a92018-07-20 18:56:12 +0800232 final InputMonitor inputMonitor =
233 mService.mRoot.getDisplayContent(mDisplayId).getInputMonitor();
234 inputMonitor.updateInputWindowsLw(true /*force*/);
Winson Chunge2d72172018-01-25 17:46:20 +0000235 mService.scheduleAnimationLocked();
236 }
237 } finally {
238 Binder.restoreCallingIdentity(token);
239 }
240 }
Winson Chungf557c3b2018-03-16 10:55:20 -0700241
242 @Override
243 public void setSplitScreenMinimized(boolean minimized) {
244 final long token = Binder.clearCallingIdentity();
245 try {
246 synchronized (mService.getWindowManagerLock()) {
247 if (mCanceled) {
248 return;
249 }
250
251 mSplitScreenMinimized = minimized;
252 mService.checkSplitScreenMinimizedChanged(true /* animate */);
253 }
254 } finally {
255 Binder.restoreCallingIdentity(token);
256 }
257 }
Winson Chunga840c322018-04-20 15:58:18 -0700258
259 @Override
260 public void hideCurrentInputMethod() {
261 final long token = Binder.clearCallingIdentity();
262 try {
263 final InputMethodManagerInternal inputMethodManagerInternal =
264 LocalServices.getService(InputMethodManagerInternal.class);
265 if (inputMethodManagerInternal != null) {
266 inputMethodManagerInternal.hideCurrentInputMethod();
267 }
268 } finally {
269 Binder.restoreCallingIdentity(token);
270 }
271 }
lumark54284462019-03-05 20:44:27 +0800272
273 @Override
274 public void setCancelWithDeferredScreenshot(boolean screenshot) {
275 synchronized (mLock) {
276 setCancelWithDeferredScreenshotLocked(screenshot);
277 }
278 }
279
280 @Override
281 public void cleanupScreenshot() {
282 synchronized (mLock) {
283 if (mRecentScreenshotAnimator != null) {
284 mRecentScreenshotAnimator.cancelAnimation();
285 mRecentScreenshotAnimator = null;
286 }
287 }
288 }
Winson Chunge2d72172018-01-25 17:46:20 +0000289 };
290
291 /**
Winson Chunge2d72172018-01-25 17:46:20 +0000292 * @param remoteAnimationRunner The remote runner which should be notified when the animation is
293 * ready to start or has been canceled
294 * @param callbacks Callbacks to be made when the animation finishes
Winson Chunge2d72172018-01-25 17:46:20 +0000295 */
296 RecentsAnimationController(WindowManagerService service,
297 IRecentsAnimationRunner remoteAnimationRunner, RecentsAnimationCallbacks callbacks,
298 int displayId) {
299 mService = service;
300 mRunner = remoteAnimationRunner;
301 mCallbacks = callbacks;
Winson Chungddf62972018-02-12 11:10:04 -0800302 mDisplayId = displayId;
303 }
Winson Chunge2d72172018-01-25 17:46:20 +0000304
Winson Chung732446a2018-09-19 13:15:17 -0700305 public void initialize(int targetActivityType, SparseBooleanArray recentTaskIds) {
306 initialize(mService.mRoot.getDisplayContent(mDisplayId), targetActivityType, recentTaskIds);
307 }
308
Winson Chungddf62972018-02-12 11:10:04 -0800309 /**
310 * Initializes the recents animation controller. This is a separate call from the constructor
311 * because it may call cancelAnimation() which needs to properly clean up the controller
312 * in the window manager.
313 */
Winson Chung732446a2018-09-19 13:15:17 -0700314 @VisibleForTesting
315 void initialize(DisplayContent dc, int targetActivityType, SparseBooleanArray recentTaskIds) {
316 mTargetActivityType = targetActivityType;
lumark54284462019-03-05 20:44:27 +0800317 dc.mAppTransition.registerListenerLocked(mAppTransitionListener);
Winson Chung732446a2018-09-19 13:15:17 -0700318
319 // Make leashes for each of the visible/target tasks and add it to the recents animation to
320 // be started
Winson Chungddf62972018-02-12 11:10:04 -0800321 final ArrayList<Task> visibleTasks = dc.getVisibleTasks();
Winson Chung732446a2018-09-19 13:15:17 -0700322 final TaskStack targetStack = dc.getStack(WINDOWING_MODE_UNDEFINED, targetActivityType);
323 if (targetStack != null) {
324 for (int i = targetStack.getChildCount() - 1; i >= 0; i--) {
325 final Task t = targetStack.getChildAt(i);
326 if (!visibleTasks.contains(t)) {
327 visibleTasks.add(t);
328 }
329 }
330 }
Winson Chunge2d72172018-01-25 17:46:20 +0000331 final int taskCount = visibleTasks.size();
332 for (int i = 0; i < taskCount; i++) {
333 final Task task = visibleTasks.get(i);
334 final WindowConfiguration config = task.getWindowConfiguration();
335 if (config.tasksAreFloating()
Winson Chung732446a2018-09-19 13:15:17 -0700336 || config.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
Winson Chunge2d72172018-01-25 17:46:20 +0000337 continue;
338 }
Vadim Tryshev593e9562018-03-08 17:15:45 -0800339 addAnimation(task, !recentTaskIds.get(task.mTaskId));
Winson Chunge2d72172018-01-25 17:46:20 +0000340 }
341
Winson Chungddf62972018-02-12 11:10:04 -0800342 // Skip the animation if there is nothing to animate
343 if (mPendingAnimations.isEmpty()) {
Winson Chungc6c3f852018-04-09 15:41:03 -0700344 cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "initialize-noVisibleTasks");
Winson Chungddf62972018-02-12 11:10:04 -0800345 return;
346 }
347
Adrian Roos842e7882018-03-26 17:34:06 +0200348 try {
Adrian Roos653c6c12018-04-09 14:12:46 -0700349 linkToDeathOfRunner();
Adrian Roos842e7882018-03-26 17:34:06 +0200350 } catch (RemoteException e) {
Winson Chungc6c3f852018-04-09 15:41:03 -0700351 cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "initialize-failedToLinkToDeath");
Adrian Roos842e7882018-03-26 17:34:06 +0200352 return;
353 }
354
Winson Chung3e2980e2018-03-29 17:28:57 -0700355 // Adjust the wallpaper visibility for the showing target activity
356 final AppWindowToken recentsComponentAppToken = dc.getStack(WINDOWING_MODE_UNDEFINED,
357 targetActivityType).getTopChild().getTopFullscreenAppToken();
Winson Chunge2d72172018-01-25 17:46:20 +0000358 if (recentsComponentAppToken != null) {
Winson Chungc6c3f852018-04-09 15:41:03 -0700359 if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "setHomeApp("
360 + recentsComponentAppToken.getName() + ")");
Winson Chung3e2980e2018-03-29 17:28:57 -0700361 mTargetAppToken = recentsComponentAppToken;
Winson Chunge2d72172018-01-25 17:46:20 +0000362 if (recentsComponentAppToken.windowsCanBeWallpaperTarget()) {
363 dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
364 dc.setLayoutNeeded();
365 }
366 }
367
Winson Chung584d6522018-02-07 23:57:38 +0000368 // Save the minimized home height
Evan Roskyc5abbd82018-10-05 16:02:19 -0700369 final TaskStack dockedStack = dc.getSplitScreenPrimaryStackIgnoringVisibility();
370 dc.getDockedDividerController().getHomeStackBoundsInDockedMode(
371 dc.getConfiguration(),
372 dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide(),
373 mMinimizedHomeBounds);
Winson Chung584d6522018-02-07 23:57:38 +0000374
Winson Chunge2d72172018-01-25 17:46:20 +0000375 mService.mWindowPlacerLocked.performSurfacePlacement();
376 }
377
Winson Chungda876c92018-04-05 18:31:06 -0700378 @VisibleForTesting
379 AnimationAdapter addAnimation(Task task, boolean isRecentTaskInvisible) {
Winson Chungc6c3f852018-04-09 15:41:03 -0700380 if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "addAnimation(" + task.getName() + ")");
Vadim Tryshev593e9562018-03-08 17:15:45 -0800381 final TaskAnimationAdapter taskAdapter = new TaskAnimationAdapter(task,
382 isRecentTaskInvisible);
Winson Chung5720d8e2018-08-03 15:50:00 -0700383 task.startAnimation(task.getPendingTransaction(), taskAdapter, false /* hidden */);
Winson Chunge2d72172018-01-25 17:46:20 +0000384 task.commitPendingTransaction();
385 mPendingAnimations.add(taskAdapter);
Winson Chungda876c92018-04-05 18:31:06 -0700386 return taskAdapter;
387 }
388
389 @VisibleForTesting
390 void removeAnimation(TaskAnimationAdapter taskAdapter) {
Winson Chungc6c3f852018-04-09 15:41:03 -0700391 if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "removeAnimation("
392 + taskAdapter.mTask.mTaskId + ")");
Winson Chungda876c92018-04-05 18:31:06 -0700393 taskAdapter.mTask.setCanAffectSystemUiFlags(true);
394 taskAdapter.mCapturedFinishCallback.onAnimationFinished(taskAdapter);
395 mPendingAnimations.remove(taskAdapter);
Winson Chunge2d72172018-01-25 17:46:20 +0000396 }
397
398 void startAnimation() {
Winson Chungc6c3f852018-04-09 15:41:03 -0700399 if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "startAnimation(): mPendingStart=" + mPendingStart
Winson Chungddf62972018-02-12 11:10:04 -0800400 + " mCanceled=" + mCanceled);
401 if (!mPendingStart || mCanceled) {
402 // Skip starting if we've already started or canceled the animation
Winson Chunge2d72172018-01-25 17:46:20 +0000403 return;
404 }
405 try {
Winson Chung2dc37362018-03-12 17:57:06 -0700406 final ArrayList<RemoteAnimationTarget> appAnimations = new ArrayList<>();
Winson Chunge2d72172018-01-25 17:46:20 +0000407 for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
Winson Chungda876c92018-04-05 18:31:06 -0700408 final TaskAnimationAdapter taskAdapter = mPendingAnimations.get(i);
409 final RemoteAnimationTarget target = taskAdapter.createRemoteAnimationApp();
Winson Chung2dc37362018-03-12 17:57:06 -0700410 if (target != null) {
411 appAnimations.add(target);
Winson Chungda876c92018-04-05 18:31:06 -0700412 } else {
413 removeAnimation(taskAdapter);
Winson Chung2dc37362018-03-12 17:57:06 -0700414 }
Winson Chunge2d72172018-01-25 17:46:20 +0000415 }
Winson Chungda876c92018-04-05 18:31:06 -0700416
417 // Skip the animation if there is nothing to animate
418 if (appAnimations.isEmpty()) {
Winson Chungc6c3f852018-04-09 15:41:03 -0700419 cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "startAnimation-noAppWindows");
Winson Chungda876c92018-04-05 18:31:06 -0700420 return;
421 }
422
Winson Chung2dc37362018-03-12 17:57:06 -0700423 final RemoteAnimationTarget[] appTargets = appAnimations.toArray(
424 new RemoteAnimationTarget[appAnimations.size()]);
Winson Chunge2d72172018-01-25 17:46:20 +0000425 mPendingStart = false;
Winson Chung584d6522018-02-07 23:57:38 +0000426
Winson Chung9e8b0cb2018-08-03 16:23:52 -0700427 // Perform layout if it was scheduled before to make sure that we get correct content
428 // insets for the target app window after a rotation
429 final DisplayContent displayContent = mService.mRoot.getDisplayContent(mDisplayId);
430 displayContent.performLayout(false /* initial */, false /* updateInputWindows */);
431
Winson Chung3e2980e2018-03-29 17:28:57 -0700432 final Rect minimizedHomeBounds = mTargetAppToken != null
433 && mTargetAppToken.inSplitScreenSecondaryWindowingMode()
434 ? mMinimizedHomeBounds
435 : null;
Vadim Tryshev257f86b2018-08-23 16:45:02 -0700436 final Rect contentInsets;
437 if (mTargetAppToken != null && mTargetAppToken.findMainWindow() != null) {
chaviw9c81e632018-07-31 11:17:52 -0700438 contentInsets = mTargetAppToken.findMainWindow().getContentInsets();
Vadim Tryshev257f86b2018-08-23 16:45:02 -0700439 } else {
440 // If the window for the activity had not yet been created, use the display insets.
441 mService.getStableInsets(mDisplayId, mTmpRect);
442 contentInsets = mTmpRect;
443 }
Winson Chung9e8b0cb2018-08-03 16:23:52 -0700444 mRunner.onAnimationStart(mController, appTargets, contentInsets, minimizedHomeBounds);
Winson Chungc6c3f852018-04-09 15:41:03 -0700445 if (DEBUG_RECENTS_ANIMATIONS) {
446 Slog.d(TAG, "startAnimation(): Notify animation start:");
447 for (int i = 0; i < mPendingAnimations.size(); i++) {
448 final Task task = mPendingAnimations.get(i).mTask;
449 Slog.d(TAG, "\t" + task.mTaskId);
450 }
451 }
Winson Chunge2d72172018-01-25 17:46:20 +0000452 } catch (RemoteException e) {
453 Slog.e(TAG, "Failed to start recents animation", e);
454 }
Jorim Jaggi54cff642018-03-15 15:51:32 +0100455 final SparseIntArray reasons = new SparseIntArray();
456 reasons.put(WINDOWING_MODE_FULLSCREEN, APP_TRANSITION_RECENTS_ANIM);
Yunfan Chencafc7062019-01-22 17:21:32 +0900457 mService.mAtmInternal.notifyAppTransitionStarting(reasons, SystemClock.uptimeMillis());
Winson Chunge2d72172018-01-25 17:46:20 +0000458 }
459
Winson Chungc6c3f852018-04-09 15:41:03 -0700460 void cancelAnimation(@ReorderMode int reorderMode, String reason) {
lumark54284462019-03-05 20:44:27 +0800461 cancelAnimation(reorderMode, false /* runSynchronously */, false /*screenshot */, reason);
Winson Chung65c5f992018-04-20 14:58:57 -0700462 }
463
464 void cancelAnimationSynchronously(@ReorderMode int reorderMode, String reason) {
lumark54284462019-03-05 20:44:27 +0800465 cancelAnimation(reorderMode, true /* runSynchronously */, false /* screenshot */, reason);
466 }
467
468 void cancelAnimationWithScreenShot() {
469 cancelAnimation(REORDER_KEEP_IN_PLACE, true /* sync */, true /* screenshot */,
470 "stackOrderChanged");
Winson Chung65c5f992018-04-20 14:58:57 -0700471 }
472
473 private void cancelAnimation(@ReorderMode int reorderMode, boolean runSynchronously,
lumark54284462019-03-05 20:44:27 +0800474 boolean screenshot, String reason) {
Winson Chung65c5f992018-04-20 14:58:57 -0700475 if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "cancelAnimation(): reason=" + reason
476 + " runSynchronously=" + runSynchronously);
Winson Chung65fc89a2018-02-28 08:32:12 -0800477 synchronized (mService.getWindowManagerLock()) {
478 if (mCanceled) {
479 // We've already canceled the animation
480 return;
481 }
Adrian Roos842e7882018-03-26 17:34:06 +0200482 mService.mH.removeCallbacks(mFailsafeRunnable);
Winson Chung65fc89a2018-02-28 08:32:12 -0800483 mCanceled = true;
484 try {
lumark54284462019-03-05 20:44:27 +0800485 if (screenshot) {
486 // Screen shot previous task when next task starts transition.
487 final Task task = mPendingAnimations.get(0).mTask;
488 screenshotRecentTask(task, reorderMode, runSynchronously);
489 mRunner.onAnimationCanceled(true /* deferredWithScreenshot */);
490 return;
491 }
492 mRunner.onAnimationCanceled(false /* deferredWithScreenshot */);
Winson Chung65fc89a2018-02-28 08:32:12 -0800493 } catch (RemoteException e) {
494 Slog.e(TAG, "Failed to cancel recents animation", e);
495 }
lumark54284462019-03-05 20:44:27 +0800496 // Clean up and return to the previous app
497 mCallbacks.onAnimationFinished(reorderMode, runSynchronously);
498 }
499 }
500
501 /**
502 * Cancel recents animation when the next app transition starts.
503 * <p>
504 * When we cancel the recents animation due to a stack order change, we can't just cancel it
505 * immediately as it would lead to a flicker in Launcher if we just remove the task from the
506 * leash. Instead we screenshot the previous task and replace the child of the leash with the
507 * screenshot, so that Launcher can still control the leash lifecycle & make the next app
508 * transition animate smoothly without flickering.
509 */
510 void cancelOnNextTransitionStart() {
511 mCancelOnNextTransitionStart = true;
512 }
513
514 void setCancelWithDeferredScreenshotLocked(boolean screenshot) {
515 mCancelWithDeferredScreenshot = screenshot;
516 }
517
518 boolean shouldCancelWithDeferredScreenshot() {
519 return mCancelWithDeferredScreenshot;
520 }
521
522 void onTransitionStart() {
523 if (mCanceled) {
524 return;
Winson Chunge2d72172018-01-25 17:46:20 +0000525 }
Winson Chungf557c3b2018-03-16 10:55:20 -0700526
lumark54284462019-03-05 20:44:27 +0800527 if (mCancelOnNextTransitionStart) {
528 mCancelOnNextTransitionStart = false;
529 cancelAnimationWithScreenShot();
530 }
531 }
532
533 void screenshotRecentTask(Task task, @ReorderMode int reorderMode, boolean runSynchronously) {
534 final TaskScreenshotAnimatable animatable = TaskScreenshotAnimatable.create(task);
535 if (animatable != null) {
536 mRecentScreenshotAnimator = new SurfaceAnimator(
537 animatable,
538 () -> {
539 if (DEBUG_RECENTS_ANIMATIONS) {
540 Slog.d(TAG, "mRecentScreenshotAnimator finish");
541 }
542 mCallbacks.onAnimationFinished(reorderMode, runSynchronously);
543 }, mService);
544 mRecentScreenshotAnimator.transferAnimation(task.mSurfaceAnimator);
545 }
Winson Chunge2d72172018-01-25 17:46:20 +0000546 }
547
Winson Chung6a38fca2018-03-28 17:57:09 -0700548 void cleanupAnimation(@ReorderMode int reorderMode) {
Winson Chungc6c3f852018-04-09 15:41:03 -0700549 if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG,
550 "cleanupAnimation(): Notify animation finished mPendingAnimations="
551 + mPendingAnimations.size() + " reorderMode=" + reorderMode);
Winson Chunge2d72172018-01-25 17:46:20 +0000552 for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
Winson Chungda876c92018-04-05 18:31:06 -0700553 final TaskAnimationAdapter taskAdapter = mPendingAnimations.get(i);
Winson Chung3e2980e2018-03-29 17:28:57 -0700554 if (reorderMode == REORDER_MOVE_TO_TOP || reorderMode == REORDER_KEEP_IN_PLACE) {
Winson Chungda876c92018-04-05 18:31:06 -0700555 taskAdapter.mTask.dontAnimateDimExit();
chaviw87ca63a2018-03-26 14:06:17 -0700556 }
Winson Chungda876c92018-04-05 18:31:06 -0700557 removeAnimation(taskAdapter);
Winson Chunge2d72172018-01-25 17:46:20 +0000558 }
Winson Chunge2d72172018-01-25 17:46:20 +0000559
Winson Chung7906b3e2018-05-10 10:32:39 -0700560 // Clear any pending failsafe runnables
561 mService.mH.removeCallbacks(mFailsafeRunnable);
562
Winson Chung5c91e8f2018-05-07 10:06:55 -0700563 // Clear references to the runner
Adrian Roos653c6c12018-04-09 14:12:46 -0700564 unlinkToDeathOfRunner();
Winson Chung5c91e8f2018-05-07 10:06:55 -0700565 mRunner = null;
Winson Chung7906b3e2018-05-10 10:32:39 -0700566 mCanceled = true;
Winson Chung5c91e8f2018-05-07 10:06:55 -0700567
lumark54284462019-03-05 20:44:27 +0800568 // Make sure previous animator has cleaned-up.
569 if (mRecentScreenshotAnimator != null) {
570 mRecentScreenshotAnimator.cancelAnimation();
571 mRecentScreenshotAnimator = null;
572 }
573
Winson Chungdb111ee2018-10-03 14:25:34 -0700574 // Update the input windows after the animation is complete
Arthur Hung95b38a92018-07-20 18:56:12 +0800575 final InputMonitor inputMonitor =
576 mService.mRoot.getDisplayContent(mDisplayId).getInputMonitor();
Arthur Hung95b38a92018-07-20 18:56:12 +0800577 inputMonitor.updateInputWindowsLw(true /*force*/);
Winson Chung0bb66cc2018-04-10 11:58:15 -0700578
579 // We have deferred all notifications to the target app as a part of the recents animation,
580 // so if we are actually transitioning there, notify again here
581 if (mTargetAppToken != null) {
582 if (reorderMode == REORDER_MOVE_TO_TOP || reorderMode == REORDER_KEEP_IN_PLACE) {
lumark588a3e82018-07-20 18:53:54 +0800583 mService.mRoot.getDisplayContent(mDisplayId)
584 .mAppTransition.notifyAppTransitionFinishedLocked(mTargetAppToken.token);
Winson Chung0bb66cc2018-04-10 11:58:15 -0700585 }
586 }
Winson Chunge2d72172018-01-25 17:46:20 +0000587 }
588
Adrian Roos842e7882018-03-26 17:34:06 +0200589 void scheduleFailsafe() {
590 mService.mH.postDelayed(mFailsafeRunnable, FAILSAFE_DELAY);
591 }
592
Adrian Roos653c6c12018-04-09 14:12:46 -0700593 private void linkToDeathOfRunner() throws RemoteException {
594 if (!mLinkedToDeathOfRunner) {
595 mRunner.asBinder().linkToDeath(this, 0);
596 mLinkedToDeathOfRunner = true;
597 }
598 }
599
600 private void unlinkToDeathOfRunner() {
601 if (mLinkedToDeathOfRunner) {
602 mRunner.asBinder().unlinkToDeath(this, 0);
603 mLinkedToDeathOfRunner = false;
604 }
605 }
606
Adrian Roos842e7882018-03-26 17:34:06 +0200607 @Override
608 public void binderDied() {
Winson Chungc6c3f852018-04-09 15:41:03 -0700609 cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "binderDied");
Winson Chungdb111ee2018-10-03 14:25:34 -0700610
Arthur Hung1b636fa2018-12-04 15:53:49 +0800611 synchronized (mService.getWindowManagerLock()) {
612 // Clear associated input consumers on runner death
613 final InputMonitor inputMonitor =
614 mService.mRoot.getDisplayContent(mDisplayId).getInputMonitor();
615 inputMonitor.destroyInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION);
616 }
Adrian Roos842e7882018-03-26 17:34:06 +0200617 }
618
Winson Chunge2d72172018-01-25 17:46:20 +0000619 void checkAnimationReady(WallpaperController wallpaperController) {
620 if (mPendingStart) {
Winson Chung3e2980e2018-03-29 17:28:57 -0700621 final boolean wallpaperReady = !isTargetOverWallpaper()
Winson Chunge2d72172018-01-25 17:46:20 +0000622 || (wallpaperController.getWallpaperTarget() != null
623 && wallpaperController.wallpaperTransitionReady());
624 if (wallpaperReady) {
625 mService.getRecentsAnimationController().startAnimation();
626 }
627 }
628 }
629
Winson Chungf557c3b2018-03-16 10:55:20 -0700630 boolean isSplitScreenMinimized() {
631 return mSplitScreenMinimized;
632 }
633
Winson Chunge2d72172018-01-25 17:46:20 +0000634 boolean isWallpaperVisible(WindowState w) {
Winson Chung3e2980e2018-03-29 17:28:57 -0700635 return w != null && w.mAppToken != null && mTargetAppToken == w.mAppToken
636 && isTargetOverWallpaper();
Winson Chunge2d72172018-01-25 17:46:20 +0000637 }
638
Winson Chungdb111ee2018-10-03 14:25:34 -0700639 /**
640 * @return Whether to use the input consumer to override app input to route home/recents.
641 */
642 boolean shouldApplyInputConsumer(AppWindowToken appToken) {
643 // Only apply the input consumer if it is enabled, it is not the target (home/recents)
644 // being revealed with the transition, and we are actively animating the app as a part of
645 // the animation
646 return mInputConsumerEnabled && mTargetAppToken != appToken && isAnimatingApp(appToken);
Winson Chunga89ffed2018-01-25 17:46:11 +0000647 }
648
Arthur Hung95b38a92018-07-20 18:56:12 +0800649 boolean updateInputConsumerForApp(InputWindowHandle inputWindowHandle,
Winson Chunga89ffed2018-01-25 17:46:11 +0000650 boolean hasFocus) {
Winson Chung3e2980e2018-03-29 17:28:57 -0700651 // Update the input consumer touchable region to match the target app main window
652 final WindowState targetAppMainWindow = mTargetAppToken != null
653 ? mTargetAppToken.findMainWindow()
Winson Chunga89ffed2018-01-25 17:46:11 +0000654 : null;
Winson Chung3e2980e2018-03-29 17:28:57 -0700655 if (targetAppMainWindow != null) {
656 targetAppMainWindow.getBounds(mTmpRect);
Arthur Hung95b38a92018-07-20 18:56:12 +0800657 inputWindowHandle.hasFocus = hasFocus;
658 inputWindowHandle.touchableRegion.set(mTmpRect);
Winson Chunga89ffed2018-01-25 17:46:11 +0000659 return true;
660 }
661 return false;
662 }
663
Winson Chung0bb66cc2018-04-10 11:58:15 -0700664 boolean isTargetApp(AppWindowToken token) {
665 return mTargetAppToken != null && token == mTargetAppToken;
666 }
667
Winson Chung3e2980e2018-03-29 17:28:57 -0700668 private boolean isTargetOverWallpaper() {
669 if (mTargetAppToken == null) {
Winson Chunge2d72172018-01-25 17:46:20 +0000670 return false;
671 }
Winson Chung3e2980e2018-03-29 17:28:57 -0700672 return mTargetAppToken.windowsCanBeWallpaperTarget();
Winson Chunge2d72172018-01-25 17:46:20 +0000673 }
674
Winson Chungd41f71d2018-03-16 15:26:07 -0700675 boolean isAnimatingTask(Task task) {
676 for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
677 if (task == mPendingAnimations.get(i).mTask) {
678 return true;
679 }
680 }
681 return false;
682 }
683
Winson Chunga89ffed2018-01-25 17:46:11 +0000684 private boolean isAnimatingApp(AppWindowToken appToken) {
Winson Chunge2d72172018-01-25 17:46:20 +0000685 for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
686 final Task task = mPendingAnimations.get(i).mTask;
687 for (int j = task.getChildCount() - 1; j >= 0; j--) {
688 final AppWindowToken app = task.getChildAt(j);
689 if (app == appToken) {
690 return true;
691 }
692 }
693 }
694 return false;
695 }
696
Winson Chungda876c92018-04-05 18:31:06 -0700697 @VisibleForTesting
698 class TaskAnimationAdapter implements AnimationAdapter {
Winson Chunge2d72172018-01-25 17:46:20 +0000699
Vadim Tryshev593e9562018-03-08 17:15:45 -0800700 private final Task mTask;
Winson Chunge2d72172018-01-25 17:46:20 +0000701 private SurfaceControl mCapturedLeash;
702 private OnAnimationFinishedCallback mCapturedFinishCallback;
Vadim Tryshev593e9562018-03-08 17:15:45 -0800703 private final boolean mIsRecentTaskInvisible;
Jorim Jaggif75d1612018-02-27 15:05:21 +0100704 private RemoteAnimationTarget mTarget;
Winson Chungd41f71d2018-03-16 15:26:07 -0700705 private final Point mPosition = new Point();
706 private final Rect mBounds = new Rect();
Winson Chunge2d72172018-01-25 17:46:20 +0000707
Vadim Tryshev593e9562018-03-08 17:15:45 -0800708 TaskAnimationAdapter(Task task, boolean isRecentTaskInvisible) {
Winson Chunge2d72172018-01-25 17:46:20 +0000709 mTask = task;
Vadim Tryshev593e9562018-03-08 17:15:45 -0800710 mIsRecentTaskInvisible = isRecentTaskInvisible;
Winson Chungd41f71d2018-03-16 15:26:07 -0700711 final WindowContainer container = mTask.getParent();
Evan Roskyed6767f2018-10-26 17:21:06 -0700712 container.getRelativeDisplayedPosition(mPosition);
713 mBounds.set(container.getDisplayedBounds());
Winson Chunge2d72172018-01-25 17:46:20 +0000714 }
715
716 RemoteAnimationTarget createRemoteAnimationApp() {
Winson Chung173020c2018-05-04 15:36:47 -0700717 final AppWindowToken topApp = mTask.getTopVisibleAppToken();
718 final WindowState mainWindow = topApp != null
719 ? topApp.findMainWindow()
720 : null;
Winson Chung2dc37362018-03-12 17:57:06 -0700721 if (mainWindow == null) {
722 return null;
723 }
chaviw9c81e632018-07-31 11:17:52 -0700724 final Rect insets = new Rect();
725 mainWindow.getContentInsets(insets);
Jorim Jaggi817ebdd2018-03-26 15:46:01 +0200726 InsetUtils.addInsets(insets, mainWindow.mAppToken.getLetterboxInsets());
Winson Chung732446a2018-09-19 13:15:17 -0700727 final int mode = topApp.getActivityType() == mTargetActivityType
728 ? MODE_OPENING
729 : MODE_CLOSING;
730 mTarget = new RemoteAnimationTarget(mTask.mTaskId, mode, mCapturedLeash,
Winson Chung173020c2018-05-04 15:36:47 -0700731 !topApp.fillsParent(), mainWindow.mWinAnimator.mLastClipRect,
Winson Chungd41f71d2018-03-16 15:26:07 -0700732 insets, mTask.getPrefixOrderIndex(), mPosition, mBounds,
Evan Rosky2289ba12018-11-19 18:28:18 -0800733 mTask.getWindowConfiguration(), mIsRecentTaskInvisible, null, null);
Jorim Jaggif75d1612018-02-27 15:05:21 +0100734 return mTarget;
Winson Chunge2d72172018-01-25 17:46:20 +0000735 }
736
737 @Override
Jorim Jaggi82c17862018-02-21 17:50:18 +0100738 public boolean getShowWallpaper() {
739 return false;
740 }
741
742 @Override
Winson Chunge2d72172018-01-25 17:46:20 +0000743 public int getBackgroundColor() {
744 return 0;
745 }
746
747 @Override
748 public void startAnimation(SurfaceControl animationLeash, Transaction t,
749 OnAnimationFinishedCallback finishCallback) {
Winson Chung65a05862018-04-12 17:14:50 -0700750 // Restore z-layering, position and stack crop until client has a chance to modify it.
751 t.setLayer(animationLeash, mTask.getPrefixOrderIndex());
Winson Chungd41f71d2018-03-16 15:26:07 -0700752 t.setPosition(animationLeash, mPosition.x, mPosition.y);
Winson Chung65a05862018-04-12 17:14:50 -0700753 mTmpRect.set(mBounds);
754 mTmpRect.offsetTo(0, 0);
755 t.setWindowCrop(animationLeash, mTmpRect);
Winson Chunge2d72172018-01-25 17:46:20 +0000756 mCapturedLeash = animationLeash;
757 mCapturedFinishCallback = finishCallback;
758 }
759
760 @Override
761 public void onAnimationCancelled(SurfaceControl animationLeash) {
Winson Chungc6c3f852018-04-09 15:41:03 -0700762 cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "taskAnimationAdapterCanceled");
Winson Chunge2d72172018-01-25 17:46:20 +0000763 }
764
765 @Override
766 public long getDurationHint() {
767 return 0;
768 }
769
770 @Override
771 public long getStatusBarTransitionsStartTime() {
772 return SystemClock.uptimeMillis();
773 }
Jorim Jaggif75d1612018-02-27 15:05:21 +0100774
775 @Override
776 public void dump(PrintWriter pw, String prefix) {
777 pw.print(prefix); pw.println("task=" + mTask);
778 if (mTarget != null) {
779 pw.print(prefix); pw.println("Target:");
780 mTarget.dump(pw, prefix + " ");
781 } else {
782 pw.print(prefix); pw.println("Target: null");
783 }
Winson Chungc6c3f852018-04-09 15:41:03 -0700784 pw.println("mIsRecentTaskInvisible=" + mIsRecentTaskInvisible);
785 pw.println("mPosition=" + mPosition);
786 pw.println("mBounds=" + mBounds);
787 pw.println("mIsRecentTaskInvisible=" + mIsRecentTaskInvisible);
Jorim Jaggif75d1612018-02-27 15:05:21 +0100788 }
789
790 @Override
791 public void writeToProto(ProtoOutputStream proto) {
792 final long token = proto.start(REMOTE);
793 if (mTarget != null) {
794 mTarget.writeToProto(proto, TARGET);
795 }
796 proto.end(token);
797 }
Winson Chunge2d72172018-01-25 17:46:20 +0000798 }
799
800 public void dump(PrintWriter pw, String prefix) {
801 final String innerPrefix = prefix + " ";
802 pw.print(prefix); pw.println(RecentsAnimationController.class.getSimpleName() + ":");
803 pw.print(innerPrefix); pw.println("mPendingStart=" + mPendingStart);
Winson Chungdb111ee2018-10-03 14:25:34 -0700804 pw.print(innerPrefix); pw.println("mPendingAnimations=" + mPendingAnimations.size());
Winson Chungc6c3f852018-04-09 15:41:03 -0700805 pw.print(innerPrefix); pw.println("mCanceled=" + mCanceled);
806 pw.print(innerPrefix); pw.println("mInputConsumerEnabled=" + mInputConsumerEnabled);
807 pw.print(innerPrefix); pw.println("mSplitScreenMinimized=" + mSplitScreenMinimized);
Winson Chung3e2980e2018-03-29 17:28:57 -0700808 pw.print(innerPrefix); pw.println("mTargetAppToken=" + mTargetAppToken);
Winson Chungc6c3f852018-04-09 15:41:03 -0700809 pw.print(innerPrefix); pw.println("isTargetOverWallpaper=" + isTargetOverWallpaper());
Winson Chunge2d72172018-01-25 17:46:20 +0000810 }
811}