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.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
     21 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
     22 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
     23 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
     24 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
     25 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
     26 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
     27 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
     28 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
     29 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
     30 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
     31 import static com.android.server.wm.WindowManagerService.WINDOW_REPLACEMENT_TIMEOUT_DURATION;
     32 import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
     33 
     34 import com.android.server.input.InputApplicationHandle;
     35 import com.android.server.wm.WindowManagerService.H;
     36 
     37 import android.annotation.NonNull;
     38 import android.content.pm.ActivityInfo;
     39 import android.content.res.Configuration;
     40 import android.graphics.Rect;
     41 import android.os.Message;
     42 import android.os.RemoteException;
     43 import android.util.Slog;
     44 import android.view.IApplicationToken;
     45 import android.view.View;
     46 import android.view.WindowManager;
     47 
     48 import java.io.PrintWriter;
     49 import java.util.ArrayDeque;
     50 import java.util.ArrayList;
     51 
     52 class AppTokenList extends ArrayList<AppWindowToken> {
     53 }
     54 
     55 /**
     56  * Version of WindowToken that is specifically for a particular application (or
     57  * really activity) that is displaying windows.
     58  */
     59 class AppWindowToken extends WindowToken {
     60     private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM;
     61 
     62     // Non-null only for application tokens.
     63     final IApplicationToken appToken;
     64 
     65     // All of the windows and child windows that are included in this
     66     // application token.  Note this list is NOT sorted!
     67     final WindowList allAppWindows = new WindowList();
     68     @NonNull final AppWindowAnimator mAppAnimator;
     69 
     70     final boolean voiceInteraction;
     71 
     72     Task mTask;
     73     boolean appFullscreen;
     74     int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     75     boolean layoutConfigChanges;
     76     boolean showForAllUsers;
     77     int targetSdk;
     78 
     79     // The input dispatching timeout for this application token in nanoseconds.
     80     long inputDispatchingTimeoutNanos;
     81 
     82     // These are used for determining when all windows associated with
     83     // an activity have been drawn, so they can be made visible together
     84     // at the same time.
     85     // initialize so that it doesn't match mTransactionSequence which is an int.
     86     long lastTransactionSequence = Long.MIN_VALUE;
     87     int numInterestingWindows;
     88     int numDrawnWindows;
     89     boolean inPendingTransaction;
     90     boolean allDrawn;
     91     // Set to true when this app creates a surface while in the middle of an animation. In that
     92     // case do not clear allDrawn until the animation completes.
     93     boolean deferClearAllDrawn;
     94 
     95     // These are to track the app's real drawing status if there were no saved surfaces.
     96     boolean allDrawnExcludingSaved;
     97     int numInterestingWindowsExcludingSaved;
     98     int numDrawnWindowsExclusingSaved;
     99 
    100     // Is this window's surface needed?  This is almost like hidden, except
    101     // it will sometimes be true a little earlier: when the token has
    102     // been shown, but is still waiting for its app transition to execute
    103     // before making its windows shown.
    104     boolean hiddenRequested;
    105 
    106     // Have we told the window clients to hide themselves?
    107     boolean clientHidden;
    108 
    109     // Last visibility state we reported to the app token.
    110     boolean reportedVisible;
    111 
    112     // Last drawn state we reported to the app token.
    113     boolean reportedDrawn;
    114 
    115     // Set to true when the token has been removed from the window mgr.
    116     boolean removed;
    117 
    118     // Information about an application starting window if displayed.
    119     StartingData startingData;
    120     WindowState startingWindow;
    121     View startingView;
    122     boolean startingDisplayed;
    123     boolean startingMoved;
    124     boolean firstWindowDrawn;
    125 
    126     // Input application handle used by the input dispatcher.
    127     final InputApplicationHandle mInputApplicationHandle;
    128 
    129     boolean mIsExiting;
    130 
    131     boolean mLaunchTaskBehind;
    132     boolean mEnteringAnimation;
    133 
    134     boolean mAlwaysFocusable;
    135 
    136     boolean mAppStopped;
    137     int mRotationAnimationHint;
    138     int mPendingRelaunchCount;
    139 
    140     private ArrayList<WindowSurfaceController.SurfaceControlWithBackground> mSurfaceViewBackgrounds =
    141         new ArrayList<WindowSurfaceController.SurfaceControlWithBackground>();
    142 
    143     ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
    144     ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
    145 
    146     AppWindowToken(WindowManagerService _service, IApplicationToken _token,
    147             boolean _voiceInteraction) {
    148         super(_service, _token.asBinder(),
    149                 WindowManager.LayoutParams.TYPE_APPLICATION, true);
    150         appWindowToken = this;
    151         appToken = _token;
    152         voiceInteraction = _voiceInteraction;
    153         mInputApplicationHandle = new InputApplicationHandle(this);
    154         mAppAnimator = new AppWindowAnimator(this);
    155     }
    156 
    157     void sendAppVisibilityToClients() {
    158         final int N = allAppWindows.size();
    159         for (int i=0; i<N; i++) {
    160             WindowState win = allAppWindows.get(i);
    161             if (win == startingWindow && clientHidden) {
    162                 // Don't hide the starting window.
    163                 continue;
    164             }
    165             try {
    166                 if (DEBUG_VISIBILITY) Slog.v(TAG,
    167                         "Setting visibility of " + win + ": " + (!clientHidden));
    168                 win.mClient.dispatchAppVisibility(!clientHidden);
    169             } catch (RemoteException e) {
    170             }
    171         }
    172     }
    173 
    174     void setVisibleBeforeClientHidden() {
    175         for (int i = allAppWindows.size() - 1; i >= 0; i--) {
    176             final WindowState w = allAppWindows.get(i);
    177             w.setVisibleBeforeClientHidden();
    178         }
    179     }
    180 
    181     void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
    182         firstWindowDrawn = true;
    183 
    184         // We now have a good window to show, remove dead placeholders
    185         removeAllDeadWindows();
    186 
    187         if (startingData != null) {
    188             if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting "
    189                     + win.mToken + ": first real window is shown, no animation");
    190             // If this initial window is animating, stop it -- we will do an animation to reveal
    191             // it from behind the starting window, so there is no need for it to also be doing its
    192             // own stuff.
    193             winAnimator.clearAnimation();
    194             winAnimator.mService.mFinishedStarting.add(this);
    195             winAnimator.mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
    196         }
    197         updateReportedVisibilityLocked();
    198     }
    199 
    200     void updateReportedVisibilityLocked() {
    201         if (appToken == null) {
    202             return;
    203         }
    204 
    205         int numInteresting = 0;
    206         int numVisible = 0;
    207         int numDrawn = 0;
    208         boolean nowGone = true;
    209 
    210         if (DEBUG_VISIBILITY) Slog.v(TAG,
    211                 "Update reported visibility: " + this);
    212         final int N = allAppWindows.size();
    213         for (int i=0; i<N; i++) {
    214             WindowState win = allAppWindows.get(i);
    215             if (win == startingWindow || win.mAppFreezing
    216                     || win.mViewVisibility != View.VISIBLE
    217                     || win.mAttrs.type == TYPE_APPLICATION_STARTING
    218                     || win.mDestroying) {
    219                 continue;
    220             }
    221             if (DEBUG_VISIBILITY) {
    222                 Slog.v(TAG, "Win " + win + ": isDrawn="
    223                         + win.isDrawnLw()
    224                         + ", isAnimationSet=" + win.mWinAnimator.isAnimationSet());
    225                 if (!win.isDrawnLw()) {
    226                     Slog.v(TAG, "Not displayed: s=" +
    227                             win.mWinAnimator.mSurfaceController
    228                             + " pv=" + win.mPolicyVisibility
    229                             + " mDrawState=" + win.mWinAnimator.mDrawState
    230                             + " ah=" + win.mAttachedHidden
    231                             + " th="
    232                             + (win.mAppToken != null
    233                                     ? win.mAppToken.hiddenRequested : false)
    234                             + " a=" + win.mWinAnimator.mAnimating);
    235                 }
    236             }
    237             numInteresting++;
    238             if (win.isDrawnLw()) {
    239                 numDrawn++;
    240                 if (!win.mWinAnimator.isAnimationSet()) {
    241                     numVisible++;
    242                 }
    243                 nowGone = false;
    244             } else if (win.mWinAnimator.isAnimationSet()) {
    245                 nowGone = false;
    246             }
    247         }
    248 
    249         boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
    250         boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
    251         if (!nowGone) {
    252             // If the app is not yet gone, then it can only become visible/drawn.
    253             if (!nowDrawn) {
    254                 nowDrawn = reportedDrawn;
    255             }
    256             if (!nowVisible) {
    257                 nowVisible = reportedVisible;
    258             }
    259         }
    260         if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
    261                 + numInteresting + " visible=" + numVisible);
    262         if (nowDrawn != reportedDrawn) {
    263             if (nowDrawn) {
    264                 Message m = service.mH.obtainMessage(
    265                         H.REPORT_APPLICATION_TOKEN_DRAWN, this);
    266                 service.mH.sendMessage(m);
    267             }
    268             reportedDrawn = nowDrawn;
    269         }
    270         if (nowVisible != reportedVisible) {
    271             if (DEBUG_VISIBILITY) Slog.v(
    272                     TAG, "Visibility changed in " + this
    273                     + ": vis=" + nowVisible);
    274             reportedVisible = nowVisible;
    275             Message m = service.mH.obtainMessage(
    276                     H.REPORT_APPLICATION_TOKEN_WINDOWS,
    277                     nowVisible ? 1 : 0,
    278                     nowGone ? 1 : 0,
    279                     this);
    280             service.mH.sendMessage(m);
    281         }
    282     }
    283 
    284     WindowState findMainWindow() {
    285         WindowState candidate = null;
    286         int j = windows.size();
    287         while (j > 0) {
    288             j--;
    289             WindowState win = windows.get(j);
    290             if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
    291                     || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
    292                 // In cases where there are multiple windows, we prefer the non-exiting window. This
    293                 // happens for example when replacing windows during an activity relaunch. When
    294                 // constructing the animation, we want the new window, not the exiting one.
    295                 if (win.mAnimatingExit) {
    296                     candidate = win;
    297                 } else {
    298                     return win;
    299                 }
    300             }
    301         }
    302         return candidate;
    303     }
    304 
    305     boolean windowsAreFocusable() {
    306         return StackId.canReceiveKeys(mTask.mStack.mStackId) || mAlwaysFocusable;
    307     }
    308 
    309     boolean isVisible() {
    310         final int N = allAppWindows.size();
    311         for (int i=0; i<N; i++) {
    312             WindowState win = allAppWindows.get(i);
    313             // If we're animating with a saved surface, we're already visible.
    314             // Return true so that the alpha doesn't get cleared.
    315             if (!win.mAppFreezing
    316                     && (win.mViewVisibility == View.VISIBLE || win.isAnimatingWithSavedSurface()
    317                             || (win.mWinAnimator.isAnimationSet()
    318                                     && !service.mAppTransition.isTransitionSet()))
    319                     && !win.mDestroying
    320                     && win.isDrawnLw()) {
    321                 return true;
    322             }
    323         }
    324         return false;
    325     }
    326 
    327     void removeAppFromTaskLocked() {
    328         mIsExiting = false;
    329         removeAllWindows();
    330 
    331         // Use local variable because removeAppToken will null out mTask.
    332         final Task task = mTask;
    333         if (task != null) {
    334             if (!task.removeAppToken(this)) {
    335                 Slog.e(TAG, "removeAppFromTaskLocked: token=" + this
    336                         + " not found.");
    337             }
    338             task.mStack.mExitingAppTokens.remove(this);
    339         }
    340     }
    341 
    342     void clearAnimatingFlags() {
    343         boolean wallpaperMightChange = false;
    344         for (int i = allAppWindows.size() - 1; i >= 0; i--) {
    345             final WindowState win = allAppWindows.get(i);
    346             // We don't want to clear it out for windows that get replaced, because the
    347             // animation depends on the flag to remove the replaced window.
    348             //
    349             // We also don't clear the mAnimatingExit flag for windows which have the
    350             // mRemoveOnExit flag. This indicates an explicit remove request has been issued
    351             // by the client. We should let animation proceed and not clear this flag or
    352             // they won't eventually be removed by WindowStateAnimator#finishExit.
    353             if (!win.mWillReplaceWindow && !win.mRemoveOnExit) {
    354                 // Clear mAnimating flag together with mAnimatingExit. When animation
    355                 // changes from exiting to entering, we need to clear this flag until the
    356                 // new animation gets applied, so that isAnimationStarting() becomes true
    357                 // until then.
    358                 // Otherwise applySurfaceChangesTransaction will faill to skip surface
    359                 // placement for this window during this period, one or more frame will
    360                 // show up with wrong position or scale.
    361                 if (win.mAnimatingExit) {
    362                     win.mAnimatingExit = false;
    363                     wallpaperMightChange = true;
    364                 }
    365                 if (win.mWinAnimator.mAnimating) {
    366                     win.mWinAnimator.mAnimating = false;
    367                     wallpaperMightChange = true;
    368                 }
    369                 if (win.mDestroying) {
    370                     win.mDestroying = false;
    371                     service.mDestroySurface.remove(win);
    372                     wallpaperMightChange = true;
    373                 }
    374             }
    375         }
    376         if (wallpaperMightChange) {
    377             requestUpdateWallpaperIfNeeded();
    378         }
    379     }
    380 
    381     void destroySurfaces() {
    382         destroySurfaces(false /*cleanupOnResume*/);
    383     }
    384 
    385     /**
    386      * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
    387      * the client has finished with them.
    388      *
    389      * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
    390      * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
    391      * others so that they are ready to be reused. If set to false (common case), destroy all
    392      * surfaces that's eligible, if the app is already stopped.
    393      */
    394 
    395     private void destroySurfaces(boolean cleanupOnResume) {
    396         final ArrayList<WindowState> allWindows = (ArrayList<WindowState>) allAppWindows.clone();
    397         final DisplayContentList displayList = new DisplayContentList();
    398         for (int i = allWindows.size() - 1; i >= 0; i--) {
    399             final WindowState win = allWindows.get(i);
    400 
    401             if (!(mAppStopped || win.mWindowRemovalAllowed || cleanupOnResume)) {
    402                 continue;
    403             }
    404 
    405             win.mWinAnimator.destroyPreservedSurfaceLocked();
    406 
    407             if (!win.mDestroying) {
    408                 continue;
    409             }
    410 
    411             if (DEBUG_ADD_REMOVE) Slog.e(TAG_WM, "win=" + win
    412                     + " destroySurfaces: mAppStopped=" + mAppStopped
    413                     + " win.mWindowRemovalAllowed=" + win.mWindowRemovalAllowed
    414                     + " win.mRemoveOnExit=" + win.mRemoveOnExit);
    415 
    416             if (!cleanupOnResume || win.mRemoveOnExit) {
    417                 win.destroyOrSaveSurface();
    418             }
    419             if (win.mRemoveOnExit) {
    420                 service.removeWindowInnerLocked(win);
    421             }
    422             final DisplayContent displayContent = win.getDisplayContent();
    423             if (displayContent != null && !displayList.contains(displayContent)) {
    424                 displayList.add(displayContent);
    425             }
    426             if (cleanupOnResume) {
    427                 win.requestUpdateWallpaperIfNeeded();
    428             }
    429             win.mDestroying = false;
    430         }
    431         for (int i = 0; i < displayList.size(); i++) {
    432             final DisplayContent displayContent = displayList.get(i);
    433             service.mLayersController.assignLayersLocked(displayContent.getWindowList());
    434             displayContent.layoutNeeded = true;
    435         }
    436     }
    437 
    438     /**
    439      * Notify that the app is now resumed, and it was not stopped before, perform a clean
    440      * up of the surfaces
    441      */
    442     void notifyAppResumed(boolean wasStopped, boolean allowSavedSurface) {
    443         if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
    444                 + " allowSavedSurface=" + allowSavedSurface + " " + this);
    445         mAppStopped = false;
    446         if (!wasStopped) {
    447             destroySurfaces(true /*cleanupOnResume*/);
    448         }
    449         if (!allowSavedSurface) {
    450             destroySavedSurfaces();
    451         }
    452     }
    453 
    454     /**
    455      * Notify that the app has stopped, and it is okay to destroy any surfaces which were
    456      * keeping alive in case they were still being used.
    457      */
    458     void notifyAppStopped() {
    459         if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
    460         mAppStopped = true;
    461         destroySurfaces();
    462         // Remove any starting window that was added for this app if they are still around.
    463         mTask.mService.scheduleRemoveStartingWindowLocked(this);
    464     }
    465 
    466     /**
    467      * Checks whether we should save surfaces for this app.
    468      *
    469      * @return true if the surfaces should be saved, false otherwise.
    470      */
    471     boolean shouldSaveSurface() {
    472         // We want to save surface if the app's windows are "allDrawn".
    473         // (If we started entering animation early with saved surfaces, allDrawn
    474         // should have been restored to true. So we'll save again in that case
    475         // even if app didn't actually finish drawing.)
    476         return allDrawn;
    477     }
    478 
    479     boolean canRestoreSurfaces() {
    480         for (int i = allAppWindows.size() -1; i >= 0; i--) {
    481             final WindowState w = allAppWindows.get(i);
    482             if (w.canRestoreSurface()) {
    483                 return true;
    484             }
    485         }
    486         return false;
    487     }
    488 
    489     void clearVisibleBeforeClientHidden() {
    490         for (int i = allAppWindows.size() - 1; i >= 0; i--) {
    491             final WindowState w = allAppWindows.get(i);
    492             w.clearVisibleBeforeClientHidden();
    493         }
    494     }
    495 
    496     /**
    497      * Whether the app has some window that is invisible in layout, but
    498      * animating with saved surface.
    499      */
    500     boolean isAnimatingInvisibleWithSavedSurface() {
    501         for (int i = allAppWindows.size() - 1; i >= 0; i--) {
    502             final WindowState w = allAppWindows.get(i);
    503             if (w.isAnimatingInvisibleWithSavedSurface()) {
    504                 return true;
    505             }
    506         }
    507         return false;
    508     }
    509 
    510     /**
    511      * Hide all window surfaces that's still invisible in layout but animating
    512      * with a saved surface, and mark them destroying.
    513      */
    514     void stopUsingSavedSurfaceLocked() {
    515         for (int i = allAppWindows.size() - 1; i >= 0; i--) {
    516             final WindowState w = allAppWindows.get(i);
    517             if (w.isAnimatingInvisibleWithSavedSurface()) {
    518                 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.d(TAG,
    519                         "stopUsingSavedSurfaceLocked: " + w);
    520                 w.clearAnimatingWithSavedSurface();
    521                 w.mDestroying = true;
    522                 w.mWinAnimator.hide("stopUsingSavedSurfaceLocked");
    523                 w.mWinAnimator.mWallpaperControllerLocked.hideWallpapers(w);
    524             }
    525         }
    526         destroySurfaces();
    527     }
    528 
    529     void markSavedSurfaceExiting() {
    530         for (int i = allAppWindows.size() - 1; i >= 0; i--) {
    531             final WindowState w = allAppWindows.get(i);
    532             if (w.isAnimatingInvisibleWithSavedSurface()) {
    533                 w.mAnimatingExit = true;
    534                 w.mWinAnimator.mAnimating = true;
    535             }
    536         }
    537     }
    538 
    539     void restoreSavedSurfaces() {
    540         if (!canRestoreSurfaces()) {
    541             clearVisibleBeforeClientHidden();
    542             return;
    543         }
    544         // Check if we have enough drawn windows to mark allDrawn= true.
    545         int numInteresting = 0;
    546         int numDrawn = 0;
    547         for (int i = allAppWindows.size() - 1; i >= 0; i--) {
    548             WindowState w = allAppWindows.get(i);
    549             if (w != startingWindow && !w.mAppDied && w.wasVisibleBeforeClientHidden()
    550                     && (!mAppAnimator.freezingScreen || !w.mAppFreezing)) {
    551                 numInteresting++;
    552                 if (w.hasSavedSurface()) {
    553                     w.restoreSavedSurface();
    554                 }
    555                 if (w.isDrawnLw()) {
    556                     numDrawn++;
    557                 }
    558             }
    559         }
    560 
    561         if (!allDrawn) {
    562             allDrawn = (numInteresting > 0) && (numInteresting == numDrawn);
    563             if (allDrawn) {
    564                 service.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
    565             }
    566         }
    567         clearVisibleBeforeClientHidden();
    568 
    569         if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.d(TAG,
    570                 "restoreSavedSurfaces: " + appWindowToken + " allDrawn=" + allDrawn
    571                 + " numInteresting=" + numInteresting + " numDrawn=" + numDrawn);
    572     }
    573 
    574     void destroySavedSurfaces() {
    575         for (int i = allAppWindows.size() - 1; i >= 0; i--) {
    576             WindowState win = allAppWindows.get(i);
    577             win.destroySavedSurface();
    578         }
    579     }
    580 
    581     void clearAllDrawn() {
    582         allDrawn = false;
    583         deferClearAllDrawn = false;
    584         allDrawnExcludingSaved = false;
    585     }
    586 
    587     @Override
    588     void removeAllWindows() {
    589         for (int winNdx = allAppWindows.size() - 1; winNdx >= 0;
    590                 // removeWindowLocked at bottom of loop may remove multiple entries from
    591                 // allAppWindows if the window to be removed has child windows. It also may
    592                 // not remove any windows from allAppWindows at all if win is exiting and
    593                 // currently animating away. This ensures that winNdx is monotonically decreasing
    594                 // and never beyond allAppWindows bounds.
    595                 winNdx = Math.min(winNdx - 1, allAppWindows.size() - 1)) {
    596             WindowState win = allAppWindows.get(winNdx);
    597             if (DEBUG_WINDOW_MOVEMENT) {
    598                 Slog.w(TAG, "removeAllWindows: removing win=" + win);
    599             }
    600 
    601             service.removeWindowLocked(win);
    602         }
    603         allAppWindows.clear();
    604         windows.clear();
    605     }
    606 
    607     void removeAllDeadWindows() {
    608         for (int winNdx = allAppWindows.size() - 1; winNdx >= 0;
    609             // removeWindowLocked at bottom of loop may remove multiple entries from
    610             // allAppWindows if the window to be removed has child windows. It also may
    611             // not remove any windows from allAppWindows at all if win is exiting and
    612             // currently animating away. This ensures that winNdx is monotonically decreasing
    613             // and never beyond allAppWindows bounds.
    614             winNdx = Math.min(winNdx - 1, allAppWindows.size() - 1)) {
    615             WindowState win = allAppWindows.get(winNdx);
    616             if (win.mAppDied) {
    617                 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
    618                     Slog.w(TAG, "removeAllDeadWindows: " + win);
    619                 }
    620                 // Set mDestroying, we don't want any animation or delayed removal here.
    621                 win.mDestroying = true;
    622                 service.removeWindowLocked(win);
    623             }
    624         }
    625     }
    626 
    627     boolean hasWindowsAlive() {
    628         for (int i = allAppWindows.size() - 1; i >= 0; i--) {
    629             if (!allAppWindows.get(i).mAppDied) {
    630                 return true;
    631             }
    632         }
    633         return false;
    634     }
    635 
    636     void setReplacingWindows(boolean animate) {
    637         if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + appWindowToken
    638                 + " with replacing windows.");
    639 
    640         for (int i = allAppWindows.size() - 1; i >= 0; i--) {
    641             final WindowState w = allAppWindows.get(i);
    642             w.setReplacing(animate);
    643         }
    644         if (animate) {
    645             // Set-up dummy animation so we can start treating windows associated with this
    646             // token like they are in transition before the new app window is ready for us to
    647             // run the real transition animation.
    648             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
    649                     "setReplacingWindow() Setting dummy animation on: " + this);
    650             mAppAnimator.setDummyAnimation();
    651         }
    652     }
    653 
    654     void setReplacingChildren() {
    655         if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + appWindowToken
    656                 + " with replacing child windows.");
    657         for (int i = allAppWindows.size() - 1; i >= 0; i--) {
    658             final WindowState w = allAppWindows.get(i);
    659             if (w.shouldBeReplacedWithChildren()) {
    660                 w.setReplacing(false /* animate */);
    661             }
    662         }
    663     }
    664 
    665     void resetReplacingWindows() {
    666         if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Resetting app token " + appWindowToken
    667                 + " of replacing window marks.");
    668 
    669         for (int i = allAppWindows.size() - 1; i >= 0; i--) {
    670             final WindowState w = allAppWindows.get(i);
    671             w.resetReplacing();
    672         }
    673     }
    674 
    675     void requestUpdateWallpaperIfNeeded() {
    676         for (int i = allAppWindows.size() - 1; i >= 0; i--) {
    677             final WindowState w = allAppWindows.get(i);
    678             w.requestUpdateWallpaperIfNeeded();
    679         }
    680     }
    681 
    682     boolean isRelaunching() {
    683         return mPendingRelaunchCount > 0;
    684     }
    685 
    686     void startRelaunching() {
    687         if (canFreezeBounds()) {
    688             freezeBounds();
    689         }
    690         mPendingRelaunchCount++;
    691     }
    692 
    693     void finishRelaunching() {
    694         if (canFreezeBounds()) {
    695             unfreezeBounds();
    696         }
    697         if (mPendingRelaunchCount > 0) {
    698             mPendingRelaunchCount--;
    699         }
    700     }
    701 
    702     void clearRelaunching() {
    703         if (mPendingRelaunchCount == 0) {
    704             return;
    705         }
    706         if (canFreezeBounds()) {
    707             unfreezeBounds();
    708         }
    709         mPendingRelaunchCount = 0;
    710     }
    711 
    712     void addWindow(WindowState w) {
    713         for (int i = allAppWindows.size() - 1; i >= 0; i--) {
    714             WindowState candidate = allAppWindows.get(i);
    715             if (candidate.mWillReplaceWindow && candidate.mReplacingWindow == null &&
    716                     candidate.getWindowTag().toString().equals(w.getWindowTag().toString())) {
    717                 candidate.mReplacingWindow = w;
    718                 w.mSkipEnterAnimationForSeamlessReplacement = !candidate.mAnimateReplacingWindow;
    719 
    720                 // if we got a replacement window, reset the timeout to give drawing more time
    721                 service.scheduleReplacingWindowTimeouts(this);
    722             }
    723         }
    724         allAppWindows.add(w);
    725     }
    726 
    727     boolean waitingForReplacement() {
    728         for (int i = allAppWindows.size() -1; i >= 0; i--) {
    729             WindowState candidate = allAppWindows.get(i);
    730             if (candidate.mWillReplaceWindow) {
    731                 return true;
    732             }
    733         }
    734         return false;
    735     }
    736 
    737     void clearTimedoutReplacesLocked() {
    738         for (int i = allAppWindows.size() - 1; i >= 0;
    739              // removeWindowLocked at bottom of loop may remove multiple entries from
    740              // allAppWindows if the window to be removed has child windows. It also may
    741              // not remove any windows from allAppWindows at all if win is exiting and
    742              // currently animating away. This ensures that winNdx is monotonically decreasing
    743              // and never beyond allAppWindows bounds.
    744              i = Math.min(i - 1, allAppWindows.size() - 1)) {
    745             WindowState candidate = allAppWindows.get(i);
    746             if (candidate.mWillReplaceWindow == false) {
    747                 continue;
    748             }
    749             candidate.mWillReplaceWindow = false;
    750             if (candidate.mReplacingWindow != null) {
    751                 candidate.mReplacingWindow.mSkipEnterAnimationForSeamlessReplacement = false;
    752             }
    753             // Since the window already timed out, remove it immediately now.
    754             // Use removeWindowInnerLocked() instead of removeWindowLocked(), as the latter
    755             // delays removal on certain conditions, which will leave the stale window in the
    756             // stack and marked mWillReplaceWindow=false, so the window will never be removed.
    757             service.removeWindowInnerLocked(candidate);
    758         }
    759     }
    760 
    761     private boolean canFreezeBounds() {
    762         // For freeform windows, we can't freeze the bounds at the moment because this would make
    763         // the resizing unresponsive.
    764         return mTask != null && !mTask.inFreeformWorkspace();
    765     }
    766 
    767     /**
    768      * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
    769      * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
    770      * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
    771      * with a queue.
    772      */
    773     private void freezeBounds() {
    774         mFrozenBounds.offer(new Rect(mTask.mPreparedFrozenBounds));
    775 
    776         if (mTask.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
    777             // We didn't call prepareFreezingBounds on the task, so use the current value.
    778             final Configuration config = new Configuration(service.mCurConfiguration);
    779             config.updateFrom(mTask.mOverrideConfig);
    780             mFrozenMergedConfig.offer(config);
    781         } else {
    782             mFrozenMergedConfig.offer(new Configuration(mTask.mPreparedFrozenMergedConfig));
    783         }
    784         mTask.mPreparedFrozenMergedConfig.setToDefaults();
    785     }
    786 
    787     /**
    788      * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
    789      */
    790     private void unfreezeBounds() {
    791         if (!mFrozenBounds.isEmpty()) {
    792             mFrozenBounds.remove();
    793         }
    794         if (!mFrozenMergedConfig.isEmpty()) {
    795             mFrozenMergedConfig.remove();
    796         }
    797         for (int i = windows.size() - 1; i >= 0; i--) {
    798             final WindowState win = windows.get(i);
    799             if (!win.mHasSurface) {
    800                 continue;
    801             }
    802             win.mLayoutNeeded = true;
    803             win.setDisplayLayoutNeeded();
    804             if (!service.mResizingWindows.contains(win)) {
    805                 service.mResizingWindows.add(win);
    806             }
    807         }
    808         service.mWindowPlacerLocked.performSurfacePlacement();
    809     }
    810 
    811     void addSurfaceViewBackground(WindowSurfaceController.SurfaceControlWithBackground background) {
    812         mSurfaceViewBackgrounds.add(background);
    813     }
    814 
    815     void removeSurfaceViewBackground(WindowSurfaceController.SurfaceControlWithBackground background) {
    816         mSurfaceViewBackgrounds.remove(background);
    817         updateSurfaceViewBackgroundVisibilities();
    818     }
    819 
    820     // We use DimLayers behind SurfaceViews to prevent holes while resizing and creating.
    821     // However, we need to ensure one SurfaceView doesn't cover another when they are both placed
    822     // below the main app window (as traditionally a SurfaceView which is never drawn
    823     // to is totally translucent). So we look at all our SurfaceView backgrounds and only enable
    824     // the background for the SurfaceView with lowest Z order
    825     void updateSurfaceViewBackgroundVisibilities() {
    826         WindowSurfaceController.SurfaceControlWithBackground bottom = null;
    827         int bottomLayer = Integer.MAX_VALUE;
    828         for (int i = 0; i < mSurfaceViewBackgrounds.size(); i++) {
    829             WindowSurfaceController.SurfaceControlWithBackground sc = mSurfaceViewBackgrounds.get(i);
    830             if (sc.mVisible && sc.mLayer < bottomLayer) {
    831                 bottomLayer = sc.mLayer;
    832                 bottom = sc;
    833             }
    834         }
    835         for (int i = 0; i < mSurfaceViewBackgrounds.size(); i++) {
    836             WindowSurfaceController.SurfaceControlWithBackground sc = mSurfaceViewBackgrounds.get(i);
    837             sc.updateBackgroundVisibility(sc != bottom);
    838         }
    839     }
    840 
    841     @Override
    842     void dump(PrintWriter pw, String prefix) {
    843         super.dump(pw, prefix);
    844         if (appToken != null) {
    845             pw.print(prefix); pw.print("app=true voiceInteraction="); pw.println(voiceInteraction);
    846         }
    847         if (allAppWindows.size() > 0) {
    848             pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
    849         }
    850         pw.print(prefix); pw.print("task="); pw.println(mTask);
    851         pw.print(prefix); pw.print(" appFullscreen="); pw.print(appFullscreen);
    852                 pw.print(" requestedOrientation="); pw.println(requestedOrientation);
    853         pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
    854                 pw.print(" clientHidden="); pw.print(clientHidden);
    855                 pw.print(" reportedDrawn="); pw.print(reportedDrawn);
    856                 pw.print(" reportedVisible="); pw.println(reportedVisible);
    857         if (paused) {
    858             pw.print(prefix); pw.print("paused="); pw.println(paused);
    859         }
    860         if (mAppStopped) {
    861             pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
    862         }
    863         if (numInterestingWindows != 0 || numDrawnWindows != 0
    864                 || allDrawn || mAppAnimator.allDrawn) {
    865             pw.print(prefix); pw.print("numInterestingWindows=");
    866                     pw.print(numInterestingWindows);
    867                     pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
    868                     pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
    869                     pw.print(" allDrawn="); pw.print(allDrawn);
    870                     pw.print(" (animator="); pw.print(mAppAnimator.allDrawn);
    871                     pw.println(")");
    872         }
    873         if (inPendingTransaction) {
    874             pw.print(prefix); pw.print("inPendingTransaction=");
    875                     pw.println(inPendingTransaction);
    876         }
    877         if (startingData != null || removed || firstWindowDrawn || mIsExiting) {
    878             pw.print(prefix); pw.print("startingData="); pw.print(startingData);
    879                     pw.print(" removed="); pw.print(removed);
    880                     pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
    881                     pw.print(" mIsExiting="); pw.println(mIsExiting);
    882         }
    883         if (startingWindow != null || startingView != null
    884                 || startingDisplayed || startingMoved) {
    885             pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
    886                     pw.print(" startingView="); pw.print(startingView);
    887                     pw.print(" startingDisplayed="); pw.print(startingDisplayed);
    888                     pw.print(" startingMoved="); pw.println(startingMoved);
    889         }
    890         if (!mFrozenBounds.isEmpty()) {
    891             pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
    892             pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
    893         }
    894         if (mPendingRelaunchCount != 0) {
    895             pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
    896         }
    897     }
    898 
    899     @Override
    900     public String toString() {
    901         if (stringName == null) {
    902             StringBuilder sb = new StringBuilder();
    903             sb.append("AppWindowToken{");
    904             sb.append(Integer.toHexString(System.identityHashCode(this)));
    905             sb.append(" token="); sb.append(token); sb.append('}');
    906             stringName = sb.toString();
    907         }
    908         return stringName;
    909     }
    910 }
    911