Home | History | Annotate | Download | only in wm
      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 
    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 
    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 
    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 
    248     void getBounds(Rect outBounds) {
    249         outBounds.set(mBounds);
    250     }
    251 
    252     boolean hasBounds() {
    253         return !mBounds.isEmpty();
    254     }
    255 
    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 
    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 
    332     boolean isClientHidden() {
    333         return mClientHidden;
    334     }
    335 
    336     void setClientHidden(boolean hideClient) {
    337         if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
    338             return;
    339         }
    340         mClientHidden = hideClient;
    341         sendAppVisibilityToClients();
    342     }
    343 
    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      */
    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 
    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 
    509     boolean windowsAreFocusable() {
    510         return StackId.canReceiveKeys(getTask().mStack.mStackId) || mAlwaysFocusable;
    511     }
    512 
    513     AppWindowContainerController getController() {
    514         final WindowContainerController controller = super.getController();
    515         return controller != null ? (AppWindowContainerController) controller : null;
    516     }
    517 
    518     @Override
    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
    526     void removeImmediately() {
    527         onRemovedFromDisplay();
    528         super.removeImmediately();
    529     }
    530 
    531     @Override
    532     void removeIfPossible() {
    533         mIsExiting = false;
    534         removeAllWindowsIfPossible();
    535         removeImmediately();
    536     }
    537 
    538     @Override
    539     boolean checkCompleteDeferredRemoval() {
    540         if (mIsExiting) {
    541             removeIfPossible();
    542         }
    543         return super.checkCompleteDeferredRemoval();
    544     }
    545 
    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 
    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 
    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      */
    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      */
    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      */
    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      */
    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 
    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 
    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      */
    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      */
    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 
    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 
    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 
    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 
    783     void clearAllDrawn() {
    784         allDrawn = false;
    785         deferClearAllDrawn = false;
    786         allDrawnExcludingSaved = false;
    787     }
    788 
    789     Task getTask() {
    790         return (Task) getParent();
    791     }
    792 
    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
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    921     boolean isRelaunching() {
    922         return mPendingRelaunchCount > 0;
    923     }
    924 
    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 
    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 
    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 
    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
    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
   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
   1023     void removeChild(WindowState child) {
   1024         super.removeChild(child);
   1025         checkKeyguardFlagsChanged();
   1026     }
   1027 
   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 
   1038     void onWindowReplacementTimeout() {
   1039         for (int i = mChildren.size() - 1; i >= 0; --i) {
   1040             (mChildren.get(i)).onWindowReplacementTimeout();
   1041         }
   1042     }
   1043 
   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      */
   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      */
   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 
   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 
   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 
   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 
   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
   1187     public void onAppFreezeTimeout() {
   1188         Slog.w(TAG_WM, "Force clearing freeze: " + this);
   1189         stopFreezingScreen(true, true);
   1190     }
   1191 
   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 
   1284     boolean isLastWindow(WindowState win) {
   1285         return mChildren.size() == 1 && mChildren.get(0) == win;
   1286     }
   1287 
   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
   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
   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. */
   1328     int getOrientationIgnoreVisibility() {
   1329         return mOrientation;
   1330     }
   1331 
   1332     @Override
   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      */
   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      */
   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      */
   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
   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
   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 
   1547     boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
   1548             boolean traverseTopToBottom) {
   1549         return super.forAllWindows(callback, traverseTopToBottom);
   1550     }
   1551 
   1552     @Override
   1553     AppWindowToken asAppWindowToken() {
   1554         // I am an app window token!
   1555         return this;
   1556     }
   1557 
   1558     @Override
   1559     boolean fillsParent() {
   1560         return mFillsParent;
   1561     }
   1562 
   1563     void setFillsParent(boolean fillsParent) {
   1564         mFillsParent = fillsParent;
   1565     }
   1566 
   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 
   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 
   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 
   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 
   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 
   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      */
   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      */
   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      */
   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      */
   1680     boolean shouldUseAppThemeSnapshot() {
   1681         return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
   1682                 true /* topToBottom */);
   1683     }
   1684 
   1685     @Override
   1686     int getAnimLayerAdjustment() {
   1687         return mAppAnimator.animLayerAdjustment;
   1688     }
   1689 
   1690     @Override
   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
   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