1/*
2 * Copyright (C) 2016 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 android.content.res.Configuration;
20import android.graphics.Rect;
21import android.hardware.power.V1_0.PowerHint;
22import android.os.Binder;
23import android.os.Debug;
24import android.os.Handler;
25import android.os.IBinder;
26import android.os.Looper;
27import android.os.Message;
28import android.os.ParcelFileDescriptor;
29import android.os.PowerManager;
30import android.os.RemoteException;
31import android.os.SystemClock;
32import android.os.UserHandle;
33import android.provider.Settings;
34import android.util.EventLog;
35import android.util.Slog;
36import android.util.SparseIntArray;
37import android.view.Display;
38import android.view.DisplayInfo;
39import android.view.WindowManager;
40
41import com.android.internal.os.SomeArgs;
42import com.android.internal.util.ArrayUtils;
43import com.android.server.EventLogTags;
44
45import java.io.FileDescriptor;
46import java.io.PrintWriter;
47import java.util.ArrayList;
48import java.util.function.Consumer;
49
50import static android.app.AppOpsManager.MODE_ALLOWED;
51import static android.app.AppOpsManager.MODE_DEFAULT;
52import static android.app.AppOpsManager.OP_NONE;
53import static android.view.Display.DEFAULT_DISPLAY;
54import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
55import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
56import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
57import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
58import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
59import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
60import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
61import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
62
63import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
64import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
65import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
66import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
71import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
72import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
73import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
74import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
75import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
76import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
77import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
78import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
79import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
80import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
81import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
82import static com.android.server.wm.WindowManagerService.H.WINDOW_FREEZE_TIMEOUT;
83import static com.android.server.wm.WindowManagerService.logSurface;
84import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
85import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
86import static com.android.server.wm.WindowSurfacePlacer.SET_TURN_ON_SCREEN;
87import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
88import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
89import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
90
91/** Root {@link WindowContainer} for the device. */
92class RootWindowContainer extends WindowContainer<DisplayContent> {
93    private static final String TAG = TAG_WITH_CLASS_NAME ? "RootWindowContainer" : TAG_WM;
94
95    private static final int SET_SCREEN_BRIGHTNESS_OVERRIDE = 1;
96    private static final int SET_USER_ACTIVITY_TIMEOUT = 2;
97
98    WindowManagerService mService;
99
100    private boolean mWallpaperForceHidingChanged = false;
101    private Object mLastWindowFreezeSource = null;
102    private Session mHoldScreen = null;
103    private float mScreenBrightness = -1;
104    private long mUserActivityTimeout = -1;
105    private boolean mUpdateRotation = false;
106    // Following variables are for debugging screen wakelock only.
107    // Last window that requires screen wakelock
108    WindowState mHoldScreenWindow = null;
109    // Last window that obscures all windows below
110    WindowState mObscuringWindow = null;
111    // Only set while traversing the default display based on its content.
112    // Affects the behavior of mirroring on secondary displays.
113    private boolean mObscureApplicationContentOnSecondaryDisplays = false;
114
115    private boolean mSustainedPerformanceModeEnabled = false;
116    private boolean mSustainedPerformanceModeCurrent = false;
117
118    boolean mWallpaperMayChange = false;
119    // During an orientation change, we track whether all windows have rendered
120    // at the new orientation, and this will be false from changing orientation until that occurs.
121    // For seamless rotation cases this always stays true, as the windows complete their orientation
122    // changes 1 by 1 without disturbing global state.
123    boolean mOrientationChangeComplete = true;
124    boolean mWallpaperActionPending = false;
125
126    private final ArrayList<Integer> mChangedStackList = new ArrayList();
127
128    // State for the RemoteSurfaceTrace system used in testing. If this is enabled SurfaceControl
129    // instances will be replaced with an instance that writes a binary representation of all
130    // commands to mSurfaceTraceFd.
131    boolean mSurfaceTraceEnabled;
132    ParcelFileDescriptor mSurfaceTraceFd;
133    RemoteEventTrace mRemoteEventTrace;
134
135    private final WindowLayersController mLayersController;
136    final WallpaperController mWallpaperController;
137
138    private final Handler mHandler;
139
140    private String mCloseSystemDialogsReason;
141    private final Consumer<WindowState> mCloseSystemDialogsConsumer = w -> {
142        if (w.mHasSurface) {
143            try {
144                w.mClient.closeSystemDialogs(mCloseSystemDialogsReason);
145            } catch (RemoteException e) {
146            }
147        }
148    };
149
150    private static final Consumer<WindowState> sRemoveReplacedWindowsConsumer = w -> {
151        final AppWindowToken aToken = w.mAppToken;
152        if (aToken != null) {
153            aToken.removeReplacedWindowIfNeeded(w);
154        }
155    };
156
157    RootWindowContainer(WindowManagerService service) {
158        mService = service;
159        mHandler = new MyHandler(service.mH.getLooper());
160        mLayersController = new WindowLayersController(mService);
161        mWallpaperController = new WallpaperController(mService);
162    }
163
164    WindowState computeFocusedWindow() {
165        for (int i = mChildren.size() - 1; i >= 0; i--) {
166            final DisplayContent dc = mChildren.get(i);
167            final WindowState win = dc.findFocusedWindow();
168            if (win != null) {
169                return win;
170            }
171        }
172        return null;
173    }
174
175    /**
176     * Get an array with display ids ordered by focus priority - last items should be given
177     * focus first. Sparse array just maps position to displayId.
178     */
179    void getDisplaysInFocusOrder(SparseIntArray displaysInFocusOrder) {
180        displaysInFocusOrder.clear();
181
182        final int size = mChildren.size();
183        for (int i = 0; i < size; ++i) {
184            final DisplayContent displayContent = mChildren.get(i);
185            if (displayContent.isRemovalDeferred()) {
186                // Don't report displays that are going to be removed soon.
187                continue;
188            }
189            displaysInFocusOrder.put(i, displayContent.getDisplayId());
190        }
191    }
192
193    /**
194     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
195     * there is a Display for the displayId.
196     *
197     * @param displayId The display the caller is interested in.
198     * @return The DisplayContent associated with displayId or null if there is no Display for it.
199     */
200    DisplayContent getDisplayContentOrCreate(int displayId) {
201        DisplayContent dc = getDisplayContent(displayId);
202
203        if (dc == null) {
204            final Display display = mService.mDisplayManager.getDisplay(displayId);
205            if (display != null) {
206                final long callingIdentity = Binder.clearCallingIdentity();
207                try {
208                    dc = createDisplayContent(display);
209                } finally {
210                    Binder.restoreCallingIdentity(callingIdentity);
211                }
212            }
213        }
214        return dc;
215    }
216
217    DisplayContent getDisplayContent(int displayId) {
218        for (int i = mChildren.size() - 1; i >= 0; --i) {
219            final DisplayContent current = mChildren.get(i);
220            if (current.getDisplayId() == displayId) {
221                return current;
222            }
223        }
224        return null;
225    }
226
227    private DisplayContent createDisplayContent(final Display display) {
228        final DisplayContent dc = new DisplayContent(display, mService, mLayersController,
229                mWallpaperController);
230        final int displayId = display.getDisplayId();
231
232        if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
233
234        final DisplayInfo displayInfo = dc.getDisplayInfo();
235        final Rect rect = new Rect();
236        mService.mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
237        displayInfo.overscanLeft = rect.left;
238        displayInfo.overscanTop = rect.top;
239        displayInfo.overscanRight = rect.right;
240        displayInfo.overscanBottom = rect.bottom;
241        if (mService.mDisplayManagerInternal != null) {
242            mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
243                    displayId, displayInfo);
244            mService.configureDisplayPolicyLocked(dc);
245
246            // TODO(multi-display): Create an input channel for each display with touch capability.
247            if (displayId == DEFAULT_DISPLAY && mService.canDispatchPointerEvents()) {
248                dc.mTapDetector = new TaskTapPointerEventListener(
249                        mService, dc);
250                mService.registerPointerEventListener(dc.mTapDetector);
251                mService.registerPointerEventListener(mService.mMousePositionTracker);
252            }
253        }
254
255        return dc;
256    }
257
258    boolean isLayoutNeeded() {
259        final int numDisplays = mChildren.size();
260        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
261            final DisplayContent displayContent = mChildren.get(displayNdx);
262            if (displayContent.isLayoutNeeded()) {
263                return true;
264            }
265        }
266        return false;
267    }
268
269    void getWindowsByName(ArrayList<WindowState> output, String name) {
270        int objectId = 0;
271        // See if this is an object ID.
272        try {
273            objectId = Integer.parseInt(name, 16);
274            name = null;
275        } catch (RuntimeException e) {
276        }
277
278        getWindowsByName(output, name, objectId);
279    }
280
281    private void getWindowsByName(ArrayList<WindowState> output, String name, int objectId) {
282        forAllWindows((w) -> {
283            if (name != null) {
284                if (w.mAttrs.getTitle().toString().contains(name)) {
285                    output.add(w);
286                }
287            } else if (System.identityHashCode(w) == objectId) {
288                output.add(w);
289            }
290        }, true /* traverseTopToBottom */);
291    }
292
293    /**
294     * Returns the app window token for the input binder if it exist in the system.
295     * NOTE: Only one AppWindowToken is allowed to exist in the system for a binder token, since
296     * AppWindowToken represents an activity which can only exist on one display.
297     */
298    AppWindowToken getAppWindowToken(IBinder binder) {
299        for (int i = mChildren.size() - 1; i >= 0; --i) {
300            final DisplayContent dc = mChildren.get(i);
301            final AppWindowToken atoken = dc.getAppWindowToken(binder);
302            if (atoken != null) {
303                return atoken;
304            }
305        }
306        return null;
307    }
308
309    /** Returns the display object the input window token is currently mapped on. */
310    DisplayContent getWindowTokenDisplay(WindowToken token) {
311        if (token == null) {
312            return null;
313        }
314
315        for (int i = mChildren.size() - 1; i >= 0; --i) {
316            final DisplayContent dc = mChildren.get(i);
317            final WindowToken current = dc.getWindowToken(token.token);
318            if (current == token) {
319                return dc;
320            }
321        }
322
323        return null;
324    }
325
326    /**
327     * Set new display override config and return array of ids of stacks that were changed during
328     * update. If called for the default display, global configuration will also be updated.
329     */
330    int[] setDisplayOverrideConfigurationIfNeeded(Configuration newConfiguration, int displayId) {
331        final DisplayContent displayContent = getDisplayContent(displayId);
332        if (displayContent == null) {
333            throw new IllegalArgumentException("Display not found for id: " + displayId);
334        }
335
336        final Configuration currentConfig = displayContent.getOverrideConfiguration();
337        final boolean configChanged = currentConfig.diff(newConfiguration) != 0;
338        if (!configChanged) {
339            return null;
340        }
341        displayContent.onOverrideConfigurationChanged(newConfiguration);
342
343        if (displayId == DEFAULT_DISPLAY) {
344            // Override configuration of the default display duplicates global config. In this case
345            // we also want to update the global config.
346            return setGlobalConfigurationIfNeeded(newConfiguration);
347        } else {
348            return updateStackBoundsAfterConfigChange(displayId);
349        }
350    }
351
352    private int[] setGlobalConfigurationIfNeeded(Configuration newConfiguration) {
353        final boolean configChanged = getConfiguration().diff(newConfiguration) != 0;
354        if (!configChanged) {
355            return null;
356        }
357        onConfigurationChanged(newConfiguration);
358        return updateStackBoundsAfterConfigChange();
359    }
360
361    @Override
362    void onConfigurationChanged(Configuration newParentConfig) {
363        prepareFreezingTaskBounds();
364        super.onConfigurationChanged(newParentConfig);
365
366        mService.mPolicy.onConfigurationChanged();
367    }
368
369    /**
370     * Callback used to trigger bounds update after configuration change and get ids of stacks whose
371     * bounds were updated.
372     */
373    private int[] updateStackBoundsAfterConfigChange() {
374        mChangedStackList.clear();
375
376        final int numDisplays = mChildren.size();
377        for (int i = 0; i < numDisplays; ++i) {
378            final DisplayContent dc = mChildren.get(i);
379            dc.updateStackBoundsAfterConfigChange(mChangedStackList);
380        }
381
382        return mChangedStackList.isEmpty() ? null : ArrayUtils.convertToIntArray(mChangedStackList);
383    }
384
385    /** Same as {@link #updateStackBoundsAfterConfigChange()} but only for a specific display. */
386    private int[] updateStackBoundsAfterConfigChange(int displayId) {
387        mChangedStackList.clear();
388
389        final DisplayContent dc = getDisplayContent(displayId);
390        dc.updateStackBoundsAfterConfigChange(mChangedStackList);
391
392        return mChangedStackList.isEmpty() ? null : ArrayUtils.convertToIntArray(mChangedStackList);
393    }
394
395    private void prepareFreezingTaskBounds() {
396        for (int i = mChildren.size() - 1; i >= 0; i--) {
397            mChildren.get(i).prepareFreezingTaskBounds();
398        }
399    }
400
401    TaskStack getStackById(int stackId) {
402        for (int i = mChildren.size() - 1; i >= 0; i--) {
403            final DisplayContent dc = mChildren.get(i);
404            final TaskStack stack = dc.getStackById(stackId);
405            if (stack != null) {
406                return stack;
407            }
408        }
409        return null;
410    }
411
412    void setSecureSurfaceState(int userId, boolean disabled) {
413        forAllWindows((w) -> {
414            if (w.mHasSurface && userId == UserHandle.getUserId(w.mOwnerUid)) {
415                w.mWinAnimator.setSecureLocked(disabled);
416            }
417        }, true /* traverseTopToBottom */);
418    }
419
420    void updateAppOpsState() {
421        forAllWindows((w) -> {
422            if (w.mAppOp == OP_NONE) {
423                return;
424            }
425            final int mode = mService.mAppOps.checkOpNoThrow(w.mAppOp, w.getOwningUid(),
426                    w.getOwningPackage());
427            w.setAppOpVisibilityLw(mode == MODE_ALLOWED || mode == MODE_DEFAULT);
428        }, false /* traverseTopToBottom */);
429    }
430
431    boolean canShowStrictModeViolation(int pid) {
432        final WindowState win = getWindow((w) -> w.mSession.mPid == pid && w.isVisibleLw());
433        return win != null;
434    }
435
436    void closeSystemDialogs(String reason) {
437        mCloseSystemDialogsReason = reason;
438        forAllWindows(mCloseSystemDialogsConsumer, false /* traverseTopToBottom */);
439    }
440
441    void removeReplacedWindows() {
442        if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
443        mService.openSurfaceTransaction();
444        try {
445            forAllWindows(sRemoveReplacedWindowsConsumer, true /* traverseTopToBottom */);
446        } finally {
447            mService.closeSurfaceTransaction();
448            if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
449        }
450    }
451
452    boolean hasPendingLayoutChanges(WindowAnimator animator) {
453        boolean hasChanges = false;
454
455        final int count = mChildren.size();
456        for (int i = 0; i < count; ++i) {
457            final DisplayContent dc = mChildren.get(i);
458            final int pendingChanges = animator.getPendingLayoutChanges(dc.getDisplayId());
459            if ((pendingChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
460                animator.mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING;
461            }
462            if (pendingChanges != 0) {
463                hasChanges = true;
464            }
465        }
466
467        return hasChanges;
468    }
469
470    boolean reclaimSomeSurfaceMemory(WindowStateAnimator winAnimator, String operation,
471            boolean secure) {
472        final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;
473        boolean leakedSurface = false;
474        boolean killedApps = false;
475
476        EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
477                winAnimator.mSession.mPid, operation);
478
479        final long callingIdentity = Binder.clearCallingIdentity();
480        try {
481            // There was some problem...first, do a sanity check of the window list to make sure
482            // we haven't left any dangling surfaces around.
483
484            Slog.i(TAG_WM, "Out of memory for surface!  Looking for leaks...");
485            final int numDisplays = mChildren.size();
486            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
487                leakedSurface |= mChildren.get(displayNdx).destroyLeakedSurfaces();
488            }
489
490            if (!leakedSurface) {
491                Slog.w(TAG_WM, "No leaked surfaces; killing applications!");
492                final SparseIntArray pidCandidates = new SparseIntArray();
493                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
494                    mChildren.get(displayNdx).forAllWindows((w) -> {
495                        if (mService.mForceRemoves.contains(w)) {
496                            return;
497                        }
498                        final WindowStateAnimator wsa = w.mWinAnimator;
499                        if (wsa.mSurfaceController != null) {
500                            pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
501                        }
502                    }, false /* traverseTopToBottom */);
503
504                    if (pidCandidates.size() > 0) {
505                        int[] pids = new int[pidCandidates.size()];
506                        for (int i = 0; i < pids.length; i++) {
507                            pids[i] = pidCandidates.keyAt(i);
508                        }
509                        try {
510                            if (mService.mActivityManager.killPids(pids, "Free memory", secure)) {
511                                killedApps = true;
512                            }
513                        } catch (RemoteException e) {
514                        }
515                    }
516                }
517            }
518
519            if (leakedSurface || killedApps) {
520                // We managed to reclaim some memory, so get rid of the trouble surface and ask the
521                // app to request another one.
522                Slog.w(TAG_WM,
523                        "Looks like we have reclaimed some memory, clearing surface for retry.");
524                if (surfaceController != null) {
525                    if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
526                            "RECOVER DESTROY", false);
527                    winAnimator.destroySurface();
528                    if (winAnimator.mWin.mAppToken != null
529                            && winAnimator.mWin.mAppToken.getController() != null) {
530                        winAnimator.mWin.mAppToken.getController().removeStartingWindow();
531                    }
532                }
533
534                try {
535                    winAnimator.mWin.mClient.dispatchGetNewSurface();
536                } catch (RemoteException e) {
537                }
538            }
539        } finally {
540            Binder.restoreCallingIdentity(callingIdentity);
541        }
542
543        return leakedSurface || killedApps;
544    }
545
546    // "Something has changed!  Let's make it correct now."
547    // TODO: Super crazy long method that should be broken down...
548    void performSurfacePlacement(boolean recoveringMemory) {
549        if (DEBUG_WINDOW_TRACE) Slog.v(TAG, "performSurfacePlacementInner: entry. Called by "
550                + Debug.getCallers(3));
551
552        int i;
553        boolean updateInputWindowsNeeded = false;
554
555        if (mService.mFocusMayChange) {
556            mService.mFocusMayChange = false;
557            updateInputWindowsNeeded = mService.updateFocusedWindowLocked(
558                    UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
559        }
560
561        // Initialize state of exiting tokens.
562        final int numDisplays = mChildren.size();
563        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
564            final DisplayContent displayContent = mChildren.get(displayNdx);
565            displayContent.setExitingTokensHasVisible(false);
566        }
567
568        mHoldScreen = null;
569        mScreenBrightness = -1;
570        mUserActivityTimeout = -1;
571        mObscureApplicationContentOnSecondaryDisplays = false;
572        mSustainedPerformanceModeCurrent = false;
573        mService.mTransactionSequence++;
574
575        // TODO(multi-display):
576        final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
577        final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
578        final int defaultDw = defaultInfo.logicalWidth;
579        final int defaultDh = defaultInfo.logicalHeight;
580
581        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
582                ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
583        mService.openSurfaceTransaction();
584        try {
585            applySurfaceChangesTransaction(recoveringMemory, defaultDw, defaultDh);
586        } catch (RuntimeException e) {
587            Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
588        } finally {
589            mService.closeSurfaceTransaction();
590            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
591                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
592        }
593
594        final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
595
596        // If we are ready to perform an app transition, check through all of the app tokens to be
597        // shown and see if they are ready to go.
598        if (mService.mAppTransition.isReady()) {
599            defaultDisplay.pendingLayoutChanges |=
600                    surfacePlacer.handleAppTransitionReadyLocked();
601            if (DEBUG_LAYOUT_REPEATS)
602                surfacePlacer.debugLayoutRepeats("after handleAppTransitionReadyLocked",
603                        defaultDisplay.pendingLayoutChanges);
604        }
605
606        if (!mService.mAnimator.mAppWindowAnimating && mService.mAppTransition.isRunning()) {
607            // We have finished the animation of an app transition. To do this, we have delayed a
608            // lot of operations like showing and hiding apps, moving apps in Z-order, etc. The app
609            // token list reflects the correct Z-order, but the window list may now be out of sync
610            // with it. So here we will just rebuild the entire app window list. Fun!
611            defaultDisplay.pendingLayoutChanges |=
612                    mService.handleAnimatingStoppedAndTransitionLocked();
613            if (DEBUG_LAYOUT_REPEATS)
614                surfacePlacer.debugLayoutRepeats("after handleAnimStopAndXitionLock",
615                        defaultDisplay.pendingLayoutChanges);
616        }
617
618        if (mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
619                && !mService.mAppTransition.isReady()) {
620            // At this point, there was a window with a wallpaper that was force hiding other
621            // windows behind it, but now it is going away. This may be simple -- just animate away
622            // the wallpaper and its window -- or it may be hard -- the wallpaper now needs to be
623            // shown behind something that was hidden.
624            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
625            if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
626                    "after animateAwayWallpaperLocked", defaultDisplay.pendingLayoutChanges);
627        }
628        mWallpaperForceHidingChanged = false;
629
630        if (mWallpaperMayChange) {
631            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change!  Adjusting");
632            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
633            if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("WallpaperMayChange",
634                    defaultDisplay.pendingLayoutChanges);
635        }
636
637        if (mService.mFocusMayChange) {
638            mService.mFocusMayChange = false;
639            if (mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
640                    false /*updateInputWindows*/)) {
641                updateInputWindowsNeeded = true;
642                defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
643            }
644        }
645
646        if (isLayoutNeeded()) {
647            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
648            if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("mLayoutNeeded",
649                    defaultDisplay.pendingLayoutChanges);
650        }
651
652        for (i = mService.mResizingWindows.size() - 1; i >= 0; i--) {
653            WindowState win = mService.mResizingWindows.get(i);
654            if (win.mAppFreezing) {
655                // Don't remove this window until rotation has completed.
656                continue;
657            }
658            // Discard the saved surface if window size is changed, it can't be reused.
659            if (win.mAppToken != null) {
660                win.mAppToken.destroySavedSurfaces();
661            }
662            win.reportResized();
663            mService.mResizingWindows.remove(i);
664        }
665
666        if (DEBUG_ORIENTATION && mService.mDisplayFrozen) Slog.v(TAG,
667                "With display frozen, orientationChangeComplete=" + mOrientationChangeComplete);
668        if (mOrientationChangeComplete) {
669            if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
670                mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
671                mService.mLastFinishedFreezeSource = mLastWindowFreezeSource;
672                mService.mH.removeMessages(WINDOW_FREEZE_TIMEOUT);
673            }
674            mService.stopFreezingDisplayLocked();
675        }
676
677        // Destroy the surface of any windows that are no longer visible.
678        boolean wallpaperDestroyed = false;
679        i = mService.mDestroySurface.size();
680        if (i > 0) {
681            do {
682                i--;
683                WindowState win = mService.mDestroySurface.get(i);
684                win.mDestroying = false;
685                if (mService.mInputMethodWindow == win) {
686                    mService.setInputMethodWindowLocked(null);
687                }
688                if (win.getDisplayContent().mWallpaperController.isWallpaperTarget(win)) {
689                    wallpaperDestroyed = true;
690                }
691                win.destroyOrSaveSurfaceUnchecked();
692            } while (i > 0);
693            mService.mDestroySurface.clear();
694        }
695
696        // Time to remove any exiting tokens?
697        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
698            final DisplayContent displayContent = mChildren.get(displayNdx);
699            displayContent.removeExistingTokensIfPossible();
700        }
701
702        if (wallpaperDestroyed) {
703            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
704            defaultDisplay.setLayoutNeeded();
705        }
706
707        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
708            final DisplayContent displayContent = mChildren.get(displayNdx);
709            if (displayContent.pendingLayoutChanges != 0) {
710                displayContent.setLayoutNeeded();
711            }
712        }
713
714        // Finally update all input windows now that the window changes have stabilized.
715        mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
716
717        mService.setHoldScreenLocked(mHoldScreen);
718        if (!mService.mDisplayFrozen) {
719            final int brightness = mScreenBrightness < 0 || mScreenBrightness > 1.0f
720                    ? -1 : toBrightnessOverride(mScreenBrightness);
721
722            // Post these on a handler such that we don't call into power manager service while
723            // holding the window manager lock to avoid lock contention with power manager lock.
724            mHandler.obtainMessage(SET_SCREEN_BRIGHTNESS_OVERRIDE, brightness, 0).sendToTarget();
725            mHandler.obtainMessage(SET_USER_ACTIVITY_TIMEOUT, mUserActivityTimeout).sendToTarget();
726        }
727
728        if (mSustainedPerformanceModeCurrent != mSustainedPerformanceModeEnabled) {
729            mSustainedPerformanceModeEnabled = mSustainedPerformanceModeCurrent;
730            mService.mPowerManagerInternal.powerHint(
731                    PowerHint.SUSTAINED_PERFORMANCE,
732                    (mSustainedPerformanceModeEnabled ? 1 : 0));
733        }
734
735        if (mService.mTurnOnScreen) {
736            if (mService.mAllowTheaterModeWakeFromLayout
737                    || Settings.Global.getInt(mService.mContext.getContentResolver(),
738                    Settings.Global.THEATER_MODE_ON, 0) == 0) {
739                if (DEBUG_VISIBILITY || DEBUG_POWER) {
740                    Slog.v(TAG, "Turning screen on after layout!");
741                }
742                mService.mPowerManager.wakeUp(SystemClock.uptimeMillis(),
743                        "android.server.wm:TURN_ON");
744            }
745            mService.mTurnOnScreen = false;
746        }
747
748        if (mUpdateRotation) {
749            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
750            // TODO(multi-display): Update rotation for different displays separately.
751            final int displayId = defaultDisplay.getDisplayId();
752            if (defaultDisplay.updateRotationUnchecked(false /* inTransaction */)) {
753                mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget();
754            } else {
755                mUpdateRotation = false;
756            }
757        }
758
759        if (mService.mWaitingForDrawnCallback != null ||
760                (mOrientationChangeComplete && !defaultDisplay.isLayoutNeeded()
761                        && !mUpdateRotation)) {
762            mService.checkDrawnWindowsLocked();
763        }
764
765        final int N = mService.mPendingRemove.size();
766        if (N > 0) {
767            if (mService.mPendingRemoveTmp.length < N) {
768                mService.mPendingRemoveTmp = new WindowState[N+10];
769            }
770            mService.mPendingRemove.toArray(mService.mPendingRemoveTmp);
771            mService.mPendingRemove.clear();
772            ArrayList<DisplayContent> displayList = new ArrayList();
773            for (i = 0; i < N; i++) {
774                final WindowState w = mService.mPendingRemoveTmp[i];
775                w.removeImmediately();
776                final DisplayContent displayContent = w.getDisplayContent();
777                if (displayContent != null && !displayList.contains(displayContent)) {
778                    displayList.add(displayContent);
779                }
780            }
781
782            for (int j = displayList.size() - 1; j >= 0; --j) {
783                final DisplayContent dc = displayList.get(j);
784                dc.assignWindowLayers(true /*setLayoutNeeded*/);
785            }
786        }
787
788        // Remove all deferred displays stacks, tasks, and activities.
789        for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) {
790            mChildren.get(displayNdx).checkCompleteDeferredRemoval();
791        }
792
793        if (updateInputWindowsNeeded) {
794            mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
795        }
796        mService.setFocusTaskRegionLocked(null);
797
798        // Check to see if we are now in a state where the screen should
799        // be enabled, because the window obscured flags have changed.
800        mService.enableScreenIfNeededLocked();
801
802        mService.scheduleAnimationLocked();
803        mService.mWindowPlacerLocked.destroyPendingSurfaces();
804
805        if (DEBUG_WINDOW_TRACE) Slog.e(TAG,
806                "performSurfacePlacementInner exit: animating=" + mService.mAnimator.isAnimating());
807    }
808
809    private void applySurfaceChangesTransaction(boolean recoveringMemory, int defaultDw,
810            int defaultDh) {
811        mHoldScreenWindow = null;
812        mObscuringWindow = null;
813
814        // TODO(multi-display): Support these features on secondary screens.
815        if (mService.mWatermark != null) {
816            mService.mWatermark.positionSurface(defaultDw, defaultDh);
817        }
818        if (mService.mStrictModeFlash != null) {
819            mService.mStrictModeFlash.positionSurface(defaultDw, defaultDh);
820        }
821        if (mService.mCircularDisplayMask != null) {
822            mService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh,
823                    mService.getDefaultDisplayRotation());
824        }
825        if (mService.mEmulatorDisplayOverlay != null) {
826            mService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
827                    mService.getDefaultDisplayRotation());
828        }
829
830        boolean focusDisplayed = false;
831
832        final int count = mChildren.size();
833        for (int j = 0; j < count; ++j) {
834            final DisplayContent dc = mChildren.get(j);
835            focusDisplayed |= dc.applySurfaceChangesTransaction(recoveringMemory);
836        }
837
838        if (focusDisplayed) {
839            mService.mH.sendEmptyMessage(REPORT_LOSING_FOCUS);
840        }
841
842        // Give the display manager a chance to adjust properties like display rotation if it needs
843        // to.
844        mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
845    }
846
847    /**
848     * @param w WindowState this method is applied to.
849     * @param obscured True if there is a window on top of this obscuring the display.
850     * @param syswin System window?
851     * @return True when the display contains content to show the user. When false, the display
852     *          manager may choose to mirror or blank the display.
853     */
854    boolean handleNotObscuredLocked(WindowState w, boolean obscured, boolean syswin) {
855        final WindowManager.LayoutParams attrs = w.mAttrs;
856        final int attrFlags = attrs.flags;
857        final boolean canBeSeen = w.isDisplayedLw();
858        final int privateflags = attrs.privateFlags;
859        boolean displayHasContent = false;
860
861        if (w.mHasSurface && canBeSeen) {
862            if ((attrFlags & FLAG_KEEP_SCREEN_ON) != 0) {
863                mHoldScreen = w.mSession;
864                mHoldScreenWindow = w;
865            } else if (DEBUG_KEEP_SCREEN_ON && w == mService.mLastWakeLockHoldingWindow) {
866                Slog.d(TAG_KEEP_SCREEN_ON, "handleNotObscuredLocked: " + w + " was holding "
867                        + "screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!! called by"
868                        + Debug.getCallers(10));
869            }
870            if (!syswin && w.mAttrs.screenBrightness >= 0 && mScreenBrightness < 0) {
871                mScreenBrightness = w.mAttrs.screenBrightness;
872            }
873            if (!syswin && w.mAttrs.userActivityTimeout >= 0 && mUserActivityTimeout < 0) {
874                mUserActivityTimeout = w.mAttrs.userActivityTimeout;
875            }
876
877            final int type = attrs.type;
878            // This function assumes that the contents of the default display are processed first
879            // before secondary displays.
880            final DisplayContent displayContent = w.getDisplayContent();
881            if (displayContent != null && displayContent.isDefaultDisplay) {
882                // While a dream or keyguard is showing, obscure ordinary application content on
883                // secondary displays (by forcibly enabling mirroring unless there is other content
884                // we want to show) but still allow opaque keyguard dialogs to be shown.
885                if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
886                    mObscureApplicationContentOnSecondaryDisplays = true;
887                }
888                displayHasContent = true;
889            } else if (displayContent != null &&
890                    (!mObscureApplicationContentOnSecondaryDisplays
891                            || (obscured && type == TYPE_KEYGUARD_DIALOG))) {
892                // Allow full screen keyguard presentation dialogs to be seen.
893                displayHasContent = true;
894            }
895            if ((privateflags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) {
896                mSustainedPerformanceModeCurrent = true;
897            }
898        }
899
900        return displayHasContent;
901    }
902
903    boolean copyAnimToLayoutParams() {
904        boolean doRequest = false;
905
906        final int bulkUpdateParams = mService.mAnimator.mBulkUpdateParams;
907        if ((bulkUpdateParams & SET_UPDATE_ROTATION) != 0) {
908            mUpdateRotation = true;
909            doRequest = true;
910        }
911        if ((bulkUpdateParams & SET_WALLPAPER_MAY_CHANGE) != 0) {
912            mWallpaperMayChange = true;
913            doRequest = true;
914        }
915        if ((bulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0) {
916            mWallpaperForceHidingChanged = true;
917            doRequest = true;
918        }
919        if ((bulkUpdateParams & SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
920            mOrientationChangeComplete = false;
921        } else {
922            mOrientationChangeComplete = true;
923            mLastWindowFreezeSource = mService.mAnimator.mLastWindowFreezeSource;
924            if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
925                doRequest = true;
926            }
927        }
928        if ((bulkUpdateParams & SET_TURN_ON_SCREEN) != 0) {
929            mService.mTurnOnScreen = true;
930        }
931        if ((bulkUpdateParams & SET_WALLPAPER_ACTION_PENDING) != 0) {
932            mWallpaperActionPending = true;
933        }
934
935        return doRequest;
936    }
937
938    private static int toBrightnessOverride(float value) {
939        return (int)(value * PowerManager.BRIGHTNESS_ON);
940    }
941
942    private final class MyHandler extends Handler {
943
944        public MyHandler(Looper looper) {
945            super(looper);
946        }
947
948        @Override
949        public void handleMessage(Message msg) {
950            switch (msg.what) {
951                case SET_SCREEN_BRIGHTNESS_OVERRIDE:
952                    mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
953                            msg.arg1);
954                    break;
955                case SET_USER_ACTIVITY_TIMEOUT:
956                    mService.mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
957                            (Long) msg.obj);
958                    break;
959                default:
960                    break;
961            }
962        }
963    }
964
965    void enableSurfaceTrace(ParcelFileDescriptor pfd) {
966        final FileDescriptor fd = pfd.getFileDescriptor();
967        if (mSurfaceTraceEnabled) {
968            disableSurfaceTrace();
969        }
970        mSurfaceTraceEnabled = true;
971        mRemoteEventTrace = new RemoteEventTrace(mService, fd);
972        mSurfaceTraceFd = pfd;
973        for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) {
974            final DisplayContent dc = mChildren.get(displayNdx);
975            dc.enableSurfaceTrace(fd);
976        }
977    }
978
979    void disableSurfaceTrace() {
980        mSurfaceTraceEnabled = false;
981        mRemoteEventTrace = null;
982        mSurfaceTraceFd = null;
983        for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) {
984            final DisplayContent dc = mChildren.get(displayNdx);
985            dc.disableSurfaceTrace();
986        }
987    }
988
989    void dumpDisplayContents(PrintWriter pw) {
990        pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
991        if (mService.mDisplayReady) {
992            final int count = mChildren.size();
993            for (int i = 0; i < count; ++i) {
994                final DisplayContent displayContent = mChildren.get(i);
995                displayContent.dump("  ", pw);
996            }
997        } else {
998            pw.println("  NO DISPLAY");
999        }
1000    }
1001
1002    void dumpLayoutNeededDisplayIds(PrintWriter pw) {
1003        if (!isLayoutNeeded()) {
1004            return;
1005        }
1006        pw.print("  mLayoutNeeded on displays=");
1007        final int count = mChildren.size();
1008        for (int displayNdx = 0; displayNdx < count; ++displayNdx) {
1009            final DisplayContent displayContent = mChildren.get(displayNdx);
1010            if (displayContent.isLayoutNeeded()) {
1011                pw.print(displayContent.getDisplayId());
1012            }
1013        }
1014        pw.println();
1015    }
1016
1017    void dumpWindowsNoHeader(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows) {
1018        final int[] index = new int[1];
1019        forAllWindows((w) -> {
1020            if (windows == null || windows.contains(w)) {
1021                pw.println("  Window #" + index[0] + " " + w + ":");
1022                w.dump(pw, "    ", dumpAll || windows != null);
1023                index[0] = index[0] + 1;
1024            }
1025        }, true /* traverseTopToBottom */);
1026    }
1027
1028    void dumpTokens(PrintWriter pw, boolean dumpAll) {
1029        pw.println("  All tokens:");
1030        for (int i = mChildren.size() - 1; i >= 0; --i) {
1031            mChildren.get(i).dumpTokens(pw, dumpAll);
1032        }
1033    }
1034
1035    @Override
1036    String getName() {
1037        return "ROOT";
1038    }
1039}
1040