RootWindowContainer.java revision 412754816d2b8e83f0f5f860b13f09f53d2da05f
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.server.wm;
18
19import android.app.AppOpsManager;
20import android.content.res.Configuration;
21import android.graphics.Rect;
22import android.hardware.power.V1_0.PowerHint;
23import android.os.Binder;
24import android.os.Debug;
25import android.os.IBinder;
26import android.os.ParcelFileDescriptor;
27import android.os.PowerManager;
28import android.os.RemoteException;
29import android.os.SystemClock;
30import android.os.UserHandle;
31import android.provider.Settings;
32import android.util.EventLog;
33import android.util.Slog;
34import android.util.SparseIntArray;
35import android.view.Display;
36import android.view.DisplayInfo;
37import android.view.InputChannel;
38import android.view.WindowManager;
39import com.android.internal.util.ArrayUtils;
40import com.android.server.EventLogTags;
41import com.android.server.input.InputWindowHandle;
42
43import java.io.FileDescriptor;
44import java.io.PrintWriter;
45import java.util.ArrayList;
46import java.util.HashMap;
47import java.util.LinkedList;
48
49import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
50import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
51import static android.view.Display.DEFAULT_DISPLAY;
52import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
53import static android.view.WindowManager.INPUT_CONSUMER_PIP;
54import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER;
55import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
56import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
57import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
58import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
59import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
60import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
61import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
62import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
63import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
64import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
65import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
66import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
67import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
68import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
74import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
75import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
76import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
77import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
78import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
79import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
80import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
81import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
82import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
83import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
84import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
85import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
86import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
87import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
88import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
89import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
90import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
91import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
92import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
93import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
94import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
95import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
96import static com.android.server.wm.WindowManagerService.H.WINDOW_FREEZE_TIMEOUT;
97import static com.android.server.wm.WindowManagerService.logSurface;
98import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
99import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
100import static com.android.server.wm.WindowSurfacePlacer.SET_TURN_ON_SCREEN;
101import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
102import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
103import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
104
105/** Root {@link WindowContainer} for the device. */
106// TODO: Several methods in here are accessing children of this container's children through various
107// references (WindowList I am looking at you :/). See if we can delegate instead.
108class RootWindowContainer extends WindowContainer<DisplayContent> {
109    private static final String TAG = TAG_WITH_CLASS_NAME ? "RootWindowContainer" : TAG_WM;
110
111    WindowManagerService mService;
112
113    private boolean mWallpaperForceHidingChanged = false;
114    private Object mLastWindowFreezeSource = null;
115    private Session mHoldScreen = null;
116    private float mScreenBrightness = -1;
117    private float mButtonBrightness = -1;
118    private long mUserActivityTimeout = -1;
119    private boolean mUpdateRotation = false;
120    private boolean mObscured = false;
121    private boolean mSyswin = false;
122    // Set to true when the display contains content to show the user.
123    // When false, the display manager may choose to mirror or blank the display.
124    private boolean mDisplayHasContent = false;
125    private float mPreferredRefreshRate = 0;
126    private int mPreferredModeId = 0;
127    // Following variables are for debugging screen wakelock only.
128    // Last window that requires screen wakelock
129    WindowState mHoldScreenWindow = null;
130    // Last window that obscures all windows below
131    WindowState mObscuringWindow = null;
132    // Only set while traversing the default display based on its content.
133    // Affects the behavior of mirroring on secondary displays.
134    private boolean mObscureApplicationContentOnSecondaryDisplays = false;
135
136    private boolean mSustainedPerformanceModeEnabled = false;
137    private boolean mSustainedPerformanceModeCurrent = false;
138
139    boolean mWallpaperMayChange = false;
140    // During an orientation change, we track whether all windows have rendered
141    // at the new orientation, and this will be false from changing orientation until that occurs.
142    // For seamless rotation cases this always stays true, as the windows complete their orientation
143    // changes 1 by 1 without disturbing global state.
144    boolean mOrientationChangeComplete = true;
145    boolean mWallpaperActionPending = false;
146
147    private final ArrayList<Integer> mChangedStackList = new ArrayList();
148
149    private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList();
150
151    private final ArrayList<WindowToken> mTmpTokensList = new ArrayList();
152
153    // Collection of binder tokens mapped to their window type we are allowed to create window
154    // tokens for but that are not current attached to any display. We need to track this here
155    // because a binder token can be added through {@link WindowManagerService#addWindowToken},
156    // but we don't know what display windows for the token will be added to until
157    // {@link WindowManagerService#addWindow} is called.
158    private final HashMap<IBinder, Integer> mUnattachedBinderTokens = new HashMap();
159
160    // State for the RemoteSurfaceTrace system used in testing. If this is enabled SurfaceControl
161    // instances will be replaced with an instance that writes a binary representation of all
162    // commands to mSurfaceTraceFd.
163    boolean mSurfaceTraceEnabled;
164    ParcelFileDescriptor mSurfaceTraceFd;
165    RemoteEventTrace mRemoteEventTrace;
166
167    RootWindowContainer(WindowManagerService service) {
168        mService = service;
169    }
170
171    WindowState computeFocusedWindow() {
172        final int count = mChildren.size();
173        for (int i = 0; i < count; i++) {
174            final DisplayContent dc = mChildren.get(i);
175            final WindowState win = dc.findFocusedWindow();
176            if (win != null) {
177                return win;
178            }
179        }
180        return null;
181    }
182
183    /**
184     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
185     * there is a Display for the displayId.
186     *
187     * @param displayId The display the caller is interested in.
188     * @return The DisplayContent associated with displayId or null if there is no Display for it.
189     */
190    DisplayContent getDisplayContentOrCreate(int displayId) {
191        DisplayContent dc = getDisplayContent(displayId);
192
193        if (dc == null) {
194            final Display display = mService.mDisplayManager.getDisplay(displayId);
195            if (display != null) {
196                dc = createDisplayContent(display);
197            }
198        }
199        return dc;
200    }
201
202    DisplayContent getDisplayContent(int displayId) {
203        for (int i = mChildren.size() - 1; i >= 0; --i) {
204            final DisplayContent current = mChildren.get(i);
205            if (current.getDisplayId() == displayId) {
206                return current;
207            }
208        }
209        return null;
210    }
211
212    private DisplayContent createDisplayContent(final Display display) {
213        final DisplayContent dc = new DisplayContent(display, mService);
214        final int displayId = display.getDisplayId();
215
216        if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
217        addChild(dc, null);
218
219        final DisplayInfo displayInfo = dc.getDisplayInfo();
220        final Rect rect = new Rect();
221        mService.mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
222        displayInfo.overscanLeft = rect.left;
223        displayInfo.overscanTop = rect.top;
224        displayInfo.overscanRight = rect.right;
225        displayInfo.overscanBottom = rect.bottom;
226        if (mService.mDisplayManagerInternal != null) {
227            mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
228                    displayId, displayInfo);
229            mService.configureDisplayPolicyLocked(dc);
230
231            // TODO(multi-display): Create an input channel for each display with touch capability.
232            if (displayId == Display.DEFAULT_DISPLAY) {
233                dc.mTapDetector = new TaskTapPointerEventListener(
234                        mService, dc);
235                mService.registerPointerEventListener(dc.mTapDetector);
236                mService.registerPointerEventListener(mService.mMousePositionTracker);
237            }
238        }
239
240        return dc;
241    }
242
243    /** Adds the input stack id to the input display id and returns the bounds of the added stack.*/
244    Rect addStackToDisplay(int stackId, int displayId, boolean onTop) {
245        final DisplayContent dc = getDisplayContent(displayId);
246        if (dc == null) {
247            Slog.w(TAG_WM, "addStackToDisplay: Trying to add stackId=" + stackId
248                    + " to unknown displayId=" + displayId + " callers=" + Debug.getCallers(6));
249            return null;
250        }
251
252        boolean attachedToDisplay = false;
253        TaskStack stack = mService.mStackIdToStack.get(stackId);
254        if (stack == null) {
255            if (DEBUG_STACK) Slog.d(TAG_WM, "attachStack: stackId=" + stackId);
256
257            stack = dc.getStackById(stackId);
258            if (stack != null) {
259                // It's already attached to the display...clear mDeferRemoval and move stack to
260                // appropriate z-order on display as needed.
261                stack.mDeferRemoval = false;
262                dc.moveStack(stack, onTop);
263                attachedToDisplay = true;
264            } else {
265                stack = new TaskStack(mService, stackId);
266            }
267
268            mService.mStackIdToStack.put(stackId, stack);
269            if (stackId == DOCKED_STACK_ID) {
270                mService.getDefaultDisplayContentLocked().mDividerControllerLocked
271                        .notifyDockedStackExistsChanged(true);
272            }
273        }
274
275        if (!attachedToDisplay) {
276            dc.attachStack(stack, onTop);
277        }
278
279        if (stack.getRawFullscreen()) {
280            return null;
281        }
282        final Rect bounds = new Rect();
283        stack.getRawBounds(bounds);
284        return bounds;
285    }
286
287    boolean isLayoutNeeded() {
288        final int numDisplays = mChildren.size();
289        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
290            final DisplayContent displayContent = mChildren.get(displayNdx);
291            if (displayContent.isLayoutNeeded()) {
292                return true;
293            }
294        }
295        return false;
296    }
297
298    void getWindows(WindowList output) {
299        final int count = mChildren.size();
300        for (int i = 0; i < count; ++i) {
301            final DisplayContent dc = mChildren.get(i);
302            output.addAll(dc.getWindowList());
303        }
304    }
305
306    void getWindows(WindowList output, boolean visibleOnly, boolean appsOnly) {
307        final int numDisplays = mChildren.size();
308        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
309            final WindowList windowList = mChildren.get(displayNdx).getWindowList();
310            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
311                final WindowState w = windowList.get(winNdx);
312                if ((!visibleOnly || w.mWinAnimator.getShown())
313                        && (!appsOnly || w.mAppToken != null)) {
314                    output.add(w);
315                }
316            }
317        }
318    }
319
320    void getWindowsByName(WindowList output, String name) {
321        int objectId = 0;
322        // See if this is an object ID.
323        try {
324            objectId = Integer.parseInt(name, 16);
325            name = null;
326        } catch (RuntimeException e) {
327        }
328        final int numDisplays = mChildren.size();
329        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
330            final WindowList windowList = mChildren.get(displayNdx).getWindowList();
331            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
332                final WindowState w = windowList.get(winNdx);
333                if (name != null) {
334                    if (w.mAttrs.getTitle().toString().contains(name)) {
335                        output.add(w);
336                    }
337                } else if (System.identityHashCode(w) == objectId) {
338                    output.add(w);
339                }
340            }
341        }
342    }
343
344    WindowState findWindow(int hashCode) {
345        final int numDisplays = mChildren.size();
346        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
347            final WindowList windows = mChildren.get(displayNdx).getWindowList();
348            final int numWindows = windows.size();
349            for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
350                final WindowState w = windows.get(winNdx);
351                if (System.identityHashCode(w) == hashCode) {
352                    return w;
353                }
354            }
355        }
356
357        return null;
358    }
359
360    /** Return the window token associated with the input binder token on the input display */
361    WindowToken getWindowToken(IBinder binder, DisplayContent dc) {
362        final WindowToken token = dc.getWindowToken(binder);
363        if (token != null) {
364            return token;
365        }
366
367        // There is no window token mapped to the binder on the display. Create and map a window
368        // token if it is currently allowed.
369        if (!mUnattachedBinderTokens.containsKey(binder)) {
370            return null;
371        }
372
373        final int type = mUnattachedBinderTokens.get(binder);
374        return new WindowToken(mService, binder, type, true, dc);
375    }
376
377    /** Returns all window tokens mapped to the input binder. */
378    ArrayList<WindowToken> getWindowTokens(IBinder binder) {
379        mTmpTokensList.clear();
380        for (int i = mChildren.size() - 1; i >= 0; --i) {
381            final DisplayContent dc = mChildren.get(i);
382            final WindowToken token = dc.getWindowToken(binder);
383            if (token != null) {
384                mTmpTokensList.add(token);
385            }
386        }
387        return mTmpTokensList;
388    }
389
390    /**
391     * Returns the app window token for the input binder if it exist in the system.
392     * NOTE: Only one AppWindowToken is allowed to exist in the system for a binder token, since
393     * AppWindowToken represents an activity which can only exist on one display.
394     */
395    AppWindowToken getAppWindowToken(IBinder binder) {
396        for (int i = mChildren.size() - 1; i >= 0; --i) {
397            final DisplayContent dc = mChildren.get(i);
398            final AppWindowToken atoken = dc.getAppWindowToken(binder);
399            if (atoken != null) {
400                return atoken;
401            }
402        }
403        return null;
404    }
405
406    /** Returns the display object the input window token is currently mapped on. */
407    DisplayContent getWindowTokenDisplay(WindowToken token) {
408        if (token == null) {
409            return null;
410        }
411
412        for (int i = mChildren.size() - 1; i >= 0; --i) {
413            final DisplayContent dc = mChildren.get(i);
414            final WindowToken current = dc.getWindowToken(token.token);
415            if (current == token) {
416                return dc;
417            }
418        }
419
420        return null;
421    }
422
423    void addWindowToken(IBinder binder, int type) {
424        if (mUnattachedBinderTokens.containsKey(binder)) {
425            Slog.w(TAG_WM, "addWindowToken: Attempted to add existing binder token: " + binder);
426            return;
427        }
428
429        final ArrayList<WindowToken> tokens = getWindowTokens(binder);
430
431        if (!tokens.isEmpty()) {
432            Slog.w(TAG_WM, "addWindowToken: Attempted to add binder token: " + binder
433                    + " for already created window tokens: " + tokens);
434            return;
435        }
436
437        mUnattachedBinderTokens.put(binder, type);
438
439        // TODO(multi-display): By default we add this to the default display, but maybe we
440        // should provide an API for a token to be added to any display?
441        final WindowToken token = new WindowToken(mService, binder, type, true,
442                getDisplayContent(DEFAULT_DISPLAY));
443        if (type == TYPE_WALLPAPER) {
444            mService.mWallpaperControllerLocked.addWallpaperToken(token);
445        }
446    }
447
448    ArrayList<WindowToken> removeWindowToken(IBinder binder) {
449        mUnattachedBinderTokens.remove(binder);
450
451        mTmpTokensList.clear();
452        for (int i = mChildren.size() - 1; i >= 0; --i) {
453            final DisplayContent dc = mChildren.get(i);
454            final WindowToken token = dc.removeWindowToken(binder);
455            if (token != null) {
456                mTmpTokensList.add(token);
457            }
458        }
459        return mTmpTokensList;
460    }
461
462    /**
463     * Removed the mapping to the input binder for the system if it no longer as a window token
464     * associated with it on any display.
465     */
466    void removeWindowTokenIfPossible(IBinder binder) {
467        for (int i = mChildren.size() - 1; i >= 0; --i) {
468            final DisplayContent dc = mChildren.get(i);
469            final WindowToken token = dc.getWindowToken(binder);
470            if (token != null) {
471                return;
472            }
473        }
474
475        mUnattachedBinderTokens.remove(binder);
476    }
477
478    void removeAppToken(IBinder binder) {
479        final ArrayList<WindowToken> removedTokens = removeWindowToken(binder);
480        if (removedTokens == null || removedTokens.isEmpty()) {
481            Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder);
482            return;
483        }
484
485        for (int i = removedTokens.size() - 1; i >= 0; --i) {
486            WindowToken wtoken = removedTokens.get(i);
487            AppWindowToken appToken = wtoken.asAppWindowToken();
488
489            if (appToken == null) {
490                Slog.w(TAG_WM,
491                        "Attempted to remove non-App token: " + binder + " wtoken=" + wtoken);
492                continue;
493            }
494
495            AppWindowToken startingToken = null;
496
497            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + appToken);
498
499            boolean delayed = appToken.setVisibility(null, false, TRANSIT_UNSET, true,
500                    appToken.voiceInteraction);
501
502            mService.mOpeningApps.remove(appToken);
503            appToken.waitingToShow = false;
504            if (mService.mClosingApps.contains(appToken)) {
505                delayed = true;
506            } else if (mService.mAppTransition.isTransitionSet()) {
507                mService.mClosingApps.add(appToken);
508                delayed = true;
509            }
510
511            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + appToken
512                    + " delayed=" + delayed
513                    + " animation=" + appToken.mAppAnimator.animation
514                    + " animating=" + appToken.mAppAnimator.animating);
515
516            if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
517                    + appToken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
518
519            final TaskStack stack = appToken.mTask.mStack;
520            if (delayed && !appToken.isEmpty()) {
521                // set the token aside because it has an active animation to be finished
522                if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
523                        "removeAppToken make exiting: " + appToken);
524                stack.mExitingAppTokens.add(appToken);
525                appToken.mIsExiting = true;
526            } else {
527                // Make sure there is no animation running on this token, so any windows associated
528                // with it will be removed as soon as their animations are complete
529                appToken.mAppAnimator.clearAnimation();
530                appToken.mAppAnimator.animating = false;
531                appToken.removeIfPossible();
532            }
533
534            appToken.removed = true;
535            if (appToken.startingData != null) {
536                startingToken = appToken;
537            }
538            appToken.stopFreezingScreen(true, true);
539            if (mService.mFocusedApp == appToken) {
540                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + appToken);
541                mService.mFocusedApp = null;
542                mService.updateFocusedWindowLocked(
543                        UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
544                mService.mInputMonitor.setFocusedAppLw(null);
545            }
546
547            if (!delayed) {
548                appToken.updateReportedVisibilityLocked();
549            }
550
551            // Will only remove if startingToken non null.
552            mService.scheduleRemoveStartingWindowLocked(startingToken);
553        }
554    }
555
556    // TODO: Users would have their own window containers under the display container?
557    void switchUser() {
558        final int count = mChildren.size();
559        for (int i = 0; i < count; ++i) {
560            final DisplayContent dc = mChildren.get(i);
561            dc.switchUser();
562        }
563    }
564
565    /** Set new config and return array of ids of stacks that were changed during update. */
566    int[] setGlobalConfigurationIfNeeded(Configuration newConfiguration) {
567        final boolean configChanged = getConfiguration().diff(newConfiguration) != 0;
568        if (!configChanged) {
569            return null;
570        }
571        onConfigurationChanged(newConfiguration);
572        return updateStackBoundsAfterConfigChange();
573    }
574
575    @Override
576    void onConfigurationChanged(Configuration newParentConfig) {
577        prepareFreezingTaskBounds();
578        super.onConfigurationChanged(newParentConfig);
579
580        mService.mPolicy.onConfigurationChanged();
581    }
582
583    /**
584     * Callback used to trigger bounds update after configuration change and get ids of stacks whose
585     * bounds were updated.
586     */
587    private int[] updateStackBoundsAfterConfigChange() {
588        mChangedStackList.clear();
589
590        final int numDisplays = mChildren.size();
591        for (int i = 0; i < numDisplays; ++i) {
592            final DisplayContent dc = mChildren.get(i);
593            dc.updateStackBoundsAfterConfigChange(mChangedStackList);
594        }
595
596        return mChangedStackList.isEmpty() ? null : ArrayUtils.convertToIntArray(mChangedStackList);
597    }
598
599    private void prepareFreezingTaskBounds() {
600        for (int i = mChildren.size() - 1; i >= 0; i--) {
601            mChildren.get(i).prepareFreezingTaskBounds();
602        }
603    }
604
605    void setSecureSurfaceState(int userId, boolean disabled) {
606        for (int i = mChildren.size() - 1; i >= 0; --i) {
607            final WindowList windows = mChildren.get(i).getWindowList();
608            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
609                final WindowState win = windows.get(winNdx);
610                if (win.mHasSurface && userId == UserHandle.getUserId(win.mOwnerUid)) {
611                    win.mWinAnimator.setSecureLocked(disabled);
612                }
613            }
614        }
615    }
616
617    void updateAppOpsState() {
618        final int count = mChildren.size();
619        for (int i = 0; i < count; ++i) {
620            final WindowList windows = mChildren.get(i).getWindowList();
621            final int numWindows = windows.size();
622            for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
623                final WindowState win = windows.get(winNdx);
624                if (win.mAppOp == AppOpsManager.OP_NONE) {
625                    continue;
626                }
627                final int mode = mService.mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(),
628                        win.getOwningPackage());
629                win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED ||
630                        mode == AppOpsManager.MODE_DEFAULT);
631            }
632        }
633    }
634
635    boolean canShowStrictModeViolation(int pid) {
636        final int count = mChildren.size();
637        for (int i = 0; i < count; ++i) {
638            final WindowList windows = mChildren.get(i).getWindowList();
639            final int numWindows = windows.size();
640            for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
641                final WindowState ws = windows.get(winNdx);
642                if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
643                    return true;
644                }
645            }
646        }
647        return false;
648    }
649
650    void closeSystemDialogs(String reason) {
651        final int count = mChildren.size();
652        for (int i = 0; i < count; ++i) {
653            final WindowList windows = mChildren.get(i).getWindowList();
654            final int numWindows = windows.size();
655            for (int j = 0; j < numWindows; ++j) {
656                final WindowState w = windows.get(j);
657                if (w.mHasSurface) {
658                    try {
659                        w.mClient.closeSystemDialogs(reason);
660                    } catch (RemoteException e) {
661                    }
662                }
663            }
664        }
665    }
666
667    void removeReplacedWindows() {
668        if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
669        mService.openSurfaceTransaction();
670        try {
671            for (int i = mChildren.size() - 1; i >= 0; i--) {
672                DisplayContent dc = mChildren.get(i);
673                final WindowList windows = dc.getWindowList();
674                for (int j = windows.size() - 1; j >= 0; j--) {
675                    final WindowState win = windows.get(j);
676                    final AppWindowToken aToken = win.mAppToken;
677                    if (aToken != null) {
678                        aToken.removeReplacedWindowIfNeeded(win);
679                    }
680                }
681            }
682        } finally {
683            mService.closeSurfaceTransaction();
684            if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
685        }
686    }
687
688    boolean hasPendingLayoutChanges(WindowAnimator animator) {
689        boolean hasChanges = false;
690
691        final int count = mChildren.size();
692        for (int i = 0; i < count; ++i) {
693            final DisplayContent dc = mChildren.get(i);
694            final int pendingChanges = animator.getPendingLayoutChanges(dc.getDisplayId());
695            if ((pendingChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
696                animator.mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING;
697            }
698            if (pendingChanges != 0) {
699                hasChanges = true;
700            }
701        }
702
703        return hasChanges;
704    }
705
706    void updateInputWindows(InputMonitor inputMonitor, WindowState inputFocus, boolean inDrag) {
707        final InputConsumerImpl navInputConsumer =
708                mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_NAVIGATION);
709        final InputConsumerImpl pipInputConsumer =
710                mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_PIP);
711        final InputConsumerImpl wallpaperInputConsumer =
712                mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_WALLPAPER);
713        boolean addInputConsumerHandle = navInputConsumer != null;
714        boolean addPipInputConsumerHandle = pipInputConsumer != null;
715        boolean addWallpaperInputConsumerHandle = wallpaperInputConsumer != null;
716        final Rect pipTouchableBounds = addPipInputConsumerHandle ? new Rect() : null;
717        final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
718        boolean disableWallpaperTouchEvents = false;
719
720        final int count = mChildren.size();
721        for (int i = 0; i < count; ++i) {
722            final DisplayContent dc = mChildren.get(i);
723            final WindowList windows = dc.getWindowList();
724            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
725                final WindowState child = windows.get(winNdx);
726                final InputChannel inputChannel = child.mInputChannel;
727                final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
728                if (inputChannel == null || inputWindowHandle == null || child.mRemoved
729                        || child.isAdjustedForMinimizedDock()) {
730                    // Skip this window because it cannot possibly receive input.
731                    continue;
732                }
733
734                if (addPipInputConsumerHandle
735                        && child.getStackId() == PINNED_STACK_ID
736                        && inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer) {
737                    // Update the bounds of the Pip input consumer to match the Pinned stack
738                    child.getStack().getBounds(pipTouchableBounds);
739                    pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds);
740                    inputMonitor.addInputWindowHandle(pipInputConsumer.mWindowHandle);
741                    addPipInputConsumerHandle = false;
742                }
743
744                if (addInputConsumerHandle
745                        && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
746                    inputMonitor.addInputWindowHandle(navInputConsumer.mWindowHandle);
747                    addInputConsumerHandle = false;
748                }
749
750                if (addWallpaperInputConsumerHandle) {
751                    if (child.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER &&
752                            child.isVisibleLw()) {
753                        // Add the wallpaper input consumer above the first visible wallpaper.
754                        inputMonitor.addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
755                        addWallpaperInputConsumerHandle = false;
756                    }
757                }
758
759                final int flags = child.mAttrs.flags;
760                final int privateFlags = child.mAttrs.privateFlags;
761                final int type = child.mAttrs.type;
762
763                final boolean hasFocus = child == inputFocus;
764                final boolean isVisible = child.isVisibleLw();
765                if ((privateFlags
766                        & WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS)
767                        != 0) {
768                    disableWallpaperTouchEvents = true;
769                }
770                final boolean hasWallpaper = wallpaperController.isWallpaperTarget(child)
771                        && (privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD) == 0
772                        && !disableWallpaperTouchEvents;
773                final boolean onDefaultDisplay = (child.getDisplayId() == Display.DEFAULT_DISPLAY);
774
775                // If there's a drag in progress and 'child' is a potential drop target,
776                // make sure it's been told about the drag
777                if (inDrag && isVisible && onDefaultDisplay) {
778                    mService.mDragState.sendDragStartedIfNeededLw(child);
779                }
780
781                inputMonitor.addInputWindowHandle(
782                        inputWindowHandle, child, flags, type, isVisible, hasFocus, hasWallpaper);
783            }
784        }
785
786        if (addWallpaperInputConsumerHandle) {
787            // No visible wallpaper found, add the wallpaper input consumer at the end.
788            inputMonitor.addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
789        }
790    }
791
792    boolean reclaimSomeSurfaceMemory(WindowStateAnimator winAnimator, String operation,
793            boolean secure) {
794        final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;
795        boolean leakedSurface = false;
796        boolean killedApps = false;
797
798        EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
799                winAnimator.mSession.mPid, operation);
800
801        final long callingIdentity = Binder.clearCallingIdentity();
802        try {
803            // There was some problem...   first, do a sanity check of the window list to make sure
804            // we haven't left any dangling surfaces around.
805
806            Slog.i(TAG_WM, "Out of memory for surface!  Looking for leaks...");
807            final int numDisplays = mChildren.size();
808            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
809                final WindowList windows = mChildren.get(displayNdx).getWindowList();
810                final int numWindows = windows.size();
811                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
812                    final WindowState ws = windows.get(winNdx);
813                    final WindowStateAnimator wsa = ws.mWinAnimator;
814                    if (wsa.mSurfaceController == null) {
815                        continue;
816                    }
817                    if (!mService.mSessions.contains(wsa.mSession)) {
818                        Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
819                                + ws + " surface=" + wsa.mSurfaceController
820                                + " token=" + ws.mToken
821                                + " pid=" + ws.mSession.mPid
822                                + " uid=" + ws.mSession.mUid);
823                        wsa.destroySurface();
824                        mService.mForceRemoves.add(ws);
825                        leakedSurface = true;
826                    } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
827                        Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
828                                + ws + " surface=" + wsa.mSurfaceController
829                                + " token=" + ws.mAppToken
830                                + " saved=" + ws.hasSavedSurface());
831                        if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false);
832                        wsa.destroySurface();
833                        leakedSurface = true;
834                    }
835                }
836            }
837
838            if (!leakedSurface) {
839                Slog.w(TAG_WM, "No leaked surfaces; killing applications!");
840                SparseIntArray pidCandidates = new SparseIntArray();
841                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
842                    final WindowList windows = mChildren.get(displayNdx).getWindowList();
843                    final int numWindows = windows.size();
844                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
845                        final WindowState ws = windows.get(winNdx);
846                        if (mService.mForceRemoves.contains(ws)) {
847                            continue;
848                        }
849                        WindowStateAnimator wsa = ws.mWinAnimator;
850                        if (wsa.mSurfaceController != null) {
851                            pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
852                        }
853                    }
854                    if (pidCandidates.size() > 0) {
855                        int[] pids = new int[pidCandidates.size()];
856                        for (int i = 0; i < pids.length; i++) {
857                            pids[i] = pidCandidates.keyAt(i);
858                        }
859                        try {
860                            if (mService.mActivityManager.killPids(pids, "Free memory", secure)) {
861                                killedApps = true;
862                            }
863                        } catch (RemoteException e) {
864                        }
865                    }
866                }
867            }
868
869            if (leakedSurface || killedApps) {
870                // We managed to reclaim some memory, so get rid of the trouble surface and ask the
871                // app to request another one.
872                Slog.w(TAG_WM,
873                        "Looks like we have reclaimed some memory, clearing surface for retry.");
874                if (surfaceController != null) {
875                    if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
876                            "RECOVER DESTROY", false);
877                    winAnimator.destroySurface();
878                    mService.scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken);
879                }
880
881                try {
882                    winAnimator.mWin.mClient.dispatchGetNewSurface();
883                } catch (RemoteException e) {
884                }
885            }
886        } finally {
887            Binder.restoreCallingIdentity(callingIdentity);
888        }
889
890        return leakedSurface || killedApps;
891    }
892
893    // "Something has changed!  Let's make it correct now."
894    // TODO: Super crazy long method that should be broken down...
895    void performSurfacePlacement(boolean recoveringMemory) {
896        if (DEBUG_WINDOW_TRACE) Slog.v(TAG, "performSurfacePlacementInner: entry. Called by "
897                + Debug.getCallers(3));
898
899        int i;
900        boolean updateInputWindowsNeeded = false;
901
902        if (mService.mFocusMayChange) {
903            mService.mFocusMayChange = false;
904            updateInputWindowsNeeded = mService.updateFocusedWindowLocked(
905                    UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
906        }
907
908        // Initialize state of exiting tokens.
909        final int numDisplays = mChildren.size();
910        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
911            final DisplayContent displayContent = mChildren.get(displayNdx);
912            for (i = displayContent.mExitingTokens.size() - 1; i >= 0; i--) {
913                displayContent.mExitingTokens.get(i).hasVisible = false;
914            }
915        }
916
917        for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
918            // Initialize state of exiting applications.
919            final AppTokenList exitingAppTokens =
920                    mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
921            for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
922                exitingAppTokens.get(tokenNdx).hasVisible = false;
923            }
924        }
925
926        mHoldScreen = null;
927        mScreenBrightness = -1;
928        mButtonBrightness = -1;
929        mUserActivityTimeout = -1;
930        mObscureApplicationContentOnSecondaryDisplays = false;
931        mSustainedPerformanceModeCurrent = false;
932        mService.mTransactionSequence++;
933
934        // TODO(multi-display):
935        final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
936        final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
937        final int defaultDw = defaultInfo.logicalWidth;
938        final int defaultDh = defaultInfo.logicalHeight;
939
940        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
941                ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
942        mService.openSurfaceTransaction();
943        try {
944            applySurfaceChangesTransaction(recoveringMemory, defaultDw, defaultDh);
945        } catch (RuntimeException e) {
946            Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
947        } finally {
948            mService.closeSurfaceTransaction();
949            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
950                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
951        }
952
953        final WindowList defaultWindows = defaultDisplay.getWindowList();
954        final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
955
956        // If we are ready to perform an app transition, check through all of the app tokens to be
957        // shown and see if they are ready to go.
958        if (mService.mAppTransition.isReady()) {
959            defaultDisplay.pendingLayoutChanges |=
960                    surfacePlacer.handleAppTransitionReadyLocked(defaultWindows);
961            if (DEBUG_LAYOUT_REPEATS)
962                surfacePlacer.debugLayoutRepeats("after handleAppTransitionReadyLocked",
963                        defaultDisplay.pendingLayoutChanges);
964        }
965
966        if (!mService.mAnimator.mAppWindowAnimating && mService.mAppTransition.isRunning()) {
967            // We have finished the animation of an app transition. To do this, we have delayed a
968            // lot of operations like showing and hiding apps, moving apps in Z-order, etc. The app
969            // token list reflects the correct Z-order, but the window list may now be out of sync
970            // with it. So here we will just rebuild the entire app window list. Fun!
971            defaultDisplay.pendingLayoutChanges |=
972                    mService.handleAnimatingStoppedAndTransitionLocked();
973            if (DEBUG_LAYOUT_REPEATS)
974                surfacePlacer.debugLayoutRepeats("after handleAnimStopAndXitionLock",
975                        defaultDisplay.pendingLayoutChanges);
976        }
977
978        if (mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
979                && !mService.mAppTransition.isReady()) {
980            // At this point, there was a window with a wallpaper that was force hiding other
981            // windows behind it, but now it is going away. This may be simple -- just animate away
982            // the wallpaper and its window -- or it may be hard -- the wallpaper now needs to be
983            // shown behind something that was hidden.
984            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
985            if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
986                    "after animateAwayWallpaperLocked", defaultDisplay.pendingLayoutChanges);
987        }
988        mWallpaperForceHidingChanged = false;
989
990        if (mWallpaperMayChange) {
991            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change!  Adjusting");
992            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
993            if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("WallpaperMayChange",
994                    defaultDisplay.pendingLayoutChanges);
995        }
996
997        if (mService.mFocusMayChange) {
998            mService.mFocusMayChange = false;
999            if (mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
1000                    false /*updateInputWindows*/)) {
1001                updateInputWindowsNeeded = true;
1002                defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
1003            }
1004        }
1005
1006        if (isLayoutNeeded()) {
1007            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
1008            if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("mLayoutNeeded",
1009                    defaultDisplay.pendingLayoutChanges);
1010        }
1011
1012        for (i = mService.mResizingWindows.size() - 1; i >= 0; i--) {
1013            WindowState win = mService.mResizingWindows.get(i);
1014            if (win.mAppFreezing) {
1015                // Don't remove this window until rotation has completed.
1016                continue;
1017            }
1018            // Discard the saved surface if window size is changed, it can't be reused.
1019            if (win.mAppToken != null) {
1020                win.mAppToken.destroySavedSurfaces();
1021            }
1022            win.reportResized();
1023            mService.mResizingWindows.remove(i);
1024        }
1025
1026        if (DEBUG_ORIENTATION && mService.mDisplayFrozen) Slog.v(TAG,
1027                "With display frozen, orientationChangeComplete=" + mOrientationChangeComplete);
1028        if (mOrientationChangeComplete) {
1029            if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
1030                mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
1031                mService.mLastFinishedFreezeSource = mLastWindowFreezeSource;
1032                mService.mH.removeMessages(WINDOW_FREEZE_TIMEOUT);
1033            }
1034            mService.stopFreezingDisplayLocked();
1035        }
1036
1037        // Destroy the surface of any windows that are no longer visible.
1038        boolean wallpaperDestroyed = false;
1039        i = mService.mDestroySurface.size();
1040        if (i > 0) {
1041            do {
1042                i--;
1043                WindowState win = mService.mDestroySurface.get(i);
1044                win.mDestroying = false;
1045                if (mService.mInputMethodWindow == win) {
1046                    mService.mInputMethodWindow = null;
1047                }
1048                if (mService.mWallpaperControllerLocked.isWallpaperTarget(win)) {
1049                    wallpaperDestroyed = true;
1050                }
1051                win.destroyOrSaveSurface();
1052            } while (i > 0);
1053            mService.mDestroySurface.clear();
1054        }
1055
1056        // Time to remove any exiting tokens?
1057        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
1058            final DisplayContent displayContent = mChildren.get(displayNdx);
1059            ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
1060            for (i = exitingTokens.size() - 1; i >= 0; i--) {
1061                WindowToken token = exitingTokens.get(i);
1062                if (!token.hasVisible) {
1063                    exitingTokens.remove(i);
1064                    if (token.windowType == TYPE_WALLPAPER) {
1065                        mService.mWallpaperControllerLocked.removeWallpaperToken(token);
1066                    }
1067                }
1068            }
1069        }
1070
1071        // Time to remove any exiting applications?
1072        for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
1073            // Initialize state of exiting applications.
1074            final AppTokenList exitingAppTokens =
1075                    mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
1076            for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
1077                final AppWindowToken token = exitingAppTokens.get(i);
1078                if (!token.hasVisible && !mService.mClosingApps.contains(token) &&
1079                        (!token.mIsExiting || token.isEmpty())) {
1080                    // Make sure there is no animation running on this token, so any windows
1081                    // associated with it will be removed as soon as their animations are complete
1082                    token.mAppAnimator.clearAnimation();
1083                    token.mAppAnimator.animating = false;
1084                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
1085                            "performLayout: App token exiting now removed" + token);
1086                    token.removeIfPossible();
1087                }
1088            }
1089        }
1090
1091        if (wallpaperDestroyed) {
1092            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1093            defaultDisplay.setLayoutNeeded();
1094        }
1095
1096        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
1097            final DisplayContent displayContent = mChildren.get(displayNdx);
1098            if (displayContent.pendingLayoutChanges != 0) {
1099                displayContent.setLayoutNeeded();
1100            }
1101        }
1102
1103        // Finally update all input windows now that the window changes have stabilized.
1104        mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
1105
1106        mService.setHoldScreenLocked(mHoldScreen);
1107        if (!mService.mDisplayFrozen) {
1108            if (mScreenBrightness < 0 || mScreenBrightness > 1.0f) {
1109                mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1);
1110            } else {
1111                mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
1112                        toBrightnessOverride(mScreenBrightness));
1113            }
1114            if (mButtonBrightness < 0 || mButtonBrightness > 1.0f) {
1115                mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1);
1116            } else {
1117                mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(
1118                        toBrightnessOverride(mButtonBrightness));
1119            }
1120            mService.mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
1121                    mUserActivityTimeout);
1122        }
1123
1124        if (mSustainedPerformanceModeCurrent != mSustainedPerformanceModeEnabled) {
1125            mSustainedPerformanceModeEnabled = mSustainedPerformanceModeCurrent;
1126            mService.mPowerManagerInternal.powerHint(
1127                    PowerHint.SUSTAINED_PERFORMANCE,
1128                    (mSustainedPerformanceModeEnabled ? 1 : 0));
1129        }
1130
1131        if (mService.mTurnOnScreen) {
1132            if (mService.mAllowTheaterModeWakeFromLayout
1133                    || Settings.Global.getInt(mService.mContext.getContentResolver(),
1134                    Settings.Global.THEATER_MODE_ON, 0) == 0) {
1135                if (DEBUG_VISIBILITY || DEBUG_POWER) {
1136                    Slog.v(TAG, "Turning screen on after layout!");
1137                }
1138                mService.mPowerManager.wakeUp(SystemClock.uptimeMillis(),
1139                        "android.server.wm:TURN_ON");
1140            }
1141            mService.mTurnOnScreen = false;
1142        }
1143
1144        if (mUpdateRotation) {
1145            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
1146            if (mService.updateRotationUncheckedLocked(false)) {
1147                mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
1148            } else {
1149                mUpdateRotation = false;
1150            }
1151        }
1152
1153        if (mService.mWaitingForDrawnCallback != null ||
1154                (mOrientationChangeComplete && !defaultDisplay.isLayoutNeeded()
1155                        && !mUpdateRotation)) {
1156            mService.checkDrawnWindowsLocked();
1157        }
1158
1159        final int N = mService.mPendingRemove.size();
1160        if (N > 0) {
1161            if (mService.mPendingRemoveTmp.length < N) {
1162                mService.mPendingRemoveTmp = new WindowState[N+10];
1163            }
1164            mService.mPendingRemove.toArray(mService.mPendingRemoveTmp);
1165            mService.mPendingRemove.clear();
1166            DisplayContentList displayList = new DisplayContentList();
1167            for (i = 0; i < N; i++) {
1168                final WindowState w = mService.mPendingRemoveTmp[i];
1169                w.removeImmediately();
1170                final DisplayContent displayContent = w.getDisplayContent();
1171                if (displayContent != null && !displayList.contains(displayContent)) {
1172                    displayList.add(displayContent);
1173                }
1174            }
1175
1176            for (DisplayContent displayContent : displayList) {
1177                mService.mLayersController.assignLayersLocked(displayContent.getWindowList());
1178                displayContent.setLayoutNeeded();
1179            }
1180        }
1181
1182        // Remove all deferred displays stacks, tasks, and activities.
1183        for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) {
1184            mChildren.get(displayNdx).checkCompleteDeferredRemoval();
1185        }
1186
1187        if (updateInputWindowsNeeded) {
1188            mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
1189        }
1190        mService.setFocusTaskRegionLocked();
1191
1192        // Check to see if we are now in a state where the screen should
1193        // be enabled, because the window obscured flags have changed.
1194        mService.enableScreenIfNeededLocked();
1195
1196        mService.scheduleAnimationLocked();
1197        mService.mWindowPlacerLocked.destroyPendingSurfaces();
1198
1199        if (DEBUG_WINDOW_TRACE) Slog.e(TAG,
1200                "performSurfacePlacementInner exit: animating=" + mService.mAnimator.isAnimating());
1201    }
1202
1203    // TODO: Super crazy long method that should be broken down...
1204    private void applySurfaceChangesTransaction(boolean recoveringMemory, int defaultDw, int defaultDh) {
1205        mHoldScreenWindow = null;
1206        mObscuringWindow = null;
1207
1208        if (mService.mWatermark != null) {
1209            mService.mWatermark.positionSurface(defaultDw, defaultDh);
1210        }
1211        if (mService.mStrictModeFlash != null) {
1212            mService.mStrictModeFlash.positionSurface(defaultDw, defaultDh);
1213        }
1214        if (mService.mCircularDisplayMask != null) {
1215            mService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mService.mRotation);
1216        }
1217        if (mService.mEmulatorDisplayOverlay != null) {
1218            mService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
1219                    mService.mRotation);
1220        }
1221
1222        boolean focusDisplayed = false;
1223
1224        final int count = mChildren.size();
1225        for (int j = 0; j < count; ++j) {
1226            final DisplayContent dc = mChildren.get(j);
1227            WindowList windows = dc.getWindowList();
1228            DisplayInfo displayInfo = dc.getDisplayInfo();
1229            final int displayId = dc.getDisplayId();
1230            final int dw = displayInfo.logicalWidth;
1231            final int dh = displayInfo.logicalHeight;
1232            final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
1233            final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
1234
1235            // Reset for each display.
1236            mDisplayHasContent = false;
1237            mPreferredRefreshRate = 0;
1238            mPreferredModeId = 0;
1239            mTmpUpdateAllDrawn.clear();
1240
1241            int repeats = 0;
1242            do {
1243                repeats++;
1244                if (repeats > 6) {
1245                    Slog.w(TAG, "Animation repeat aborted after too many iterations");
1246                    dc.clearLayoutNeeded();
1247                    break;
1248                }
1249
1250                if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
1251                        "On entry to LockedInner", dc.pendingLayoutChanges);
1252
1253                if ((dc.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0
1254                        && mService.mWallpaperControllerLocked.adjustWallpaperWindows()) {
1255                    mService.mLayersController.assignLayersLocked(windows);
1256                    dc.setLayoutNeeded();
1257                }
1258
1259                if (isDefaultDisplay
1260                        && (dc.pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
1261                    if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
1262                    if (mService.updateOrientationFromAppTokensLocked(true)) {
1263                        dc.setLayoutNeeded();
1264                        mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
1265                    }
1266                }
1267
1268                if ((dc.pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
1269                    dc.setLayoutNeeded();
1270                }
1271
1272                // FIRST LOOP: Perform a layout, if needed.
1273                if (repeats < LAYOUT_REPEAT_THRESHOLD) {
1274                    surfacePlacer.performLayoutLockedInner(dc, repeats == 1,
1275                            false /* updateInputWindows */);
1276                } else {
1277                    Slog.w(TAG, "Layout repeat skipped after too many iterations");
1278                }
1279
1280                // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
1281                // it is animating.
1282                dc.pendingLayoutChanges = 0;
1283
1284                if (isDefaultDisplay) {
1285                    mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
1286                    for (int i = windows.size() - 1; i >= 0; i--) {
1287                        WindowState w = windows.get(i);
1288                        if (w.mHasSurface) {
1289                            mService.mPolicy.applyPostLayoutPolicyLw(
1290                                    w, w.mAttrs, w.getParentWindow());
1291                        }
1292                    }
1293                    dc.pendingLayoutChanges |=
1294                            mService.mPolicy.finishPostLayoutPolicyLw();
1295                    if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
1296                            "after finishPostLayoutPolicyLw", dc.pendingLayoutChanges);
1297                }
1298            } while (dc.pendingLayoutChanges != 0);
1299
1300            mObscured = false;
1301            mSyswin = false;
1302            dc.resetDimming();
1303
1304            // Only used if default window
1305            final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty();
1306
1307            for (int i = windows.size() - 1; i >= 0; i--) {
1308                WindowState w = windows.get(i);
1309                final Task task = w.getTask();
1310                final boolean obscuredChanged = w.mObscured != mObscured;
1311
1312                // Update effect.
1313                w.mObscured = mObscured;
1314                if (!mObscured) {
1315                    handleNotObscuredLocked(w, displayInfo);
1316                }
1317
1318                w.applyDimLayerIfNeeded();
1319
1320                if (isDefaultDisplay && obscuredChanged && w.isVisibleLw()
1321                        && mService.mWallpaperControllerLocked.isWallpaperTarget(w)) {
1322                    // This is the wallpaper target and its obscured state changed... make sure the
1323                    // current wallpaper's visibility has been updated accordingly.
1324                    mService.mWallpaperControllerLocked.updateWallpaperVisibility();
1325                }
1326
1327                w.handleWindowMovedIfNeeded();
1328
1329                final WindowStateAnimator winAnimator = w.mWinAnimator;
1330
1331                //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
1332                w.mContentChanged = false;
1333
1334                // Moved from updateWindowsAndWallpaperLocked().
1335                if (w.mHasSurface) {
1336                    // Take care of the window being ready to display.
1337                    final boolean committed = winAnimator.commitFinishDrawingLocked();
1338                    if (isDefaultDisplay && committed) {
1339                        if (w.mAttrs.type == TYPE_DREAM) {
1340                            // HACK: When a dream is shown, it may at that point hide the lock
1341                            // screen. So we need to redo the layout to let the phone window manager
1342                            // make this happen.
1343                            dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
1344                            if (DEBUG_LAYOUT_REPEATS) {
1345                                surfacePlacer.debugLayoutRepeats(
1346                                        "dream and commitFinishDrawingLocked true",
1347                                        dc.pendingLayoutChanges);
1348                            }
1349                        }
1350                        if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
1351                            if (DEBUG_WALLPAPER_LIGHT)
1352                                Slog.v(TAG, "First draw done in potential wallpaper target " + w);
1353                            mWallpaperMayChange = true;
1354                            dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1355                            if (DEBUG_LAYOUT_REPEATS) {
1356                                surfacePlacer.debugLayoutRepeats(
1357                                        "wallpaper and commitFinishDrawingLocked true",
1358                                        dc.pendingLayoutChanges);
1359                            }
1360                        }
1361                    }
1362                    if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) {
1363                        // Updates the shown frame before we set up the surface. This is needed
1364                        // because the resizing could change the top-left position (in addition to
1365                        // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to
1366                        // position the surface.
1367                        //
1368                        // If an animation is being started, we can't call this method because the
1369                        // animation hasn't processed its initial transformation yet, but in general
1370                        // we do want to update the position if the window is animating.
1371                        winAnimator.computeShownFrameLocked();
1372                    }
1373                    winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
1374                }
1375
1376                final AppWindowToken atoken = w.mAppToken;
1377                if (atoken != null) {
1378                    final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w);
1379                    if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) {
1380                        mTmpUpdateAllDrawn.add(atoken);
1381                    }
1382                }
1383
1384                if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus
1385                        && w.isDisplayedLw()) {
1386                    focusDisplayed = true;
1387                }
1388
1389                w.updateResizingWindowIfNeeded();
1390            }
1391
1392            mService.mDisplayManagerInternal.setDisplayProperties(displayId,
1393                    mDisplayHasContent,
1394                    mPreferredRefreshRate,
1395                    mPreferredModeId,
1396                    true /* inTraversal, must call performTraversalInTrans... below */);
1397
1398            dc.stopDimmingIfNeeded();
1399
1400            while (!mTmpUpdateAllDrawn.isEmpty()) {
1401                final AppWindowToken atoken = mTmpUpdateAllDrawn.removeLast();
1402                // See if any windows have been drawn, so they (and others associated with them)
1403                // can now be shown.
1404                atoken.updateAllDrawn(dc);
1405            }
1406        }
1407
1408        if (focusDisplayed) {
1409            mService.mH.sendEmptyMessage(REPORT_LOSING_FOCUS);
1410        }
1411
1412        // Give the display manager a chance to adjust properties
1413        // like display rotation if it needs to.
1414        mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
1415    }
1416
1417    /**
1418     * @param w WindowState this method is applied to.
1419     * @param dispInfo info of the display that the window's obscuring state is checked against.
1420     */
1421    private void handleNotObscuredLocked(final WindowState w, final DisplayInfo dispInfo) {
1422        final WindowManager.LayoutParams attrs = w.mAttrs;
1423        final int attrFlags = attrs.flags;
1424        final boolean canBeSeen = w.isDisplayedLw();
1425        final int privateflags = attrs.privateFlags;
1426
1427        if (canBeSeen && w.isObscuringFullscreen(dispInfo)) {
1428            // This window completely covers everything behind it,
1429            // so we want to leave all of them as undimmed (for
1430            // performance reasons).
1431            if (!mObscured) {
1432                mObscuringWindow = w;
1433            }
1434
1435            mObscured = true;
1436        }
1437
1438        if (w.mHasSurface && canBeSeen) {
1439            if ((attrFlags & FLAG_KEEP_SCREEN_ON) != 0) {
1440                mHoldScreen = w.mSession;
1441                mHoldScreenWindow = w;
1442            } else if (DEBUG_KEEP_SCREEN_ON && w == mService.mLastWakeLockHoldingWindow) {
1443                Slog.d(TAG_KEEP_SCREEN_ON, "handleNotObscuredLocked: " + w + " was holding "
1444                        + "screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!! called by"
1445                        + Debug.getCallers(10));
1446            }
1447            if (!mSyswin && w.mAttrs.screenBrightness >= 0 && mScreenBrightness < 0) {
1448                mScreenBrightness = w.mAttrs.screenBrightness;
1449            }
1450            if (!mSyswin && w.mAttrs.buttonBrightness >= 0 && mButtonBrightness < 0) {
1451                mButtonBrightness = w.mAttrs.buttonBrightness;
1452            }
1453            if (!mSyswin && w.mAttrs.userActivityTimeout >= 0 && mUserActivityTimeout < 0) {
1454                mUserActivityTimeout = w.mAttrs.userActivityTimeout;
1455            }
1456
1457            final int type = attrs.type;
1458            if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
1459                    || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
1460                mSyswin = true;
1461            }
1462
1463            // This function assumes that the contents of the default display are processed first
1464            // before secondary displays.
1465            final DisplayContent displayContent = w.getDisplayContent();
1466            if (displayContent != null && displayContent.isDefaultDisplay) {
1467                // While a dream or keyguard is showing, obscure ordinary application content on
1468                // secondary displays (by forcibly enabling mirroring unless there is other content
1469                // we want to show) but still allow opaque keyguard dialogs to be shown.
1470                if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
1471                    mObscureApplicationContentOnSecondaryDisplays = true;
1472                }
1473                mDisplayHasContent = true;
1474            } else if (displayContent != null &&
1475                    (!mObscureApplicationContentOnSecondaryDisplays
1476                            || (mObscured && type == TYPE_KEYGUARD_DIALOG))) {
1477                // Allow full screen keyguard presentation dialogs to be seen.
1478                mDisplayHasContent = true;
1479            }
1480            if (mPreferredRefreshRate == 0 && w.mAttrs.preferredRefreshRate != 0) {
1481                mPreferredRefreshRate = w.mAttrs.preferredRefreshRate;
1482            }
1483            if (mPreferredModeId == 0 && w.mAttrs.preferredDisplayModeId != 0) {
1484                mPreferredModeId = w.mAttrs.preferredDisplayModeId;
1485            }
1486            if ((privateflags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) {
1487                mSustainedPerformanceModeCurrent = true;
1488            }
1489        }
1490    }
1491
1492    boolean copyAnimToLayoutParams() {
1493        boolean doRequest = false;
1494
1495        final int bulkUpdateParams = mService.mAnimator.mBulkUpdateParams;
1496        if ((bulkUpdateParams & SET_UPDATE_ROTATION) != 0) {
1497            mUpdateRotation = true;
1498            doRequest = true;
1499        }
1500        if ((bulkUpdateParams & SET_WALLPAPER_MAY_CHANGE) != 0) {
1501            mWallpaperMayChange = true;
1502            doRequest = true;
1503        }
1504        if ((bulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0) {
1505            mWallpaperForceHidingChanged = true;
1506            doRequest = true;
1507        }
1508        if ((bulkUpdateParams & SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
1509            mOrientationChangeComplete = false;
1510        } else {
1511            mOrientationChangeComplete = true;
1512            mLastWindowFreezeSource = mService.mAnimator.mLastWindowFreezeSource;
1513            if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
1514                doRequest = true;
1515            }
1516        }
1517        if ((bulkUpdateParams & SET_TURN_ON_SCREEN) != 0) {
1518            mService.mTurnOnScreen = true;
1519        }
1520        if ((bulkUpdateParams & SET_WALLPAPER_ACTION_PENDING) != 0) {
1521            mWallpaperActionPending = true;
1522        }
1523
1524        return doRequest;
1525    }
1526
1527    private static int toBrightnessOverride(float value) {
1528        return (int)(value * PowerManager.BRIGHTNESS_ON);
1529    }
1530
1531    void enableSurfaceTrace(ParcelFileDescriptor pfd) {
1532        final FileDescriptor fd = pfd.getFileDescriptor();
1533        if (mSurfaceTraceEnabled) {
1534            disableSurfaceTrace();
1535        }
1536        mSurfaceTraceEnabled = true;
1537        mRemoteEventTrace = new RemoteEventTrace(mService, fd);
1538        mSurfaceTraceFd = pfd;
1539        for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) {
1540            final DisplayContent dc = mChildren.get(displayNdx);
1541            dc.enableSurfaceTrace(fd);
1542        }
1543    }
1544
1545    void disableSurfaceTrace() {
1546        mSurfaceTraceEnabled = false;
1547        mRemoteEventTrace = null;
1548        mSurfaceTraceFd = null;
1549        for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) {
1550            final DisplayContent dc = mChildren.get(displayNdx);
1551            dc.disableSurfaceTrace();
1552        }
1553    }
1554
1555    void dumpDisplayContents(PrintWriter pw) {
1556        pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
1557        if (mService.mDisplayReady) {
1558            final int count = mChildren.size();
1559            for (int i = 0; i < count; ++i) {
1560                final DisplayContent displayContent = mChildren.get(i);
1561                displayContent.dump("  ", pw);
1562            }
1563        } else {
1564            pw.println("  NO DISPLAY");
1565        }
1566    }
1567
1568    void dumpLayoutNeededDisplayIds(PrintWriter pw) {
1569        if (!isLayoutNeeded()) {
1570            return;
1571        }
1572        pw.print("  mLayoutNeeded on displays=");
1573        final int count = mChildren.size();
1574        for (int displayNdx = 0; displayNdx < count; ++displayNdx) {
1575            final DisplayContent displayContent = mChildren.get(displayNdx);
1576            if (displayContent.isLayoutNeeded()) {
1577                pw.print(displayContent.getDisplayId());
1578            }
1579        }
1580        pw.println();
1581    }
1582
1583    void dumpWindowsNoHeader(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows) {
1584        final int numDisplays = mChildren.size();
1585        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
1586            final WindowList windowList = mChildren.get(displayNdx).getWindowList();
1587            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
1588                final WindowState w = windowList.get(winNdx);
1589                if (windows == null || windows.contains(w)) {
1590                    pw.println("  Window #" + winNdx + " " + w + ":");
1591                    w.dump(pw, "    ", dumpAll || windows != null);
1592                }
1593            }
1594        }
1595    }
1596
1597    void dumpTokens(PrintWriter pw, boolean dumpAll) {
1598        pw.println("  All tokens:");
1599        for (int i = mChildren.size() - 1; i >= 0; --i) {
1600            mChildren.get(i).dumpTokens(pw, dumpAll);
1601        }
1602    }
1603
1604    @Override
1605    String getName() {
1606        return "ROOT";
1607    }
1608}
1609