Home | History | Annotate | Download | only in wm
      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.power.V1_0.PowerHint;
     22 import android.os.Binder;
     23 import android.os.Debug;
     24 import android.os.Handler;
     25 import android.os.IBinder;
     26 import android.os.Looper;
     27 import android.os.Message;
     28 import android.os.ParcelFileDescriptor;
     29 import android.os.PowerManager;
     30 import android.os.RemoteException;
     31 import android.os.SystemClock;
     32 import android.os.UserHandle;
     33 import android.provider.Settings;
     34 import android.util.EventLog;
     35 import android.util.Slog;
     36 import android.util.SparseIntArray;
     37 import android.view.Display;
     38 import android.view.DisplayInfo;
     39 import android.view.WindowManager;
     40 
     41 import com.android.internal.os.SomeArgs;
     42 import com.android.internal.util.ArrayUtils;
     43 import com.android.server.EventLogTags;
     44 
     45 import java.io.FileDescriptor;
     46 import java.io.PrintWriter;
     47 import java.util.ArrayList;
     48 import java.util.function.Consumer;
     49 
     50 import static android.app.AppOpsManager.MODE_ALLOWED;
     51 import static android.app.AppOpsManager.MODE_DEFAULT;
     52 import static android.app.AppOpsManager.OP_NONE;
     53 import static android.view.Display.DEFAULT_DISPLAY;
     54 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
     55 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
     56 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
     57 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
     58 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
     59 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
     60 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
     61 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
     62 
     63 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
     64 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
     65 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
     66 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
     67 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
     68 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
     69 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
     70 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
     71 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
     72 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
     73 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
     74 import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
     75 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
     76 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
     77 import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
     78 import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
     79 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
     80 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
     81 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
     82 import static com.android.server.wm.WindowManagerService.H.WINDOW_FREEZE_TIMEOUT;
     83 import static com.android.server.wm.WindowManagerService.logSurface;
     84 import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
     85 import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
     86 import static com.android.server.wm.WindowSurfacePlacer.SET_TURN_ON_SCREEN;
     87 import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
     88 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
     89 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
     90 
     91 /** Root {@link WindowContainer} for the device. */
     92 class 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