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