• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 
17 package com.android.server.wm;
18 
19 import static android.app.ActivityManager.StackId;
20 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
21 import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
22 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
23 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
24 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
25 import static android.view.Display.DEFAULT_DISPLAY;
26 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
27 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
28 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
29 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
30 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
31 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
32 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
33 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
34 import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
35 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
36 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
37 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
38 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
39 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
40 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
41 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
42 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
43 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
44 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
45 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
46 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
47 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
48 import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
49 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
50 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
51 import static com.android.server.wm.WindowManagerService.logWithStack;
52 
53 import android.annotation.NonNull;
54 import android.app.Activity;
55 import android.content.res.Configuration;
56 import android.graphics.Rect;
57 import android.os.Binder;
58 import android.os.Debug;
59 import android.os.IBinder;
60 import android.os.SystemClock;
61 import android.util.Slog;
62 import android.view.IApplicationToken;
63 import android.view.SurfaceControl;
64 import android.view.WindowManager;
65 import android.view.WindowManager.LayoutParams;
66 import android.view.WindowManagerPolicy.StartingSurface;
67 
68 import com.android.internal.util.ToBooleanFunction;
69 import com.android.server.input.InputApplicationHandle;
70 import com.android.server.wm.WindowManagerService.H;
71 
72 import java.io.PrintWriter;
73 import java.util.ArrayDeque;
74 import java.util.ArrayList;
75 
76 class AppTokenList extends ArrayList<AppWindowToken> {
77 }
78 
79 /**
80  * Version of WindowToken that is specifically for a particular application (or
81  * really activity) that is displaying windows.
82  */
83 class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener {
84     private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM;
85 
86     // Non-null only for application tokens.
87     final IApplicationToken appToken;
88 
89     @NonNull final AppWindowAnimator mAppAnimator;
90 
91     final boolean mVoiceInteraction;
92 
93     /** @see WindowContainer#fillsParent() */
94     private boolean mFillsParent;
95     boolean layoutConfigChanges;
96     boolean mShowForAllUsers;
97     int mTargetSdk;
98 
99     // Flag set while reparenting to prevent actions normally triggered by an individual parent
100     // change.
101     private boolean mReparenting;
102 
103     // True if we are current in the process of removing this app token from the display
104     private boolean mRemovingFromDisplay = false;
105 
106     // The input dispatching timeout for this application token in nanoseconds.
107     long mInputDispatchingTimeoutNanos;
108 
109     // These are used for determining when all windows associated with
110     // an activity have been drawn, so they can be made visible together
111     // at the same time.
112     // initialize so that it doesn't match mTransactionSequence which is an int.
113     private long mLastTransactionSequence = Long.MIN_VALUE;
114     private int mNumInterestingWindows;
115     private int mNumDrawnWindows;
116     boolean inPendingTransaction;
117     boolean allDrawn;
118     // Set to true when this app creates a surface while in the middle of an animation. In that
119     // case do not clear allDrawn until the animation completes.
120     boolean deferClearAllDrawn;
121 
122     /**
123      * These are to track the app's real drawing status if there were no saved surfaces.
124      * @see #updateDrawnWindowStates
125      */
126     boolean allDrawnExcludingSaved;
127     private int mNumInterestingWindowsExcludingSaved;
128     private int mNumDrawnWindowsExcludingSaved;
129 
130     // Is this window's surface needed?  This is almost like hidden, except
131     // it will sometimes be true a little earlier: when the token has
132     // been shown, but is still waiting for its app transition to execute
133     // before making its windows shown.
134     boolean hiddenRequested;
135 
136     // Have we told the window clients to hide themselves?
137     private boolean mClientHidden;
138 
139     // If true we will defer setting mClientHidden to true and reporting to the client that it is
140     // hidden.
141     boolean mDeferHidingClient;
142 
143     // Last visibility state we reported to the app token.
144     boolean reportedVisible;
145 
146     // Last drawn state we reported to the app token.
147     private boolean reportedDrawn;
148 
149     // Set to true when the token has been removed from the window mgr.
150     boolean removed;
151 
152     // Information about an application starting window if displayed.
153     StartingData startingData;
154     WindowState startingWindow;
155     StartingSurface startingSurface;
156     boolean startingDisplayed;
157     boolean startingMoved;
158     // True if the hidden state of this token was forced to false due to a transferred starting
159     // window.
160     private boolean mHiddenSetFromTransferredStartingWindow;
161     boolean firstWindowDrawn;
162     private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
163             new WindowState.UpdateReportedVisibilityResults();
164 
165     // Input application handle used by the input dispatcher.
166     final InputApplicationHandle mInputApplicationHandle;
167 
168     // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
169     boolean mIsExiting;
170 
171     boolean mLaunchTaskBehind;
172     boolean mEnteringAnimation;
173 
174     private boolean mAlwaysFocusable;
175 
176     boolean mAppStopped;
177     int mRotationAnimationHint;
178     private int mPendingRelaunchCount;
179 
180     private boolean mLastContainsShowWhenLockedWindow;
181     private boolean mLastContainsDismissKeyguardWindow;
182 
183     // The bounds of this activity. Mainly used for aspect-ratio compatibility.
184     // TODO(b/36505427): Every level on WindowContainer now has bounds information, which directly
185     // affects the configuration. We should probably move this into that class.
186     private final Rect mBounds = new Rect();
187 
188     ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
189     ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
190 
191     private boolean mDisablePreviewScreenshots;
192 
193     Task mLastParent;
194 
195     /**
196      * See {@link #canTurnScreenOn()}
197      */
198     private boolean mCanTurnScreenOn = true;
199 
AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint, int configChanges, boolean launchTaskBehind, boolean alwaysFocusable, AppWindowContainerController controller, Configuration overrideConfig, Rect bounds)200     AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction,
201             DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen,
202             boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint,
203             int configChanges, boolean launchTaskBehind, boolean alwaysFocusable,
204             AppWindowContainerController controller, Configuration overrideConfig, Rect bounds) {
205         this(service, token, voiceInteraction, dc, fullscreen, overrideConfig, bounds);
206         setController(controller);
207         mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
208         mShowForAllUsers = showForAllUsers;
209         mTargetSdk = targetSdk;
210         mOrientation = orientation;
211         layoutConfigChanges = (configChanges & (CONFIG_SCREEN_SIZE | CONFIG_ORIENTATION)) != 0;
212         mLaunchTaskBehind = launchTaskBehind;
213         mAlwaysFocusable = alwaysFocusable;
214         mRotationAnimationHint = rotationAnimationHint;
215 
216         // Application tokens start out hidden.
217         hidden = true;
218         hiddenRequested = true;
219     }
220 
AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction, DisplayContent dc, boolean fillsParent, Configuration overrideConfig, Rect bounds)221     AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction,
222             DisplayContent dc, boolean fillsParent, Configuration overrideConfig, Rect bounds) {
223         super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
224                 false /* ownerCanManageAppTokens */);
225         appToken = token;
226         mVoiceInteraction = voiceInteraction;
227         mFillsParent = fillsParent;
228         mInputApplicationHandle = new InputApplicationHandle(this);
229         mAppAnimator = new AppWindowAnimator(this, service);
230         if (overrideConfig != null) {
231             onOverrideConfigurationChanged(overrideConfig);
232         }
233         if (bounds != null) {
234             mBounds.set(bounds);
235         }
236     }
237 
onOverrideConfigurationChanged(Configuration overrideConfiguration, Rect bounds)238     void onOverrideConfigurationChanged(Configuration overrideConfiguration, Rect bounds) {
239         onOverrideConfigurationChanged(overrideConfiguration);
240         if (mBounds.equals(bounds)) {
241             return;
242         }
243         // TODO(b/36505427): If bounds is in WC, then we can automatically call onResize() when set.
244         mBounds.set(bounds);
245         onResize();
246     }
247 
getBounds(Rect outBounds)248     void getBounds(Rect outBounds) {
249         outBounds.set(mBounds);
250     }
251 
hasBounds()252     boolean hasBounds() {
253         return !mBounds.isEmpty();
254     }
255 
onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator)256     void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
257         firstWindowDrawn = true;
258 
259         // We now have a good window to show, remove dead placeholders
260         removeDeadWindows();
261 
262         if (startingWindow != null) {
263             if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting "
264                     + win.mToken + ": first real window is shown, no animation");
265             // If this initial window is animating, stop it -- we will do an animation to reveal
266             // it from behind the starting window, so there is no need for it to also be doing its
267             // own stuff.
268             winAnimator.clearAnimation();
269             if (getController() != null) {
270                 getController().removeStartingWindow();
271             }
272         }
273         updateReportedVisibilityLocked();
274     }
275 
updateReportedVisibilityLocked()276     void updateReportedVisibilityLocked() {
277         if (appToken == null) {
278             return;
279         }
280 
281         if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
282         final int count = mChildren.size();
283 
284         mReportedVisibilityResults.reset();
285 
286         for (int i = 0; i < count; i++) {
287             final WindowState win = mChildren.get(i);
288             win.updateReportedVisibility(mReportedVisibilityResults);
289         }
290 
291         int numInteresting = mReportedVisibilityResults.numInteresting;
292         int numVisible = mReportedVisibilityResults.numVisible;
293         int numDrawn = mReportedVisibilityResults.numDrawn;
294         boolean nowGone = mReportedVisibilityResults.nowGone;
295 
296         boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
297         boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !hidden;
298         if (!nowGone) {
299             // If the app is not yet gone, then it can only become visible/drawn.
300             if (!nowDrawn) {
301                 nowDrawn = reportedDrawn;
302             }
303             if (!nowVisible) {
304                 nowVisible = reportedVisible;
305             }
306         }
307         if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
308                 + numInteresting + " visible=" + numVisible);
309         final AppWindowContainerController controller = getController();
310         if (nowDrawn != reportedDrawn) {
311             if (nowDrawn) {
312                 if (controller != null) {
313                     controller.reportWindowsDrawn();
314                 }
315             }
316             reportedDrawn = nowDrawn;
317         }
318         if (nowVisible != reportedVisible) {
319             if (DEBUG_VISIBILITY) Slog.v(TAG,
320                     "Visibility changed in " + this + ": vis=" + nowVisible);
321             reportedVisible = nowVisible;
322             if (controller != null) {
323                 if (nowVisible) {
324                     controller.reportWindowsVisible();
325                 } else {
326                     controller.reportWindowsGone();
327                 }
328             }
329         }
330     }
331 
isClientHidden()332     boolean isClientHidden() {
333         return mClientHidden;
334     }
335 
setClientHidden(boolean hideClient)336     void setClientHidden(boolean hideClient) {
337         if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
338             return;
339         }
340         mClientHidden = hideClient;
341         sendAppVisibilityToClients();
342     }
343 
setVisibility(WindowManager.LayoutParams lp, boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction)344     boolean setVisibility(WindowManager.LayoutParams lp,
345             boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
346 
347         boolean delayed = false;
348         inPendingTransaction = false;
349         // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
350         // been set by the app now.
351         mHiddenSetFromTransferredStartingWindow = false;
352         setClientHidden(!visible);
353 
354         // Allow for state changes and animation to be applied if:
355         // * token is transitioning visibility state
356         // * or the token was marked as hidden and is exiting before we had a chance to play the
357         // transition animation
358         // * or this is an opening app and windows are being replaced.
359         boolean visibilityChanged = false;
360         if (hidden == visible || (hidden && mIsExiting) || (visible && waitingForReplacement())) {
361             final AccessibilityController accessibilityController = mService.mAccessibilityController;
362             boolean changed = false;
363             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
364                     "Changing app " + this + " hidden=" + hidden + " performLayout=" + performLayout);
365 
366             boolean runningAppAnimation = false;
367 
368             if (mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
369                 mAppAnimator.setNullAnimation();
370             }
371             if (transit != AppTransition.TRANSIT_UNSET) {
372                 if (mService.applyAnimationLocked(this, lp, transit, visible, isVoiceInteraction)) {
373                     delayed = runningAppAnimation = true;
374                 }
375                 final WindowState window = findMainWindow();
376                 //TODO (multidisplay): Magnification is supported only for the default display.
377                 if (window != null && accessibilityController != null
378                         && getDisplayContent().getDisplayId() == DEFAULT_DISPLAY) {
379                     accessibilityController.onAppWindowTransitionLocked(window, transit);
380                 }
381                 changed = true;
382             }
383 
384             final int windowsCount = mChildren.size();
385             for (int i = 0; i < windowsCount; i++) {
386                 final WindowState win = mChildren.get(i);
387                 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
388             }
389 
390             hidden = hiddenRequested = !visible;
391             visibilityChanged = true;
392             if (!visible) {
393                 stopFreezingScreen(true, true);
394             } else {
395                 // If we are being set visible, and the starting window is not yet displayed,
396                 // then make sure it doesn't get displayed.
397                 if (startingWindow != null && !startingWindow.isDrawnLw()) {
398                     startingWindow.mPolicyVisibility = false;
399                     startingWindow.mPolicyVisibilityAfterAnim = false;
400                 }
401 
402                 // We are becoming visible, so better freeze the screen with the windows that are
403                 // getting visible so we also wait for them.
404                 forAllWindows(mService::makeWindowFreezingScreenIfNeededLocked, true);
405             }
406 
407             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setVisibility: " + this
408                     + ": hidden=" + hidden + " hiddenRequested=" + hiddenRequested);
409 
410             if (changed) {
411                 mService.mInputMonitor.setUpdateInputWindowsNeededLw();
412                 if (performLayout) {
413                     mService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
414                             false /*updateInputWindows*/);
415                     mService.mWindowPlacerLocked.performSurfacePlacement();
416                 }
417                 mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
418             }
419         }
420 
421         if (mAppAnimator.animation != null) {
422             delayed = true;
423         }
424 
425         for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
426             if ((mChildren.get(i)).isWindowAnimationSet()) {
427                 delayed = true;
428             }
429         }
430 
431         if (visibilityChanged) {
432             if (visible && !delayed) {
433                 // The token was made immediately visible, there will be no entrance animation.
434                 // We need to inform the client the enter animation was finished.
435                 mEnteringAnimation = true;
436                 mService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(token);
437             }
438 
439             // If we are hidden but there is no delay needed we immediately
440             // apply the Surface transaction so that the ActivityManager
441             // can have some guarantee on the Surface state following
442             // setting the visibility. This captures cases like dismissing
443             // the docked or pinned stack where there is no app transition.
444             //
445             // In the case of a "Null" animation, there will be
446             // no animation but there will still be a transition set.
447             // We still need to delay hiding the surface such that it
448             // can be synchronized with showing the next surface in the transition.
449             if (hidden && !delayed && !mService.mAppTransition.isTransitionSet()) {
450                 SurfaceControl.openTransaction();
451                 for (int i = mChildren.size() - 1; i >= 0; i--) {
452                     mChildren.get(i).mWinAnimator.hide("immediately hidden");
453                 }
454                 SurfaceControl.closeTransaction();
455             }
456 
457             if (!mService.mClosingApps.contains(this) && !mService.mOpeningApps.contains(this)) {
458                 // The token is not closing nor opening, so even if there is an animation set, that
459                 // doesn't mean that it goes through the normal app transition cycle so we have
460                 // to inform the docked controller about visibility change.
461                 // TODO(multi-display): notify docked divider on all displays where visibility was
462                 // affected.
463                 mService.getDefaultDisplayContentLocked().getDockedDividerController()
464                         .notifyAppVisibilityChanged();
465                 mService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
466             }
467         }
468 
469         return delayed;
470     }
471 
472     /**
473      * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
474      *         true.
475      */
getTopFullscreenWindow()476     WindowState getTopFullscreenWindow() {
477         for (int i = mChildren.size() - 1; i >= 0; i--) {
478             final WindowState win = mChildren.get(i);
479             if (win != null && win.mAttrs.isFullscreen()) {
480                 return win;
481             }
482         }
483         return null;
484     }
485 
findMainWindow()486     WindowState findMainWindow() {
487         WindowState candidate = null;
488         int j = mChildren.size();
489         while (j > 0) {
490             j--;
491             final WindowState win = mChildren.get(j);
492             final int type = win.mAttrs.type;
493             // No need to loop through child window as base application and starting types can't be
494             // child windows.
495             if (type == TYPE_BASE_APPLICATION || type == TYPE_APPLICATION_STARTING) {
496                 // In cases where there are multiple windows, we prefer the non-exiting window. This
497                 // happens for example when replacing windows during an activity relaunch. When
498                 // constructing the animation, we want the new window, not the exiting one.
499                 if (win.mAnimatingExit) {
500                     candidate = win;
501                 } else {
502                     return win;
503                 }
504             }
505         }
506         return candidate;
507     }
508 
windowsAreFocusable()509     boolean windowsAreFocusable() {
510         return StackId.canReceiveKeys(getTask().mStack.mStackId) || mAlwaysFocusable;
511     }
512 
getController()513     AppWindowContainerController getController() {
514         final WindowContainerController controller = super.getController();
515         return controller != null ? (AppWindowContainerController) controller : null;
516     }
517 
518     @Override
isVisible()519     boolean isVisible() {
520         // If the app token isn't hidden then it is considered visible and there is no need to check
521         // its children windows to see if they are visible.
522         return !hidden;
523     }
524 
525     @Override
removeImmediately()526     void removeImmediately() {
527         onRemovedFromDisplay();
528         super.removeImmediately();
529     }
530 
531     @Override
removeIfPossible()532     void removeIfPossible() {
533         mIsExiting = false;
534         removeAllWindowsIfPossible();
535         removeImmediately();
536     }
537 
538     @Override
checkCompleteDeferredRemoval()539     boolean checkCompleteDeferredRemoval() {
540         if (mIsExiting) {
541             removeIfPossible();
542         }
543         return super.checkCompleteDeferredRemoval();
544     }
545 
onRemovedFromDisplay()546     void onRemovedFromDisplay() {
547         if (mRemovingFromDisplay) {
548             return;
549         }
550         mRemovingFromDisplay = true;
551 
552         if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
553 
554         boolean delayed = setVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
555 
556         mService.mOpeningApps.remove(this);
557         mService.mUnknownAppVisibilityController.appRemovedOrHidden(this);
558         mService.mTaskSnapshotController.onAppRemoved(this);
559         waitingToShow = false;
560         if (mService.mClosingApps.contains(this)) {
561             delayed = true;
562         } else if (mService.mAppTransition.isTransitionSet()) {
563             mService.mClosingApps.add(this);
564             delayed = true;
565         }
566 
567         if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
568                 + " animation=" + mAppAnimator.animation + " animating=" + mAppAnimator.animating);
569 
570         if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
571                 + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
572 
573         if (startingData != null && getController() != null) {
574             getController().removeStartingWindow();
575         }
576 
577         // If this window was animating, then we need to ensure that the app transition notifies
578         // that animations have completed in WMS.handleAnimatingStoppedAndTransitionLocked(), so
579         // add to that list now
580         if (mAppAnimator.animating) {
581             mService.mNoAnimationNotifyOnTransitionFinished.add(token);
582         }
583 
584         final TaskStack stack = getStack();
585         if (delayed && !isEmpty()) {
586             // set the token aside because it has an active animation to be finished
587             if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
588                     "removeAppToken make exiting: " + this);
589             if (stack != null) {
590                 stack.mExitingAppTokens.add(this);
591             }
592             mIsExiting = true;
593         } else {
594             // Make sure there is no animation running on this token, so any windows associated
595             // with it will be removed as soon as their animations are complete
596             mAppAnimator.clearAnimation();
597             mAppAnimator.animating = false;
598             if (stack != null) {
599                 stack.mExitingAppTokens.remove(this);
600             }
601             removeIfPossible();
602         }
603 
604         removed = true;
605         stopFreezingScreen(true, true);
606 
607         if (mService.mFocusedApp == this) {
608             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this);
609             mService.mFocusedApp = null;
610             mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
611             mService.mInputMonitor.setFocusedAppLw(null);
612         }
613 
614         if (!delayed) {
615             updateReportedVisibilityLocked();
616         }
617 
618         mRemovingFromDisplay = false;
619     }
620 
clearAnimatingFlags()621     void clearAnimatingFlags() {
622         boolean wallpaperMightChange = false;
623         for (int i = mChildren.size() - 1; i >= 0; i--) {
624             final WindowState win = mChildren.get(i);
625             wallpaperMightChange |= win.clearAnimatingFlags();
626         }
627         if (wallpaperMightChange) {
628             requestUpdateWallpaperIfNeeded();
629         }
630     }
631 
destroySurfaces()632     void destroySurfaces() {
633         destroySurfaces(false /*cleanupOnResume*/);
634     }
635 
636     /**
637      * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
638      * the client has finished with them.
639      *
640      * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
641      * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
642      * others so that they are ready to be reused. If set to false (common case), destroy all
643      * surfaces that's eligible, if the app is already stopped.
644      */
destroySurfaces(boolean cleanupOnResume)645     private void destroySurfaces(boolean cleanupOnResume) {
646         boolean destroyedSomething = false;
647         for (int i = mChildren.size() - 1; i >= 0; i--) {
648             final WindowState win = mChildren.get(i);
649             destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
650         }
651         if (destroyedSomething) {
652             final DisplayContent dc = getDisplayContent();
653             dc.assignWindowLayers(true /*setLayoutNeeded*/);
654         }
655     }
656 
657     /**
658      * Notify that the app is now resumed, and it was not stopped before, perform a clean
659      * up of the surfaces
660      */
notifyAppResumed(boolean wasStopped)661     void notifyAppResumed(boolean wasStopped) {
662         if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
663                 + " " + this);
664         mAppStopped = false;
665         // Allow the window to turn the screen on once the app is resumed again.
666         setCanTurnScreenOn(true);
667         if (!wasStopped) {
668             destroySurfaces(true /*cleanupOnResume*/);
669         }
670     }
671 
672     /**
673      * Notify that the app has stopped, and it is okay to destroy any surfaces which were
674      * keeping alive in case they were still being used.
675      */
notifyAppStopped()676     void notifyAppStopped() {
677         if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
678         mAppStopped = true;
679         destroySurfaces();
680         // Remove any starting window that was added for this app if they are still around.
681         if (getController() != null) {
682             getController().removeStartingWindow();
683         }
684     }
685 
686     /**
687      * Checks whether we should save surfaces for this app.
688      *
689      * @return true if the surfaces should be saved, false otherwise.
690      */
shouldSaveSurface()691     boolean shouldSaveSurface() {
692         // We want to save surface if the app's windows are "allDrawn".
693         // (If we started entering animation early with saved surfaces, allDrawn
694         // should have been restored to true. So we'll save again in that case
695         // even if app didn't actually finish drawing.)
696         return allDrawn;
697     }
698 
canRestoreSurfaces()699     private boolean canRestoreSurfaces() {
700         for (int i = mChildren.size() -1; i >= 0; i--) {
701             final WindowState w = mChildren.get(i);
702             if (w.canRestoreSurface()) {
703                 return true;
704             }
705         }
706         return false;
707     }
708 
clearWasVisibleBeforeClientHidden()709     private void clearWasVisibleBeforeClientHidden() {
710         for (int i = mChildren.size() - 1; i >= 0; i--) {
711             final WindowState w = mChildren.get(i);
712             w.clearWasVisibleBeforeClientHidden();
713         }
714     }
715 
716     /**
717      * Whether the app has some window that is invisible in layout, but
718      * animating with saved surface.
719      */
isAnimatingInvisibleWithSavedSurface()720     boolean isAnimatingInvisibleWithSavedSurface() {
721         for (int i = mChildren.size() - 1; i >= 0; i--) {
722             final WindowState w = mChildren.get(i);
723             if (w.isAnimatingInvisibleWithSavedSurface()) {
724                 return true;
725             }
726         }
727         return false;
728     }
729 
730     /**
731      * Hide all window surfaces that's still invisible in layout but animating
732      * with a saved surface, and mark them destroying.
733      */
stopUsingSavedSurfaceLocked()734     void stopUsingSavedSurfaceLocked() {
735         for (int i = mChildren.size() - 1; i >= 0; i--) {
736             final WindowState w = mChildren.get(i);
737             w.stopUsingSavedSurface();
738         }
739         destroySurfaces();
740     }
741 
markSavedSurfaceExiting()742     void markSavedSurfaceExiting() {
743         for (int i = mChildren.size() - 1; i >= 0; i--) {
744             final WindowState w = mChildren.get(i);
745             w.markSavedSurfaceExiting();
746         }
747     }
748 
restoreSavedSurfaceForInterestingWindows()749     void restoreSavedSurfaceForInterestingWindows() {
750         if (!canRestoreSurfaces()) {
751             clearWasVisibleBeforeClientHidden();
752             return;
753         }
754 
755         // Check if all interesting windows are drawn and we can mark allDrawn=true.
756         int interestingNotDrawn = -1;
757 
758         for (int i = mChildren.size() - 1; i >= 0; i--) {
759             final WindowState w = mChildren.get(i);
760             interestingNotDrawn = w.restoreSavedSurfaceForInterestingWindow();
761         }
762 
763         if (!allDrawn) {
764             allDrawn = (interestingNotDrawn == 0);
765             if (allDrawn) {
766                 mService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
767             }
768         }
769         clearWasVisibleBeforeClientHidden();
770 
771         if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.d(TAG,
772                 "restoreSavedSurfaceForInterestingWindows: " + this + " allDrawn=" + allDrawn
773                 + " interestingNotDrawn=" + interestingNotDrawn);
774     }
775 
destroySavedSurfaces()776     void destroySavedSurfaces() {
777         for (int i = mChildren.size() - 1; i >= 0; i--) {
778             final WindowState win = mChildren.get(i);
779             win.destroySavedSurface();
780         }
781     }
782 
clearAllDrawn()783     void clearAllDrawn() {
784         allDrawn = false;
785         deferClearAllDrawn = false;
786         allDrawnExcludingSaved = false;
787     }
788 
getTask()789     Task getTask() {
790         return (Task) getParent();
791     }
792 
getStack()793     TaskStack getStack() {
794         final Task task = getTask();
795         if (task != null) {
796             return task.mStack;
797         } else {
798             return null;
799         }
800     }
801 
802     @Override
onParentSet()803     void onParentSet() {
804         super.onParentSet();
805 
806         final Task task = getTask();
807 
808         // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
809         // access visual elements like the {@link DisplayContent}. We must remove any associations
810         // such as animations.
811         if (!mReparenting) {
812             if (task == null) {
813                 // It is possible we have been marked as a closing app earlier. We must remove ourselves
814                 // from this list so we do not participate in any future animations.
815                 mService.mClosingApps.remove(this);
816             } else if (mLastParent != null && mLastParent.mStack != null) {
817                 task.mStack.mExitingAppTokens.remove(this);
818             }
819         }
820         mLastParent = task;
821     }
822 
postWindowRemoveStartingWindowCleanup(WindowState win)823     void postWindowRemoveStartingWindowCleanup(WindowState win) {
824         // TODO: Something smells about the code below...Is there a better way?
825         if (startingWindow == win) {
826             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
827             if (getController() != null) {
828                 getController().removeStartingWindow();
829             }
830         } else if (mChildren.size() == 0) {
831             // If this is the last window and we had requested a starting transition window,
832             // well there is no point now.
833             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
834             startingData = null;
835             if (mHiddenSetFromTransferredStartingWindow) {
836                 // We set the hidden state to false for the token from a transferred starting window.
837                 // We now reset it back to true since the starting window was the last window in the
838                 // token.
839                 hidden = true;
840             }
841         } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
842             // If this is the last window except for a starting transition window,
843             // we need to get rid of the starting transition.
844             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
845                     + win);
846             if (getController() != null) {
847                 getController().removeStartingWindow();
848             }
849         }
850     }
851 
removeDeadWindows()852     void removeDeadWindows() {
853         for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
854             WindowState win = mChildren.get(winNdx);
855             if (win.mAppDied) {
856                 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG,
857                         "removeDeadWindows: " + win);
858                 // Set mDestroying, we don't want any animation or delayed removal here.
859                 win.mDestroying = true;
860                 // Also removes child windows.
861                 win.removeIfPossible();
862             }
863         }
864     }
865 
hasWindowsAlive()866     boolean hasWindowsAlive() {
867         for (int i = mChildren.size() - 1; i >= 0; i--) {
868             // No need to loop through child windows as the answer should be the same as that of the
869             // parent window.
870             if (!(mChildren.get(i)).mAppDied) {
871                 return true;
872             }
873         }
874         return false;
875     }
876 
setWillReplaceWindows(boolean animate)877     void setWillReplaceWindows(boolean animate) {
878         if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
879                 "Marking app token " + this + " with replacing windows.");
880 
881         for (int i = mChildren.size() - 1; i >= 0; i--) {
882             final WindowState w = mChildren.get(i);
883             w.setWillReplaceWindow(animate);
884         }
885         if (animate) {
886             // Set-up dummy animation so we can start treating windows associated with this
887             // token like they are in transition before the new app window is ready for us to
888             // run the real transition animation.
889             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
890                     "setWillReplaceWindow() Setting dummy animation on: " + this);
891             mAppAnimator.setDummyAnimation();
892         }
893     }
894 
setWillReplaceChildWindows()895     void setWillReplaceChildWindows() {
896         if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this
897                 + " with replacing child windows.");
898         for (int i = mChildren.size() - 1; i >= 0; i--) {
899             final WindowState w = mChildren.get(i);
900             w.setWillReplaceChildWindows();
901         }
902     }
903 
clearWillReplaceWindows()904     void clearWillReplaceWindows() {
905         if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
906                 "Resetting app token " + this + " of replacing window marks.");
907 
908         for (int i = mChildren.size() - 1; i >= 0; i--) {
909             final WindowState w = mChildren.get(i);
910             w.clearWillReplaceWindow();
911         }
912     }
913 
requestUpdateWallpaperIfNeeded()914     void requestUpdateWallpaperIfNeeded() {
915         for (int i = mChildren.size() - 1; i >= 0; i--) {
916             final WindowState w = mChildren.get(i);
917             w.requestUpdateWallpaperIfNeeded();
918         }
919     }
920 
isRelaunching()921     boolean isRelaunching() {
922         return mPendingRelaunchCount > 0;
923     }
924 
shouldFreezeBounds()925     boolean shouldFreezeBounds() {
926         final Task task = getTask();
927 
928         // For freeform windows, we can't freeze the bounds at the moment because this would make
929         // the resizing unresponsive.
930         if (task == null || task.inFreeformWorkspace()) {
931             return false;
932         }
933 
934         // We freeze the bounds while drag resizing to deal with the time between
935         // the divider/drag handle being released, and the handling it's new
936         // configuration. If we are relaunched outside of the drag resizing state,
937         // we need to be careful not to do this.
938         return getTask().isDragResizing();
939     }
940 
startRelaunching()941     void startRelaunching() {
942         if (shouldFreezeBounds()) {
943             freezeBounds();
944         }
945 
946         // In the process of tearing down before relaunching, the app will
947         // try and clean up it's child surfaces. We need to prevent this from
948         // happening, so we sever the children, transfering their ownership
949         // from the client it-self to the parent surface (owned by us).
950         for (int i = mChildren.size() - 1; i >= 0; i--) {
951             final WindowState w = mChildren.get(i);
952             w.mWinAnimator.detachChildren();
953         }
954 
955         mPendingRelaunchCount++;
956     }
957 
finishRelaunching()958     void finishRelaunching() {
959         unfreezeBounds();
960 
961         if (mPendingRelaunchCount > 0) {
962             mPendingRelaunchCount--;
963         } else {
964             // Update keyguard flags upon finishing relaunch.
965             checkKeyguardFlagsChanged();
966         }
967     }
968 
clearRelaunching()969     void clearRelaunching() {
970         if (mPendingRelaunchCount == 0) {
971             return;
972         }
973         unfreezeBounds();
974         mPendingRelaunchCount = 0;
975     }
976 
977     /**
978      * Returns true if the new child window we are adding to this token is considered greater than
979      * the existing child window in this token in terms of z-order.
980      */
981     @Override
isFirstChildWindowGreaterThanSecond(WindowState newWindow, WindowState existingWindow)982     protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
983             WindowState existingWindow) {
984         final int type1 = newWindow.mAttrs.type;
985         final int type2 = existingWindow.mAttrs.type;
986 
987         // Base application windows should be z-ordered BELOW all other windows in the app token.
988         if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
989             return false;
990         } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
991             return true;
992         }
993 
994         // Starting windows should be z-ordered ABOVE all other windows in the app token.
995         if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
996             return true;
997         } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
998             return false;
999         }
1000 
1001         // Otherwise the new window is greater than the existing window.
1002         return true;
1003     }
1004 
1005     @Override
addWindow(WindowState w)1006     void addWindow(WindowState w) {
1007         super.addWindow(w);
1008 
1009         boolean gotReplacementWindow = false;
1010         for (int i = mChildren.size() - 1; i >= 0; i--) {
1011             final WindowState candidate = mChildren.get(i);
1012             gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
1013         }
1014 
1015         // if we got a replacement window, reset the timeout to give drawing more time
1016         if (gotReplacementWindow) {
1017             mService.scheduleWindowReplacementTimeouts(this);
1018         }
1019         checkKeyguardFlagsChanged();
1020     }
1021 
1022     @Override
removeChild(WindowState child)1023     void removeChild(WindowState child) {
1024         super.removeChild(child);
1025         checkKeyguardFlagsChanged();
1026     }
1027 
waitingForReplacement()1028     private boolean waitingForReplacement() {
1029         for (int i = mChildren.size() - 1; i >= 0; i--) {
1030             final WindowState candidate = mChildren.get(i);
1031             if (candidate.waitingForReplacement()) {
1032                 return true;
1033             }
1034         }
1035         return false;
1036     }
1037 
onWindowReplacementTimeout()1038     void onWindowReplacementTimeout() {
1039         for (int i = mChildren.size() - 1; i >= 0; --i) {
1040             (mChildren.get(i)).onWindowReplacementTimeout();
1041         }
1042     }
1043 
reparent(Task task, int position)1044     void reparent(Task task, int position) {
1045         final Task currentTask = getTask();
1046         if (task == currentTask) {
1047             throw new IllegalArgumentException(
1048                     "window token=" + this + " already child of task=" + currentTask);
1049         }
1050 
1051         if (currentTask.mStack != task.mStack) {
1052             throw new IllegalArgumentException(
1053                     "window token=" + this + " current task=" + currentTask
1054                         + " belongs to a different stack than " + task);
1055         }
1056 
1057         if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
1058                 + " from task=" + currentTask);
1059         final DisplayContent prevDisplayContent = getDisplayContent();
1060 
1061         mReparenting = true;
1062 
1063         getParent().removeChild(this);
1064         task.addChild(this, position);
1065 
1066         mReparenting = false;
1067 
1068         // Relayout display(s).
1069         final DisplayContent displayContent = task.getDisplayContent();
1070         displayContent.setLayoutNeeded();
1071         if (prevDisplayContent != displayContent) {
1072             onDisplayChanged(displayContent);
1073             prevDisplayContent.setLayoutNeeded();
1074         }
1075     }
1076 
1077     /**
1078      * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
1079      * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
1080      * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
1081      * with a queue.
1082      */
freezeBounds()1083     private void freezeBounds() {
1084         final Task task = getTask();
1085         mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
1086 
1087         if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
1088             // We didn't call prepareFreezingBounds on the task, so use the current value.
1089             mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
1090         } else {
1091             mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
1092         }
1093         // Calling unset() to make it equal to Configuration.EMPTY.
1094         task.mPreparedFrozenMergedConfig.unset();
1095     }
1096 
1097     /**
1098      * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
1099      */
unfreezeBounds()1100     private void unfreezeBounds() {
1101         if (mFrozenBounds.isEmpty()) {
1102             return;
1103         }
1104         mFrozenBounds.remove();
1105         if (!mFrozenMergedConfig.isEmpty()) {
1106             mFrozenMergedConfig.remove();
1107         }
1108         for (int i = mChildren.size() - 1; i >= 0; i--) {
1109             final WindowState win = mChildren.get(i);
1110             win.onUnfreezeBounds();
1111         }
1112         mService.mWindowPlacerLocked.performSurfacePlacement();
1113     }
1114 
setAppLayoutChanges(int changes, String reason)1115     void setAppLayoutChanges(int changes, String reason) {
1116         if (!mChildren.isEmpty()) {
1117             final DisplayContent dc = getDisplayContent();
1118             dc.pendingLayoutChanges |= changes;
1119             if (DEBUG_LAYOUT_REPEATS) {
1120                 mService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
1121             }
1122         }
1123     }
1124 
removeReplacedWindowIfNeeded(WindowState replacement)1125     void removeReplacedWindowIfNeeded(WindowState replacement) {
1126         for (int i = mChildren.size() - 1; i >= 0; i--) {
1127             final WindowState win = mChildren.get(i);
1128             if (win.removeReplacedWindowIfNeeded(replacement)) {
1129                 return;
1130             }
1131         }
1132     }
1133 
startFreezingScreen()1134     void startFreezingScreen() {
1135         if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
1136                 + hidden + " freezing=" + mAppAnimator.freezingScreen + " hiddenRequested="
1137                 + hiddenRequested);
1138         if (!hiddenRequested) {
1139             if (!mAppAnimator.freezingScreen) {
1140                 mAppAnimator.freezingScreen = true;
1141                 mService.registerAppFreezeListener(this);
1142                 mAppAnimator.lastFreezeDuration = 0;
1143                 mService.mAppsFreezingScreen++;
1144                 if (mService.mAppsFreezingScreen == 1) {
1145                     mService.startFreezingDisplayLocked(false, 0, 0, getDisplayContent());
1146                     mService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1147                     mService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
1148                 }
1149             }
1150             final int count = mChildren.size();
1151             for (int i = 0; i < count; i++) {
1152                 final WindowState w = mChildren.get(i);
1153                 w.onStartFreezingScreen();
1154             }
1155         }
1156     }
1157 
stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force)1158     void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
1159         if (!mAppAnimator.freezingScreen) {
1160             return;
1161         }
1162         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
1163         final int count = mChildren.size();
1164         boolean unfrozeWindows = false;
1165         for (int i = 0; i < count; i++) {
1166             final WindowState w = mChildren.get(i);
1167             unfrozeWindows |= w.onStopFreezingScreen();
1168         }
1169         if (force || unfrozeWindows) {
1170             if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
1171             mAppAnimator.freezingScreen = false;
1172             mService.unregisterAppFreezeListener(this);
1173             mAppAnimator.lastFreezeDuration =
1174                     (int)(SystemClock.elapsedRealtime() - mService.mDisplayFreezeTime);
1175             mService.mAppsFreezingScreen--;
1176             mService.mLastFinishedFreezeSource = this;
1177         }
1178         if (unfreezeSurfaceNow) {
1179             if (unfrozeWindows) {
1180                 mService.mWindowPlacerLocked.performSurfacePlacement();
1181             }
1182             mService.stopFreezingDisplayLocked();
1183         }
1184     }
1185 
1186     @Override
onAppFreezeTimeout()1187     public void onAppFreezeTimeout() {
1188         Slog.w(TAG_WM, "Force clearing freeze: " + this);
1189         stopFreezingScreen(true, true);
1190     }
1191 
transferStartingWindow(IBinder transferFrom)1192     boolean transferStartingWindow(IBinder transferFrom) {
1193         final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
1194         if (fromToken == null) {
1195             return false;
1196         }
1197 
1198         final WindowState tStartingWindow = fromToken.startingWindow;
1199         if (tStartingWindow != null && fromToken.startingSurface != null) {
1200             // In this case, the starting icon has already been displayed, so start
1201             // letting windows get shown immediately without any more transitions.
1202             mService.mSkipAppTransitionAnimation = true;
1203 
1204             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving existing starting " + tStartingWindow
1205                     + " from " + fromToken + " to " + this);
1206 
1207             final long origId = Binder.clearCallingIdentity();
1208 
1209             // Transfer the starting window over to the new token.
1210             startingData = fromToken.startingData;
1211             startingSurface = fromToken.startingSurface;
1212             startingDisplayed = fromToken.startingDisplayed;
1213             fromToken.startingDisplayed = false;
1214             startingWindow = tStartingWindow;
1215             reportedVisible = fromToken.reportedVisible;
1216             fromToken.startingData = null;
1217             fromToken.startingSurface = null;
1218             fromToken.startingWindow = null;
1219             fromToken.startingMoved = true;
1220             tStartingWindow.mToken = this;
1221             tStartingWindow.mAppToken = this;
1222 
1223             if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1224                     "Removing starting " + tStartingWindow + " from " + fromToken);
1225             fromToken.removeChild(tStartingWindow);
1226             fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
1227             fromToken.mHiddenSetFromTransferredStartingWindow = false;
1228             addWindow(tStartingWindow);
1229 
1230             // Propagate other interesting state between the tokens. If the old token is displayed,
1231             // we should immediately force the new one to be displayed. If it is animating, we need
1232             // to move that animation to the new one.
1233             if (fromToken.allDrawn) {
1234                 allDrawn = true;
1235                 deferClearAllDrawn = fromToken.deferClearAllDrawn;
1236             }
1237             if (fromToken.firstWindowDrawn) {
1238                 firstWindowDrawn = true;
1239             }
1240             if (!fromToken.hidden) {
1241                 hidden = false;
1242                 hiddenRequested = false;
1243                 mHiddenSetFromTransferredStartingWindow = true;
1244             }
1245             setClientHidden(fromToken.mClientHidden);
1246             fromToken.mAppAnimator.transferCurrentAnimation(
1247                     mAppAnimator, tStartingWindow.mWinAnimator);
1248 
1249             mService.updateFocusedWindowLocked(
1250                     UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
1251             getDisplayContent().setLayoutNeeded();
1252             mService.mWindowPlacerLocked.performSurfacePlacement();
1253             Binder.restoreCallingIdentity(origId);
1254             return true;
1255         } else if (fromToken.startingData != null) {
1256             // The previous app was getting ready to show a
1257             // starting window, but hasn't yet done so.  Steal it!
1258             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1259                     "Moving pending starting from " + fromToken + " to " + this);
1260             startingData = fromToken.startingData;
1261             fromToken.startingData = null;
1262             fromToken.startingMoved = true;
1263             if (getController() != null) {
1264                 getController().scheduleAddStartingWindow();
1265             }
1266             return true;
1267         }
1268 
1269         final AppWindowAnimator tAppAnimator = fromToken.mAppAnimator;
1270         final AppWindowAnimator wAppAnimator = mAppAnimator;
1271         if (tAppAnimator.thumbnail != null) {
1272             // The old token is animating with a thumbnail, transfer that to the new token.
1273             if (wAppAnimator.thumbnail != null) {
1274                 wAppAnimator.thumbnail.destroy();
1275             }
1276             wAppAnimator.thumbnail = tAppAnimator.thumbnail;
1277             wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer;
1278             wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation;
1279             tAppAnimator.thumbnail = null;
1280         }
1281         return false;
1282     }
1283 
isLastWindow(WindowState win)1284     boolean isLastWindow(WindowState win) {
1285         return mChildren.size() == 1 && mChildren.get(0) == win;
1286     }
1287 
setAllAppWinAnimators()1288     void setAllAppWinAnimators() {
1289         final ArrayList<WindowStateAnimator> allAppWinAnimators = mAppAnimator.mAllAppWinAnimators;
1290         allAppWinAnimators.clear();
1291 
1292         final int windowsCount = mChildren.size();
1293         for (int j = 0; j < windowsCount; j++) {
1294             (mChildren.get(j)).addWinAnimatorToList(allAppWinAnimators);
1295         }
1296     }
1297 
1298     @Override
onAppTransitionDone()1299     void onAppTransitionDone() {
1300         sendingToBottom = false;
1301     }
1302 
1303     /**
1304      * We override because this class doesn't want its children affecting its reported orientation
1305      * in anyway.
1306      */
1307     @Override
getOrientation(int candidate)1308     int getOrientation(int candidate) {
1309         if (candidate == SCREEN_ORIENTATION_BEHIND) {
1310             // Allow app to specify orientation regardless of its visibility state if the current
1311             // candidate want us to use orientation behind. I.e. the visible app on-top of this one
1312             // wants us to use the orientation of the app behind it.
1313             return mOrientation;
1314         }
1315 
1316         // The {@link AppWindowToken} should only specify an orientation when it is not closing or
1317         // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
1318         // an Activity in another task being started in the wrong orientation during the transition.
1319         if (!(sendingToBottom || mService.mClosingApps.contains(this))
1320                 && (isVisible() || mService.mOpeningApps.contains(this) || isOnTop())) {
1321             return mOrientation;
1322         }
1323 
1324         return SCREEN_ORIENTATION_UNSET;
1325     }
1326 
1327     /** Returns the app's preferred orientation regardless of its currently visibility state. */
getOrientationIgnoreVisibility()1328     int getOrientationIgnoreVisibility() {
1329         return mOrientation;
1330     }
1331 
1332     @Override
checkAppWindowsReadyToShow()1333     void checkAppWindowsReadyToShow() {
1334         if (allDrawn == mAppAnimator.allDrawn) {
1335             return;
1336         }
1337 
1338         mAppAnimator.allDrawn = allDrawn;
1339         if (!allDrawn) {
1340             return;
1341         }
1342 
1343         // The token has now changed state to having all windows shown...  what to do, what to do?
1344         if (mAppAnimator.freezingScreen) {
1345             mAppAnimator.showAllWindowsLocked();
1346             stopFreezingScreen(false, true);
1347             if (DEBUG_ORIENTATION) Slog.i(TAG,
1348                     "Setting mOrientationChangeComplete=true because wtoken " + this
1349                     + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows);
1350             // This will set mOrientationChangeComplete and cause a pass through layout.
1351             setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
1352                     "checkAppWindowsReadyToShow: freezingScreen");
1353         } else {
1354             setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
1355 
1356             // We can now show all of the drawn windows!
1357             if (!mService.mOpeningApps.contains(this)) {
1358                 mService.mAnimator.orAnimating(mAppAnimator.showAllWindowsLocked());
1359             }
1360         }
1361     }
1362 
1363     /**
1364      * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1365      * child {@link WindowState}. A child is considered if it has been passed into
1366      * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1367      * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1368      * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1369      *
1370      * @return {@code true} If all children have been considered, {@code false}.
1371      */
allDrawnStatesConsidered()1372     private boolean allDrawnStatesConsidered() {
1373         for (int i = mChildren.size() - 1; i >= 0; --i) {
1374             final WindowState child = mChildren.get(i);
1375             if (child.mightAffectAllDrawn(false /*visibleOnly*/ )
1376                     && !child.getDrawnStateEvaluated()) {
1377                 return false;
1378             }
1379         }
1380         return true;
1381     }
1382 
1383     /**
1384      *  Determines if the token has finished drawing. This should only be called from
1385      *  {@link DisplayContent#applySurfaceChangesTransaction}
1386      */
updateAllDrawn()1387     void updateAllDrawn() {
1388         if (!allDrawn) {
1389             // Number of drawn windows can be less when a window is being relaunched, wait for
1390             // all windows to be launched and drawn for this token be considered all drawn.
1391             final int numInteresting = mNumInterestingWindows;
1392 
1393             // We must make sure that all present children have been considered (determined by
1394             // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1395             // drawn.
1396             if (numInteresting > 0 && allDrawnStatesConsidered()
1397                     && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
1398                 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
1399                         + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
1400                 allDrawn = true;
1401                 // Force an additional layout pass where
1402                 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
1403                 if (mDisplayContent != null) {
1404                     mDisplayContent.setLayoutNeeded();
1405                 }
1406                 mService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
1407 
1408                 // Notify the pinned stack upon all windows drawn. If there was an animation in
1409                 // progress then this signal will resume that animation.
1410                 final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID);
1411                 if (pinnedStack != null) {
1412                     pinnedStack.onAllWindowsDrawn();
1413                 }
1414             }
1415         }
1416 
1417         if (!allDrawnExcludingSaved) {
1418             int numInteresting = mNumInterestingWindowsExcludingSaved;
1419             if (numInteresting > 0 && mNumDrawnWindowsExcludingSaved >= numInteresting) {
1420                 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawnExcludingSaved: " + this
1421                         + " interesting=" + numInteresting
1422                         + " drawn=" + mNumDrawnWindowsExcludingSaved);
1423                 allDrawnExcludingSaved = true;
1424                 if (mDisplayContent != null) {
1425                     mDisplayContent.setLayoutNeeded();
1426                 }
1427                 if (isAnimatingInvisibleWithSavedSurface()
1428                         && !mService.mFinishedEarlyAnim.contains(this)) {
1429                     mService.mFinishedEarlyAnim.add(this);
1430                 }
1431             }
1432         }
1433     }
1434 
1435     /**
1436      * Updated this app token tracking states for interesting and drawn windows based on the window.
1437      *
1438      * @return Returns true if the input window is considered interesting and drawn while all the
1439      *         windows in this app token where not considered drawn as of the last pass.
1440      */
updateDrawnWindowStates(WindowState w)1441     boolean updateDrawnWindowStates(WindowState w) {
1442         w.setDrawnStateEvaluated(true /*evaluated*/);
1443 
1444         if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
1445             Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
1446                     + " allDrawn=" + allDrawn + " freezingScreen=" + mAppAnimator.freezingScreen);
1447         }
1448 
1449         if (allDrawn && allDrawnExcludingSaved && !mAppAnimator.freezingScreen) {
1450             return false;
1451         }
1452 
1453         if (mLastTransactionSequence != mService.mTransactionSequence) {
1454             mLastTransactionSequence = mService.mTransactionSequence;
1455             mNumInterestingWindows = mNumDrawnWindows = 0;
1456             mNumInterestingWindowsExcludingSaved = 0;
1457             mNumDrawnWindowsExcludingSaved = 0;
1458             startingDisplayed = false;
1459         }
1460 
1461         final WindowStateAnimator winAnimator = w.mWinAnimator;
1462 
1463         boolean isInterestingAndDrawn = false;
1464 
1465         if (!allDrawn && w.mightAffectAllDrawn(false /* visibleOnly */)) {
1466             if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
1467                 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
1468                         + ", isAnimationSet=" + winAnimator.isAnimationSet());
1469                 if (!w.isDrawnLw()) {
1470                     Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
1471                             + " pv=" + w.mPolicyVisibility
1472                             + " mDrawState=" + winAnimator.drawStateToString()
1473                             + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
1474                             + " a=" + winAnimator.mAnimating);
1475                 }
1476             }
1477 
1478             if (w != startingWindow) {
1479                 if (w.isInteresting()) {
1480                     mNumInterestingWindows++;
1481                     if (w.isDrawnLw()) {
1482                         mNumDrawnWindows++;
1483 
1484                         if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: "
1485                                 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
1486                                 + " freezingScreen=" + mAppAnimator.freezingScreen
1487                                 + " mAppFreezing=" + w.mAppFreezing);
1488 
1489                         isInterestingAndDrawn = true;
1490                     }
1491                 }
1492             } else if (w.isDrawnLw()) {
1493                 if (getController() != null) {
1494                     getController().reportStartingWindowDrawn();
1495                 }
1496                 startingDisplayed = true;
1497             }
1498         }
1499 
1500         if (!allDrawnExcludingSaved && w.mightAffectAllDrawn(true /* visibleOnly */)) {
1501             if (w != startingWindow && w.isInteresting()) {
1502                 mNumInterestingWindowsExcludingSaved++;
1503                 if (w.isDrawnLw() && !w.isAnimatingWithSavedSurface()) {
1504                     mNumDrawnWindowsExcludingSaved++;
1505 
1506                     if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
1507                             "tokenMayBeDrawnExcludingSaved: " + this + " w=" + w
1508                             + " numInteresting=" + mNumInterestingWindowsExcludingSaved
1509                             + " freezingScreen=" + mAppAnimator.freezingScreen
1510                             + " mAppFreezing=" + w.mAppFreezing);
1511 
1512                     isInterestingAndDrawn = true;
1513                 }
1514             }
1515         }
1516 
1517         return isInterestingAndDrawn;
1518     }
1519 
1520     @Override
stepAppWindowsAnimation(long currentTime)1521     void stepAppWindowsAnimation(long currentTime) {
1522         mAppAnimator.wasAnimating = mAppAnimator.animating;
1523         if (mAppAnimator.stepAnimationLocked(currentTime)) {
1524             mAppAnimator.animating = true;
1525             mService.mAnimator.setAnimating(true);
1526             mService.mAnimator.mAppWindowAnimating = true;
1527         } else if (mAppAnimator.wasAnimating) {
1528             // stopped animating, do one more pass through the layout
1529             setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
1530                     DEBUG_LAYOUT_REPEATS ? "appToken " + this + " done" : null);
1531             if (DEBUG_ANIM) Slog.v(TAG, "updateWindowsApps...: done animating " + this);
1532         }
1533     }
1534 
1535     @Override
forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)1536     boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
1537         // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
1538         // before the non-exiting app tokens. So, we skip the exiting app tokens here.
1539         // TODO: Investigate if we need to continue to do this or if we can just process them
1540         // in-order.
1541         if (mIsExiting && !waitingForReplacement()) {
1542             return false;
1543         }
1544         return forAllWindowsUnchecked(callback, traverseTopToBottom);
1545     }
1546 
forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)1547     boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
1548             boolean traverseTopToBottom) {
1549         return super.forAllWindows(callback, traverseTopToBottom);
1550     }
1551 
1552     @Override
asAppWindowToken()1553     AppWindowToken asAppWindowToken() {
1554         // I am an app window token!
1555         return this;
1556     }
1557 
1558     @Override
fillsParent()1559     boolean fillsParent() {
1560         return mFillsParent;
1561     }
1562 
setFillsParent(boolean fillsParent)1563     void setFillsParent(boolean fillsParent) {
1564         mFillsParent = fillsParent;
1565     }
1566 
containsDismissKeyguardWindow()1567     boolean containsDismissKeyguardWindow() {
1568         // Window state is transient during relaunch. We are not guaranteed to be frozen during the
1569         // entirety of the relaunch.
1570         if (isRelaunching()) {
1571             return mLastContainsDismissKeyguardWindow;
1572         }
1573 
1574         for (int i = mChildren.size() - 1; i >= 0; i--) {
1575             if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
1576                 return true;
1577             }
1578         }
1579         return false;
1580     }
1581 
containsShowWhenLockedWindow()1582     boolean containsShowWhenLockedWindow() {
1583         // When we are relaunching, it is possible for us to be unfrozen before our previous
1584         // windows have been added back. Using the cached value ensures that our previous
1585         // showWhenLocked preference is honored until relaunching is complete.
1586         if (isRelaunching()) {
1587             return mLastContainsShowWhenLockedWindow;
1588         }
1589 
1590         for (int i = mChildren.size() - 1; i >= 0; i--) {
1591             if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
1592                 return true;
1593             }
1594         }
1595 
1596         return false;
1597     }
1598 
checkKeyguardFlagsChanged()1599     void checkKeyguardFlagsChanged() {
1600         final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
1601         final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
1602         if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
1603                 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
1604             mService.notifyKeyguardFlagsChanged(null /* callback */);
1605         }
1606         mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
1607         mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
1608     }
1609 
getImeTargetBelowWindow(WindowState w)1610     WindowState getImeTargetBelowWindow(WindowState w) {
1611         final int index = mChildren.indexOf(w);
1612         if (index > 0) {
1613             final WindowState target = mChildren.get(index - 1);
1614             if (target.canBeImeTarget()) {
1615                 return target;
1616             }
1617         }
1618         return null;
1619     }
1620 
getLowestAnimLayer()1621     int getLowestAnimLayer() {
1622         for (int i = 0; i < mChildren.size(); i++) {
1623             final WindowState w = mChildren.get(i);
1624             if (w.mRemoved) {
1625                 continue;
1626             }
1627             return w.mWinAnimator.mAnimLayer;
1628         }
1629         return Integer.MAX_VALUE;
1630     }
1631 
getHighestAnimLayerWindow(WindowState currentTarget)1632     WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
1633         WindowState candidate = null;
1634         for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
1635             final WindowState w = mChildren.get(i);
1636             if (w.mRemoved) {
1637                 continue;
1638             }
1639             if (candidate == null || w.mWinAnimator.mAnimLayer >
1640                     candidate.mWinAnimator.mAnimLayer) {
1641                 candidate = w;
1642             }
1643         }
1644         return candidate;
1645     }
1646 
1647     /**
1648      * See {@link Activity#setDisablePreviewScreenshots}.
1649      */
setDisablePreviewScreenshots(boolean disable)1650     void setDisablePreviewScreenshots(boolean disable) {
1651         mDisablePreviewScreenshots = disable;
1652     }
1653 
1654     /**
1655      * Sets whether the current launch can turn the screen on. See {@link #canTurnScreenOn()}
1656      */
setCanTurnScreenOn(boolean canTurnScreenOn)1657     void setCanTurnScreenOn(boolean canTurnScreenOn) {
1658         mCanTurnScreenOn = canTurnScreenOn;
1659     }
1660 
1661     /**
1662      * Indicates whether the current launch can turn the screen on. This is to prevent multiple
1663      * relayouts from turning the screen back on. The screen should only turn on at most
1664      * once per activity resume.
1665      *
1666      * @return true if the screen can be turned on.
1667      */
canTurnScreenOn()1668     boolean canTurnScreenOn() {
1669         return mCanTurnScreenOn;
1670     }
1671 
1672     /**
1673      * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
1674      * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
1675      * we can't take a snapshot for other reasons, for example, if we have a secure window.
1676      *
1677      * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
1678      *         screenshot.
1679      */
shouldUseAppThemeSnapshot()1680     boolean shouldUseAppThemeSnapshot() {
1681         return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
1682                 true /* topToBottom */);
1683     }
1684 
1685     @Override
getAnimLayerAdjustment()1686     int getAnimLayerAdjustment() {
1687         return mAppAnimator.animLayerAdjustment;
1688     }
1689 
1690     @Override
dump(PrintWriter pw, String prefix)1691     void dump(PrintWriter pw, String prefix) {
1692         super.dump(pw, prefix);
1693         if (appToken != null) {
1694             pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
1695         }
1696         pw.print(prefix); pw.print("task="); pw.println(getTask());
1697         pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
1698                 pw.print(" mOrientation="); pw.println(mOrientation);
1699         pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
1700             + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
1701             + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
1702         if (paused) {
1703             pw.print(prefix); pw.print("paused="); pw.println(paused);
1704         }
1705         if (mAppStopped) {
1706             pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
1707         }
1708         if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
1709                 || allDrawn || mAppAnimator.allDrawn) {
1710             pw.print(prefix); pw.print("mNumInterestingWindows=");
1711                     pw.print(mNumInterestingWindows);
1712                     pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
1713                     pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
1714                     pw.print(" allDrawn="); pw.print(allDrawn);
1715                     pw.print(" (animator="); pw.print(mAppAnimator.allDrawn);
1716                     pw.println(")");
1717         }
1718         if (inPendingTransaction) {
1719             pw.print(prefix); pw.print("inPendingTransaction=");
1720                     pw.println(inPendingTransaction);
1721         }
1722         if (startingData != null || removed || firstWindowDrawn || mIsExiting) {
1723             pw.print(prefix); pw.print("startingData="); pw.print(startingData);
1724                     pw.print(" removed="); pw.print(removed);
1725                     pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
1726                     pw.print(" mIsExiting="); pw.println(mIsExiting);
1727         }
1728         if (startingWindow != null || startingSurface != null
1729                 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
1730             pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
1731                     pw.print(" startingSurface="); pw.print(startingSurface);
1732                     pw.print(" startingDisplayed="); pw.print(startingDisplayed);
1733                     pw.print(" startingMoved="); pw.print(startingMoved);
1734                     pw.println(" mHiddenSetFromTransferredStartingWindow="
1735                             + mHiddenSetFromTransferredStartingWindow);
1736         }
1737         if (!mFrozenBounds.isEmpty()) {
1738             pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
1739             pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
1740         }
1741         if (mPendingRelaunchCount != 0) {
1742             pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
1743         }
1744         if (getController() != null) {
1745             pw.print(prefix); pw.print("controller="); pw.println(getController());
1746         }
1747         if (mRemovingFromDisplay) {
1748             pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
1749         }
1750         if (mAppAnimator.isAnimating()) {
1751             mAppAnimator.dump(pw, prefix + "  ");
1752         }
1753     }
1754 
1755     @Override
toString()1756     public String toString() {
1757         if (stringName == null) {
1758             StringBuilder sb = new StringBuilder();
1759             sb.append("AppWindowToken{");
1760             sb.append(Integer.toHexString(System.identityHashCode(this)));
1761             sb.append(" token="); sb.append(token); sb.append('}');
1762             stringName = sb.toString();
1763         }
1764         return stringName + ((mIsExiting) ? " mIsExiting=" : "");
1765     }
1766 }
1767