OSDN Git Service

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