OSDN Git Service

[automerger skipped] Merge "DO NOT MERGE: Disable SpellChecker in secondary user...
[android-x86/frameworks-base.git] / services / core / java / com / android / server / wm / DisplayPolicy.java
1 /*
2  * Copyright (C) 2018 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 static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
21 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
22 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
23 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
24 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
25 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
26 import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
27 import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
28 import static android.view.Display.TYPE_BUILT_IN;
29 import static android.view.InsetsState.TYPE_TOP_BAR;
30 import static android.view.InsetsState.TYPE_TOP_GESTURES;
31 import static android.view.InsetsState.TYPE_TOP_TAPPABLE_ELEMENT;
32 import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
33 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
34 import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
35 import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
36 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
37 import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
38 import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
39 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
40 import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
41 import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
42 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR;
43 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
44 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN;
45 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
46 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
47 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
48 import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
49 import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
50 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
51 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
52 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
53 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
54 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
55 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
56 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR;
57 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
58 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
59 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
60 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
61 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
62 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
63 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
64 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
65 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
66 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
67 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
68 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
69 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
70 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
71 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
72 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
73 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
74 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
75 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
76 import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
77 import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
78 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
79 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
80 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
81 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
82 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
83 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
84 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
85 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
86 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING;
87 import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
88 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
89 import static android.view.WindowManagerGlobal.ADD_OKAY;
90 import static android.view.WindowManagerPolicyConstants.ACTION_HDMI_PLUGGED;
91 import static android.view.WindowManagerPolicyConstants.EXTRA_HDMI_PLUGGED_STATE;
92 import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
93 import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
94 import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;
95
96 import static com.android.server.policy.PhoneWindowManager.TOAST_WINDOW_TIMEOUT;
97 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
98 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_ENTER;
99 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_EXIT;
100 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_HIDE;
101 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
102 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_SHOW;
103 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
104 import static com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
105 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
106 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
107 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
108 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
109 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
110 import static com.android.server.wm.WindowManagerService.localLOGV;
111
112 import android.Manifest.permission;
113 import android.annotation.NonNull;
114 import android.annotation.Nullable;
115 import android.annotation.Px;
116 import android.app.ActivityManager;
117 import android.app.ActivityThread;
118 import android.app.LoadedApk;
119 import android.app.ResourcesManager;
120 import android.app.StatusBarManager;
121 import android.content.Context;
122 import android.content.Intent;
123 import android.content.pm.PackageManager;
124 import android.content.res.Resources;
125 import android.graphics.Insets;
126 import android.graphics.PixelFormat;
127 import android.graphics.Rect;
128 import android.graphics.Region;
129 import android.hardware.input.InputManager;
130 import android.hardware.power.V1_0.PowerHint;
131 import android.os.Handler;
132 import android.os.Looper;
133 import android.os.Message;
134 import android.os.SystemClock;
135 import android.os.SystemProperties;
136 import android.os.UserHandle;
137 import android.util.ArraySet;
138 import android.util.Pair;
139 import android.util.PrintWriterPrinter;
140 import android.util.Slog;
141 import android.view.DisplayCutout;
142 import android.view.Gravity;
143 import android.view.IApplicationToken;
144 import android.view.InputChannel;
145 import android.view.InputDevice;
146 import android.view.InputEvent;
147 import android.view.InputEventReceiver;
148 import android.view.InsetsState;
149 import android.view.MotionEvent;
150 import android.view.PointerIcon;
151 import android.view.Surface;
152 import android.view.View;
153 import android.view.ViewRootImpl;
154 import android.view.WindowManager;
155 import android.view.WindowManager.LayoutParams;
156 import android.view.WindowManagerGlobal;
157 import android.view.WindowManagerPolicyConstants;
158 import android.view.accessibility.AccessibilityManager;
159
160 import com.android.internal.R;
161 import com.android.internal.annotations.GuardedBy;
162 import com.android.internal.annotations.VisibleForTesting;
163 import com.android.internal.policy.ScreenDecorationsUtils;
164 import com.android.internal.util.ScreenShapeHelper;
165 import com.android.internal.util.ScreenshotHelper;
166 import com.android.internal.util.function.TriConsumer;
167 import com.android.internal.widget.PointerLocationView;
168 import com.android.server.LocalServices;
169 import com.android.server.UiThread;
170 import com.android.server.policy.WindowManagerPolicy;
171 import com.android.server.policy.WindowManagerPolicy.InputConsumer;
172 import com.android.server.policy.WindowManagerPolicy.NavigationBarPosition;
173 import com.android.server.policy.WindowManagerPolicy.ScreenOnListener;
174 import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs;
175 import com.android.server.policy.WindowOrientationListener;
176 import com.android.server.statusbar.StatusBarManagerInternal;
177 import com.android.server.wallpaper.WallpaperManagerInternal;
178 import com.android.server.wm.utils.InsetUtils;
179
180 import java.io.PrintWriter;
181
182 /**
183  * The policy that provides the basic behaviors and states of a display to show UI.
184  */
185 public class DisplayPolicy {
186     private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayPolicy" : TAG_WM;
187     private static final boolean DEBUG = false;
188
189     private static final boolean ALTERNATE_CAR_MODE_NAV_SIZE = false;
190
191     // The panic gesture may become active only after the keyguard is dismissed and the immersive
192     // app shows again. If that doesn't happen for 30s we drop the gesture.
193     private static final long PANIC_GESTURE_EXPIRATION = 30000;
194
195     // Controls navigation bar opacity depending on which workspace stacks are currently
196     // visible.
197     // Nav bar is always opaque when either the freeform stack or docked stack is visible.
198     private static final int NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED = 0;
199     // Nav bar is always translucent when the freeform stack is visible, otherwise always opaque.
200     private static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1;
201     // Nav bar is never forced opaque.
202     private static final int NAV_BAR_FORCE_TRANSPARENT = 2;
203
204     /**
205      * These are the system UI flags that, when changing, can cause the layout
206      * of the screen to change.
207      */
208     private static final int SYSTEM_UI_CHANGING_LAYOUT =
209             View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
210                     | View.SYSTEM_UI_FLAG_FULLSCREEN
211                     | View.STATUS_BAR_TRANSLUCENT
212                     | View.NAVIGATION_BAR_TRANSLUCENT
213                     | View.STATUS_BAR_TRANSPARENT
214                     | View.NAVIGATION_BAR_TRANSPARENT;
215
216     private final WindowManagerService mService;
217     private final Context mContext;
218     private final DisplayContent mDisplayContent;
219     private final Object mLock;
220     private final Handler mHandler;
221
222     private Resources mCurrentUserResources;
223
224     private final boolean mCarDockEnablesAccelerometer;
225     private final boolean mDeskDockEnablesAccelerometer;
226     private final AccessibilityManager mAccessibilityManager;
227     private final ImmersiveModeConfirmation mImmersiveModeConfirmation;
228     private final ScreenshotHelper mScreenshotHelper;
229
230     private final Object mServiceAcquireLock = new Object();
231     private StatusBarManagerInternal mStatusBarManagerInternal;
232
233     @Px
234     private int mBottomGestureAdditionalInset;
235     @Px
236     private int mSideGestureInset;
237
238     private StatusBarManagerInternal getStatusBarManagerInternal() {
239         synchronized (mServiceAcquireLock) {
240             if (mStatusBarManagerInternal == null) {
241                 mStatusBarManagerInternal =
242                         LocalServices.getService(StatusBarManagerInternal.class);
243             }
244             return mStatusBarManagerInternal;
245         }
246     }
247
248     private final SystemGesturesPointerEventListener mSystemGestures;
249
250     private volatile int mLidState = LID_ABSENT;
251     private volatile int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
252     private volatile boolean mHdmiPlugged;
253
254     private volatile boolean mHasStatusBar;
255     private volatile boolean mHasNavigationBar;
256     // Can the navigation bar ever move to the side?
257     private volatile boolean mNavigationBarCanMove;
258     private volatile boolean mNavigationBarLetsThroughTaps;
259     private volatile boolean mNavigationBarAlwaysShowOnSideGesture;
260     private volatile boolean mAllowSeamlessRotationDespiteNavBarMoving;
261
262     // Written by vr manager thread, only read in this class.
263     private volatile boolean mPersistentVrModeEnabled;
264
265     private volatile boolean mAwake;
266     private volatile boolean mScreenOnEarly;
267     private volatile boolean mScreenOnFully;
268     private volatile ScreenOnListener mScreenOnListener;
269
270     private volatile boolean mKeyguardDrawComplete;
271     private volatile boolean mWindowManagerDrawComplete;
272
273     private final ArraySet<WindowState> mScreenDecorWindows = new ArraySet<>();
274     private WindowState mStatusBar = null;
275     private final int[] mStatusBarHeightForRotation = new int[4];
276     private WindowState mNavigationBar = null;
277     @NavigationBarPosition
278     private int mNavigationBarPosition = NAV_BAR_BOTTOM;
279     private int[] mNavigationBarHeightForRotationDefault = new int[4];
280     private int[] mNavigationBarWidthForRotationDefault = new int[4];
281     private int[] mNavigationBarHeightForRotationInCarMode = new int[4];
282     private int[] mNavigationBarWidthForRotationInCarMode = new int[4];
283
284     /** See {@link #getNavigationBarFrameHeight} */
285     private int[] mNavigationBarFrameHeightForRotationDefault = new int[4];
286
287     /** Cached value of {@link ScreenShapeHelper#getWindowOutsetBottomPx} */
288     @Px private int mWindowOutsetBottom;
289
290     private final StatusBarController mStatusBarController;
291
292     private final BarController mNavigationBarController;
293
294     private final BarController.OnBarVisibilityChangedListener mNavBarVisibilityListener =
295             new BarController.OnBarVisibilityChangedListener() {
296                 @Override
297                 public void onBarVisibilityChanged(boolean visible) {
298                     if (mAccessibilityManager == null) {
299                         return;
300                     }
301                     mAccessibilityManager.notifyAccessibilityButtonVisibilityChanged(visible);
302                 }
303             };
304
305     @GuardedBy("mHandler")
306     private SleepToken mDreamingSleepToken;
307
308     @GuardedBy("mHandler")
309     private SleepToken mWindowSleepToken;
310
311     private final Runnable mAcquireSleepTokenRunnable;
312     private final Runnable mReleaseSleepTokenRunnable;
313
314     // The windows we were told about in focusChanged.
315     private WindowState mFocusedWindow;
316     private WindowState mLastFocusedWindow;
317
318     IApplicationToken mFocusedApp;
319
320     int mLastSystemUiFlags;
321     // Bits that we are in the process of clearing, so we want to prevent
322     // them from being set by applications until everything has been updated
323     // to have them clear.
324     private int mResettingSystemUiFlags = 0;
325     // Bits that we are currently always keeping cleared.
326     private int mForceClearedSystemUiFlags = 0;
327     private int mLastFullscreenStackSysUiFlags;
328     private int mLastDockedStackSysUiFlags;
329     private final Rect mNonDockedStackBounds = new Rect();
330     private final Rect mDockedStackBounds = new Rect();
331     private final Rect mLastNonDockedStackBounds = new Rect();
332     private final Rect mLastDockedStackBounds = new Rect();
333
334     // What we last reported to system UI about whether the compatibility
335     // menu needs to be displayed.
336     private boolean mLastFocusNeedsMenu = false;
337     // If nonzero, a panic gesture was performed at that time in uptime millis and is still pending.
338     private long mPendingPanicGestureUptime;
339
340     private static final Rect sTmpDisplayCutoutSafeExceptMaybeBarsRect = new Rect();
341     private static final Rect sTmpRect = new Rect();
342     private static final Rect sTmpDockedFrame = new Rect();
343     private static final Rect sTmpNavFrame = new Rect();
344     private static final Rect sTmpLastParentFrame = new Rect();
345
346     private WindowState mTopFullscreenOpaqueWindowState;
347     private WindowState mTopFullscreenOpaqueOrDimmingWindowState;
348     private WindowState mTopDockedOpaqueWindowState;
349     private WindowState mTopDockedOpaqueOrDimmingWindowState;
350     private boolean mTopIsFullscreen;
351     private boolean mForceStatusBar;
352     private boolean mForceStatusBarFromKeyguard;
353     private boolean mForceStatusBarTransparent;
354     private int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
355     private boolean mForcingShowNavBar;
356     private int mForcingShowNavBarLayer;
357     private boolean mForceShowSystemBars;
358
359     /**
360      * Force the display of system bars regardless of other settings.
361      */
362     private boolean mForceShowSystemBarsFromExternal;
363
364     private boolean mShowingDream;
365     private boolean mLastShowingDream;
366     private boolean mDreamingLockscreen;
367     private boolean mDreamingSleepTokenNeeded;
368     private boolean mWindowSleepTokenNeeded;
369     private boolean mLastWindowSleepTokenNeeded;
370     private boolean mAllowLockscreenWhenOn;
371
372     private InputConsumer mInputConsumer = null;
373
374     private PointerLocationView mPointerLocationView;
375
376     /**
377      * The area covered by system windows which belong to another display. Forwarded insets is set
378      * in case this is a virtual display, this is displayed on another display that has insets, and
379      * the bounds of this display is overlapping with the insets of the host display (e.g. IME is
380      * displayed on the host display, and it covers a part of this virtual display.)
381      * The forwarded insets is used to compute display frames of this virtual display, which will
382      * be then used to layout windows in the virtual display.
383      */
384     @NonNull private Insets mForwardedInsets = Insets.NONE;
385
386     private RefreshRatePolicy mRefreshRatePolicy;
387
388     // -------- PolicyHandler --------
389     private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 1;
390     private static final int MSG_REQUEST_TRANSIENT_BARS = 2;
391     private static final int MSG_DISPOSE_INPUT_CONSUMER = 3;
392     private static final int MSG_ENABLE_POINTER_LOCATION = 4;
393     private static final int MSG_DISABLE_POINTER_LOCATION = 5;
394
395     private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
396     private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
397
398     private class PolicyHandler extends Handler {
399
400         PolicyHandler(Looper looper) {
401             super(looper);
402         }
403
404         @Override
405         public void handleMessage(Message msg) {
406             switch (msg.what) {
407                 case MSG_UPDATE_DREAMING_SLEEP_TOKEN:
408                     updateDreamingSleepToken(msg.arg1 != 0);
409                     break;
410                 case MSG_REQUEST_TRANSIENT_BARS:
411                     WindowState targetBar = (msg.arg1 == MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS)
412                             ? mStatusBar : mNavigationBar;
413                     if (targetBar != null) {
414                         requestTransientBars(targetBar);
415                     }
416                     break;
417                 case MSG_DISPOSE_INPUT_CONSUMER:
418                     disposeInputConsumer((InputConsumer) msg.obj);
419                     break;
420                 case MSG_ENABLE_POINTER_LOCATION:
421                     enablePointerLocation();
422                     break;
423                 case MSG_DISABLE_POINTER_LOCATION:
424                     disablePointerLocation();
425                     break;
426             }
427         }
428     }
429
430     DisplayPolicy(WindowManagerService service, DisplayContent displayContent) {
431         mService = service;
432         mContext = displayContent.isDefaultDisplay ? service.mContext
433                 : service.mContext.createDisplayContext(displayContent.getDisplay());
434         mDisplayContent = displayContent;
435         mLock = service.getWindowManagerLock();
436
437         final int displayId = displayContent.getDisplayId();
438         mStatusBarController = new StatusBarController(displayId);
439         mNavigationBarController = new BarController("NavigationBar",
440                 displayId,
441                 View.NAVIGATION_BAR_TRANSIENT,
442                 View.NAVIGATION_BAR_UNHIDE,
443                 View.NAVIGATION_BAR_TRANSLUCENT,
444                 StatusBarManager.WINDOW_NAVIGATION_BAR,
445                 FLAG_TRANSLUCENT_NAVIGATION,
446                 View.NAVIGATION_BAR_TRANSPARENT);
447
448         final Resources r = mContext.getResources();
449         mCarDockEnablesAccelerometer = r.getBoolean(R.bool.config_carDockEnablesAccelerometer);
450         mDeskDockEnablesAccelerometer = r.getBoolean(R.bool.config_deskDockEnablesAccelerometer);
451         mForceShowSystemBarsFromExternal = r.getBoolean(R.bool.config_forceShowSystemBars);
452
453         mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(
454                 Context.ACCESSIBILITY_SERVICE);
455         if (!displayContent.isDefaultDisplay) {
456             mAwake = true;
457             mScreenOnEarly = true;
458             mScreenOnFully = true;
459         }
460
461         final Looper looper = UiThread.getHandler().getLooper();
462         mHandler = new PolicyHandler(looper);
463         mSystemGestures = new SystemGesturesPointerEventListener(mContext, mHandler,
464                 new SystemGesturesPointerEventListener.Callbacks() {
465                     @Override
466                     public void onSwipeFromTop() {
467                         if (mStatusBar != null) {
468                             requestTransientBars(mStatusBar);
469                         }
470                     }
471
472                     @Override
473                     public void onSwipeFromBottom() {
474                         if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_BOTTOM) {
475                             requestTransientBars(mNavigationBar);
476                         }
477                     }
478
479                     @Override
480                     public void onSwipeFromRight() {
481                         final Region excludedRegion;
482                         synchronized (mLock) {
483                             excludedRegion = mDisplayContent.calculateSystemGestureExclusion();
484                         }
485                         final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
486                                 || mNavigationBarPosition == NAV_BAR_RIGHT;
487                         if (mNavigationBar != null && sideAllowed
488                                 && !mSystemGestures.currentGestureStartedInRegion(excludedRegion)) {
489                             requestTransientBars(mNavigationBar);
490                         }
491                     }
492
493                     @Override
494                     public void onSwipeFromLeft() {
495                         final Region excludedRegion;
496                         synchronized (mLock) {
497                             excludedRegion = mDisplayContent.calculateSystemGestureExclusion();
498                         }
499                         final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
500                                 || mNavigationBarPosition == NAV_BAR_LEFT;
501                         if (mNavigationBar != null && sideAllowed
502                                 && !mSystemGestures.currentGestureStartedInRegion(excludedRegion)) {
503                             requestTransientBars(mNavigationBar);
504                         }
505                     }
506
507                     @Override
508                     public void onFling(int duration) {
509                         if (mService.mPowerManagerInternal != null) {
510                             mService.mPowerManagerInternal.powerHint(
511                                     PowerHint.INTERACTION, duration);
512                         }
513                     }
514
515                     @Override
516                     public void onDebug() {
517                         // no-op
518                     }
519
520                     private WindowOrientationListener getOrientationListener() {
521                         final DisplayRotation rotation = mDisplayContent.getDisplayRotation();
522                         return rotation != null ? rotation.getOrientationListener() : null;
523                     }
524
525                     @Override
526                     public void onDown() {
527                         final WindowOrientationListener listener = getOrientationListener();
528                         if (listener != null) {
529                             listener.onTouchStart();
530                         }
531                     }
532
533                     @Override
534                     public void onUpOrCancel() {
535                         final WindowOrientationListener listener = getOrientationListener();
536                         if (listener != null) {
537                             listener.onTouchEnd();
538                         }
539                     }
540
541                     @Override
542                     public void onMouseHoverAtTop() {
543                         mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
544                         Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
545                         msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
546                         mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
547                     }
548
549                     @Override
550                     public void onMouseHoverAtBottom() {
551                         mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
552                         Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
553                         msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
554                         mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
555                     }
556
557                     @Override
558                     public void onMouseLeaveFromEdge() {
559                         mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
560                     }
561                 });
562         displayContent.registerPointerEventListener(mSystemGestures);
563         displayContent.mAppTransition.registerListenerLocked(
564                 mStatusBarController.getAppTransitionListener());
565         mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext, looper,
566                 mService.mVrModeEnabled);
567         mAcquireSleepTokenRunnable = () -> {
568             if (mWindowSleepToken != null) {
569                 return;
570             }
571             mWindowSleepToken = service.mAtmInternal.acquireSleepToken(
572                     "WindowSleepTokenOnDisplay" + displayId, displayId);
573         };
574         mReleaseSleepTokenRunnable = () -> {
575             if (mWindowSleepToken == null) {
576                 return;
577             }
578             mWindowSleepToken.release();
579             mWindowSleepToken = null;
580         };
581
582         // TODO: Make it can take screenshot on external display
583         mScreenshotHelper = displayContent.isDefaultDisplay
584                 ? new ScreenshotHelper(mContext) : null;
585
586         if (mDisplayContent.isDefaultDisplay) {
587             mHasStatusBar = true;
588             mHasNavigationBar = mContext.getResources().getBoolean(R.bool.config_showNavigationBar);
589
590             // Allow a system property to override this. Used by the emulator.
591             // See also hasNavigationBar().
592             String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
593             if ("1".equals(navBarOverride)) {
594                 mHasNavigationBar = false;
595             } else if ("0".equals(navBarOverride)) {
596                 mHasNavigationBar = true;
597             }
598         } else {
599             mHasStatusBar = false;
600             mHasNavigationBar = mDisplayContent.supportsSystemDecorations();
601         }
602
603         mRefreshRatePolicy = new RefreshRatePolicy(mService,
604                 mDisplayContent.getDisplayInfo(),
605                 mService.mHighRefreshRateBlacklist);
606     }
607
608     void systemReady() {
609         mSystemGestures.systemReady();
610         if (mService.mPointerLocationEnabled) {
611             setPointerLocationEnabled(true);
612         }
613     }
614
615     private int getDisplayId() {
616         return mDisplayContent.getDisplayId();
617     }
618
619     public void setHdmiPlugged(boolean plugged) {
620         setHdmiPlugged(plugged, false /* force */);
621     }
622
623     public void setHdmiPlugged(boolean plugged, boolean force) {
624         if (force || mHdmiPlugged != plugged) {
625             mHdmiPlugged = plugged;
626             mService.updateRotation(true /* alwaysSendConfiguration */, true /* forceRelayout */);
627             final Intent intent = new Intent(ACTION_HDMI_PLUGGED);
628             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
629             intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
630             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
631         }
632     }
633
634     boolean isHdmiPlugged() {
635         return mHdmiPlugged;
636     }
637
638     boolean isCarDockEnablesAccelerometer() {
639         return mCarDockEnablesAccelerometer;
640     }
641
642     boolean isDeskDockEnablesAccelerometer() {
643         return mDeskDockEnablesAccelerometer;
644     }
645
646     public void setPersistentVrModeEnabled(boolean persistentVrModeEnabled) {
647         mPersistentVrModeEnabled = persistentVrModeEnabled;
648     }
649
650     public boolean isPersistentVrModeEnabled() {
651         return mPersistentVrModeEnabled;
652     }
653
654     public void setDockMode(int dockMode) {
655         mDockMode = dockMode;
656     }
657
658     public int getDockMode() {
659         return mDockMode;
660     }
661
662     /**
663      * @see WindowManagerService.setForceShowSystemBars
664      */
665     void setForceShowSystemBars(boolean forceShowSystemBars) {
666         mForceShowSystemBarsFromExternal = forceShowSystemBars;
667     }
668
669     public boolean hasNavigationBar() {
670         return mHasNavigationBar;
671     }
672
673     public boolean hasStatusBar() {
674         return mHasStatusBar;
675     }
676
677     public boolean navigationBarCanMove() {
678         return mNavigationBarCanMove;
679     }
680
681     public void setLidState(int lidState) {
682         mLidState = lidState;
683     }
684
685     public int getLidState() {
686         return mLidState;
687     }
688
689     public void setAwake(boolean awake) {
690         mAwake = awake;
691     }
692
693     public boolean isAwake() {
694         return mAwake;
695     }
696
697     public boolean isScreenOnEarly() {
698         return mScreenOnEarly;
699     }
700
701     public boolean isScreenOnFully() {
702         return mScreenOnFully;
703     }
704
705     public boolean isKeyguardDrawComplete() {
706         return mKeyguardDrawComplete;
707     }
708
709     public boolean isWindowManagerDrawComplete() {
710         return mWindowManagerDrawComplete;
711     }
712
713     public ScreenOnListener getScreenOnListener() {
714         return mScreenOnListener;
715     }
716
717     public void screenTurnedOn(ScreenOnListener screenOnListener) {
718         synchronized (mLock) {
719             mScreenOnEarly = true;
720             mScreenOnFully = false;
721             mKeyguardDrawComplete = false;
722             mWindowManagerDrawComplete = false;
723             mScreenOnListener = screenOnListener;
724         }
725     }
726
727     public void screenTurnedOff() {
728         synchronized (mLock) {
729             mScreenOnEarly = false;
730             mScreenOnFully = false;
731             mKeyguardDrawComplete = false;
732             mWindowManagerDrawComplete = false;
733             mScreenOnListener = null;
734         }
735     }
736
737     /** Return false if we are not awake yet or we have already informed of this event. */
738     public boolean finishKeyguardDrawn() {
739         synchronized (mLock) {
740             if (!mScreenOnEarly || mKeyguardDrawComplete) {
741                 return false;
742             }
743
744             mKeyguardDrawComplete = true;
745             mWindowManagerDrawComplete = false;
746         }
747         return true;
748     }
749
750     /** Return false if screen is not turned on or we did already handle this case earlier. */
751     public boolean finishWindowsDrawn() {
752         synchronized (mLock) {
753             if (!mScreenOnEarly || mWindowManagerDrawComplete) {
754                 return false;
755             }
756
757             mWindowManagerDrawComplete = true;
758         }
759         return true;
760     }
761
762     /** Return false if it is not ready to turn on. */
763     public boolean finishScreenTurningOn() {
764         synchronized (mLock) {
765             if (DEBUG_SCREEN_ON) Slog.d(TAG,
766                     "finishScreenTurningOn: mAwake=" + mAwake
767                             + ", mScreenOnEarly=" + mScreenOnEarly
768                             + ", mScreenOnFully=" + mScreenOnFully
769                             + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
770                             + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
771
772             if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
773                     || (mAwake && !mKeyguardDrawComplete)) {
774                 return false;
775             }
776
777             if (DEBUG_SCREEN_ON) Slog.i(TAG, "Finished screen turning on...");
778             mScreenOnListener = null;
779             mScreenOnFully = true;
780         }
781         return true;
782     }
783
784     private boolean hasStatusBarServicePermission(int pid, int uid) {
785         return mContext.checkPermission(permission.STATUS_BAR_SERVICE, pid, uid)
786                 == PackageManager.PERMISSION_GRANTED;
787     }
788
789     /**
790      * Sanitize the layout parameters coming from a client.  Allows the policy
791      * to do things like ensure that windows of a specific type can't take
792      * input focus.
793      *
794      * @param attrs The window layout parameters to be modified.  These values
795      * are modified in-place.
796      */
797     public void adjustWindowParamsLw(WindowState win, WindowManager.LayoutParams attrs,
798             int callingPid, int callingUid) {
799
800         final boolean isScreenDecor = (attrs.privateFlags & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0;
801         if (mScreenDecorWindows.contains(win)) {
802             if (!isScreenDecor) {
803                 // No longer has the flag set, so remove from the set.
804                 mScreenDecorWindows.remove(win);
805             }
806         } else if (isScreenDecor && hasStatusBarServicePermission(callingPid, callingUid)) {
807             mScreenDecorWindows.add(win);
808         }
809
810         switch (attrs.type) {
811             case TYPE_SYSTEM_OVERLAY:
812             case TYPE_SECURE_SYSTEM_OVERLAY:
813                 // These types of windows can't receive input events.
814                 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
815                         | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
816                 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
817                 break;
818             case TYPE_DREAM:
819             case TYPE_WALLPAPER:
820                 // Dreams and wallpapers don't have an app window token and can thus not be
821                 // letterboxed. Hence always let them extend under the cutout.
822                 attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
823                 break;
824             case TYPE_STATUS_BAR:
825
826                 // If the Keyguard is in a hidden state (occluded by another window), we force to
827                 // remove the wallpaper and keyguard flag so that any change in-flight after setting
828                 // the keyguard as occluded wouldn't set these flags again.
829                 // See {@link #processKeyguardSetHiddenResultLw}.
830                 if (mService.mPolicy.isKeyguardOccluded()) {
831                     attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
832                     attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
833                 }
834                 break;
835
836             case TYPE_SCREENSHOT:
837                 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
838                 break;
839
840             case TYPE_TOAST:
841                 // While apps should use the dedicated toast APIs to add such windows
842                 // it possible legacy apps to add the window directly. Therefore, we
843                 // make windows added directly by the app behave as a toast as much
844                 // as possible in terms of timeout and animation.
845                 if (attrs.hideTimeoutMilliseconds < 0
846                         || attrs.hideTimeoutMilliseconds > TOAST_WINDOW_TIMEOUT) {
847                     attrs.hideTimeoutMilliseconds = TOAST_WINDOW_TIMEOUT;
848                 }
849                 // Accessibility users may need longer timeout duration. This api compares
850                 // original timeout with user's preference and return longer one. It returns
851                 // original timeout if there's no preference.
852                 attrs.hideTimeoutMilliseconds = mAccessibilityManager.getRecommendedTimeoutMillis(
853                         (int) attrs.hideTimeoutMilliseconds,
854                         AccessibilityManager.FLAG_CONTENT_TEXT);
855                 attrs.windowAnimations = com.android.internal.R.style.Animation_Toast;
856                 // Toast can show with below conditions when the screen is locked.
857                 if (canToastShowWhenLocked(callingPid)) {
858                     attrs.flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
859                 }
860                 break;
861         }
862
863         if (attrs.type != TYPE_STATUS_BAR) {
864             // The status bar is the only window allowed to exhibit keyguard behavior.
865             attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
866         }
867     }
868
869     /**
870      * @return {@code true} if the calling activity initiate toast and is visible with
871      * {@link WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} flag.
872      */
873     boolean canToastShowWhenLocked(int callingPid) {
874         return mDisplayContent.forAllWindows(w -> {
875             return callingPid == w.mSession.mPid && w.isVisible() && w.canShowWhenLocked();
876         }, true /* traverseTopToBottom */);
877     }
878
879     /**
880      * Preflight adding a window to the system.
881      *
882      * Currently enforces that three window types are singletons per display:
883      * <ul>
884      * <li>{@link WindowManager.LayoutParams#TYPE_STATUS_BAR}</li>
885      * <li>{@link WindowManager.LayoutParams#TYPE_NAVIGATION_BAR}</li>
886      * </ul>
887      *
888      * @param win The window to be added
889      * @param attrs Information about the window to be added
890      *
891      * @return If ok, WindowManagerImpl.ADD_OKAY.  If too many singletons,
892      * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
893      */
894     public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
895
896         if ((attrs.privateFlags & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0) {
897             mContext.enforceCallingOrSelfPermission(
898                     android.Manifest.permission.STATUS_BAR_SERVICE,
899                     "DisplayPolicy");
900             mScreenDecorWindows.add(win);
901         }
902
903         switch (attrs.type) {
904             case TYPE_STATUS_BAR:
905                 mContext.enforceCallingOrSelfPermission(
906                         android.Manifest.permission.STATUS_BAR_SERVICE,
907                         "DisplayPolicy");
908                 if (mStatusBar != null) {
909                     if (mStatusBar.isAlive()) {
910                         return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
911                     }
912                 }
913                 mStatusBar = win;
914                 mStatusBarController.setWindow(win);
915                 if (mDisplayContent.isDefaultDisplay) {
916                     mService.mPolicy.setKeyguardCandidateLw(win);
917                 }
918                 final TriConsumer<DisplayFrames, WindowState, Rect> frameProvider =
919                         (displayFrames, windowState, rect) -> {
920                             rect.top = 0;
921                             rect.bottom = getStatusBarHeight(displayFrames);
922                         };
923                 mDisplayContent.setInsetProvider(TYPE_TOP_BAR, win, frameProvider);
924                 mDisplayContent.setInsetProvider(TYPE_TOP_GESTURES, win, frameProvider);
925                 mDisplayContent.setInsetProvider(TYPE_TOP_TAPPABLE_ELEMENT, win, frameProvider);
926                 break;
927             case TYPE_NAVIGATION_BAR:
928                 mContext.enforceCallingOrSelfPermission(
929                         android.Manifest.permission.STATUS_BAR_SERVICE,
930                         "DisplayPolicy");
931                 if (mNavigationBar != null) {
932                     if (mNavigationBar.isAlive()) {
933                         return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
934                     }
935                 }
936                 mNavigationBar = win;
937                 mNavigationBarController.setWindow(win);
938                 mNavigationBarController.setOnBarVisibilityChangedListener(
939                         mNavBarVisibilityListener, true);
940                 mDisplayContent.setInsetProvider(InsetsState.TYPE_NAVIGATION_BAR,
941                         win, null /* frameProvider */);
942                 mDisplayContent.setInsetProvider(InsetsState.TYPE_BOTTOM_GESTURES, win,
943                         (displayFrames, windowState, inOutFrame) -> {
944                             inOutFrame.top -= mBottomGestureAdditionalInset;
945                         });
946                 mDisplayContent.setInsetProvider(InsetsState.TYPE_LEFT_GESTURES, win,
947                         (displayFrames, windowState, inOutFrame) -> {
948                             inOutFrame.left = 0;
949                             inOutFrame.top = 0;
950                             inOutFrame.bottom = displayFrames.mDisplayHeight;
951                             inOutFrame.right = displayFrames.mUnrestricted.left + mSideGestureInset;
952                         });
953                 mDisplayContent.setInsetProvider(InsetsState.TYPE_RIGHT_GESTURES, win,
954                         (displayFrames, windowState, inOutFrame) -> {
955                             inOutFrame.left = displayFrames.mUnrestricted.right - mSideGestureInset;
956                             inOutFrame.top = 0;
957                             inOutFrame.bottom = displayFrames.mDisplayHeight;
958                             inOutFrame.right = displayFrames.mDisplayWidth;
959                         });
960                 mDisplayContent.setInsetProvider(InsetsState.TYPE_BOTTOM_TAPPABLE_ELEMENT, win,
961                         (displayFrames, windowState, inOutFrame) -> {
962                             if ((windowState.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0
963                                     || mNavigationBarLetsThroughTaps) {
964                                 inOutFrame.setEmpty();
965                             }
966                         });
967                 if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
968                 break;
969             case TYPE_NAVIGATION_BAR_PANEL:
970             case TYPE_STATUS_BAR_PANEL:
971             case TYPE_STATUS_BAR_SUB_PANEL:
972             case TYPE_VOICE_INTERACTION_STARTING:
973                 mContext.enforceCallingOrSelfPermission(
974                         android.Manifest.permission.STATUS_BAR_SERVICE,
975                         "DisplayPolicy");
976                 break;
977         }
978         return ADD_OKAY;
979     }
980
981     /**
982      * Called when a window is being removed from a window manager.  Must not
983      * throw an exception -- clean up as much as possible.
984      *
985      * @param win The window being removed.
986      */
987     public void removeWindowLw(WindowState win) {
988         if (mStatusBar == win) {
989             mStatusBar = null;
990             mStatusBarController.setWindow(null);
991             if (mDisplayContent.isDefaultDisplay) {
992                 mService.mPolicy.setKeyguardCandidateLw(null);
993             }
994             mDisplayContent.setInsetProvider(TYPE_TOP_BAR, null, null);
995         } else if (mNavigationBar == win) {
996             mNavigationBar = null;
997             mNavigationBarController.setWindow(null);
998             mDisplayContent.setInsetProvider(InsetsState.TYPE_NAVIGATION_BAR, null, null);
999         }
1000         if (mLastFocusedWindow == win) {
1001             mLastFocusedWindow = null;
1002         }
1003         mScreenDecorWindows.remove(win);
1004     }
1005
1006     private int getStatusBarHeight(DisplayFrames displayFrames) {
1007         return Math.max(mStatusBarHeightForRotation[displayFrames.mRotation],
1008                 displayFrames.mDisplayCutoutSafe.top);
1009     }
1010
1011     /**
1012      * Control the animation to run when a window's state changes.  Return a
1013      * non-0 number to force the animation to a specific resource ID, or 0
1014      * to use the default animation.
1015      *
1016      * @param win The window that is changing.
1017      * @param transit What is happening to the window:
1018      *                {@link com.android.server.policy.WindowManagerPolicy#TRANSIT_ENTER},
1019      *                {@link com.android.server.policy.WindowManagerPolicy#TRANSIT_EXIT},
1020      *                {@link com.android.server.policy.WindowManagerPolicy#TRANSIT_SHOW}, or
1021      *                {@link com.android.server.policy.WindowManagerPolicy#TRANSIT_HIDE}.
1022      *
1023      * @return Resource ID of the actual animation to use, or 0 for none.
1024      */
1025     public int selectAnimationLw(WindowState win, int transit) {
1026         if (DEBUG_ANIM) Slog.i(TAG, "selectAnimation in " + win
1027                 + ": transit=" + transit);
1028         if (win == mStatusBar) {
1029             final boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
1030             final boolean expanded = win.getAttrs().height == MATCH_PARENT
1031                     && win.getAttrs().width == MATCH_PARENT;
1032             if (isKeyguard || expanded) {
1033                 return -1;
1034             }
1035             if (transit == TRANSIT_EXIT
1036                     || transit == TRANSIT_HIDE) {
1037                 return R.anim.dock_top_exit;
1038             } else if (transit == TRANSIT_ENTER
1039                     || transit == TRANSIT_SHOW) {
1040                 return R.anim.dock_top_enter;
1041             }
1042         } else if (win == mNavigationBar) {
1043             if (win.getAttrs().windowAnimations != 0) {
1044                 return 0;
1045             }
1046             // This can be on either the bottom or the right or the left.
1047             if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
1048                 if (transit == TRANSIT_EXIT
1049                         || transit == TRANSIT_HIDE) {
1050                     if (mService.mPolicy.isKeyguardShowingAndNotOccluded()) {
1051                         return R.anim.dock_bottom_exit_keyguard;
1052                     } else {
1053                         return R.anim.dock_bottom_exit;
1054                     }
1055                 } else if (transit == TRANSIT_ENTER
1056                         || transit == TRANSIT_SHOW) {
1057                     return R.anim.dock_bottom_enter;
1058                 }
1059             } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
1060                 if (transit == TRANSIT_EXIT
1061                         || transit == TRANSIT_HIDE) {
1062                     return R.anim.dock_right_exit;
1063                 } else if (transit == TRANSIT_ENTER
1064                         || transit == TRANSIT_SHOW) {
1065                     return R.anim.dock_right_enter;
1066                 }
1067             } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
1068                 if (transit == TRANSIT_EXIT
1069                         || transit == TRANSIT_HIDE) {
1070                     return R.anim.dock_left_exit;
1071                 } else if (transit == TRANSIT_ENTER
1072                         || transit == TRANSIT_SHOW) {
1073                     return R.anim.dock_left_enter;
1074                 }
1075             }
1076         } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) {
1077             return selectDockedDividerAnimationLw(win, transit);
1078         }
1079
1080         if (transit == TRANSIT_PREVIEW_DONE) {
1081             if (win.hasAppShownWindows()) {
1082                 if (DEBUG_ANIM) Slog.i(TAG, "**** STARTING EXIT");
1083                 return R.anim.app_starting_exit;
1084             }
1085         } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
1086                 && transit == TRANSIT_ENTER) {
1087             // Special case: we are animating in a dream, while the keyguard
1088             // is shown.  We don't want an animation on the dream, because
1089             // we need it shown immediately with the keyguard animating away
1090             // to reveal it.
1091             return -1;
1092         }
1093
1094         return 0;
1095     }
1096
1097     private int selectDockedDividerAnimationLw(WindowState win, int transit) {
1098         int insets = mDisplayContent.getDockedDividerController().getContentInsets();
1099
1100         // If the divider is behind the navigation bar, don't animate.
1101         final Rect frame = win.getFrameLw();
1102         final boolean behindNavBar = mNavigationBar != null
1103                 && ((mNavigationBarPosition == NAV_BAR_BOTTOM
1104                 && frame.top + insets >= mNavigationBar.getFrameLw().top)
1105                 || (mNavigationBarPosition == NAV_BAR_RIGHT
1106                 && frame.left + insets >= mNavigationBar.getFrameLw().left)
1107                 || (mNavigationBarPosition == NAV_BAR_LEFT
1108                 && frame.right - insets <= mNavigationBar.getFrameLw().right));
1109         final boolean landscape = frame.height() > frame.width();
1110         final boolean offscreenLandscape = landscape && (frame.right - insets <= 0
1111                 || frame.left + insets >= win.getDisplayFrameLw().right);
1112         final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0
1113                 || frame.bottom + insets >= win.getDisplayFrameLw().bottom);
1114         final boolean offscreen = offscreenLandscape || offscreenPortrait;
1115         if (behindNavBar || offscreen) {
1116             return 0;
1117         }
1118         if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
1119             return R.anim.fade_in;
1120         } else if (transit == TRANSIT_EXIT) {
1121             return R.anim.fade_out;
1122         } else {
1123             return 0;
1124         }
1125     }
1126
1127     /**
1128      * Determine the animation to run for a rotation transition based on the
1129      * top fullscreen windows {@link WindowManager.LayoutParams#rotationAnimation}
1130      * and whether it is currently fullscreen and frontmost.
1131      *
1132      * @param anim The exiting animation resource id is stored in anim[0], the
1133      * entering animation resource id is stored in anim[1].
1134      */
1135     public void selectRotationAnimationLw(int anim[]) {
1136         // If the screen is off or non-interactive, force a jumpcut.
1137         final boolean forceJumpcut = !mScreenOnFully || !mService.mPolicy.okToAnimate();
1138         if (DEBUG_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
1139                 + mTopFullscreenOpaqueWindowState + " rotationAnimation="
1140                 + (mTopFullscreenOpaqueWindowState == null
1141                 ? "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation)
1142                 + " forceJumpcut=" + forceJumpcut);
1143         if (forceJumpcut) {
1144             anim[0] = R.anim.rotation_animation_jump_exit;
1145             anim[1] = R.anim.rotation_animation_enter;
1146             return;
1147         }
1148         if (mTopFullscreenOpaqueWindowState != null) {
1149             int animationHint = mTopFullscreenOpaqueWindowState.getRotationAnimationHint();
1150             if (animationHint < 0 && mTopIsFullscreen) {
1151                 animationHint = mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation;
1152             }
1153             switch (animationHint) {
1154                 case ROTATION_ANIMATION_CROSSFADE:
1155                 case ROTATION_ANIMATION_SEAMLESS: // Crossfade is fallback for seamless.
1156                     anim[0] = R.anim.rotation_animation_xfade_exit;
1157                     anim[1] = R.anim.rotation_animation_enter;
1158                     break;
1159                 case ROTATION_ANIMATION_JUMPCUT:
1160                     anim[0] = R.anim.rotation_animation_jump_exit;
1161                     anim[1] = R.anim.rotation_animation_enter;
1162                     break;
1163                 case ROTATION_ANIMATION_ROTATE:
1164                 default:
1165                     anim[0] = anim[1] = 0;
1166                     break;
1167             }
1168         } else {
1169             anim[0] = anim[1] = 0;
1170         }
1171     }
1172
1173     /**
1174      * Validate whether the current top fullscreen has specified the same
1175      * {@link WindowManager.LayoutParams#rotationAnimation} value as that
1176      * being passed in from the previous top fullscreen window.
1177      *
1178      * @param exitAnimId exiting resource id from the previous window.
1179      * @param enterAnimId entering resource id from the previous window.
1180      * @param forceDefault For rotation animations only, if true ignore the
1181      * animation values and just return false.
1182      * @return true if the previous values are still valid, false if they
1183      * should be replaced with the default.
1184      */
1185     public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId,
1186             boolean forceDefault) {
1187         switch (exitAnimId) {
1188             case R.anim.rotation_animation_xfade_exit:
1189             case R.anim.rotation_animation_jump_exit:
1190                 // These are the only cases that matter.
1191                 if (forceDefault) {
1192                     return false;
1193                 }
1194                 int anim[] = new int[2];
1195                 selectRotationAnimationLw(anim);
1196                 return (exitAnimId == anim[0] && enterAnimId == anim[1]);
1197             default:
1198                 return true;
1199         }
1200     }
1201
1202     /**
1203      * Called when a new system UI visibility is being reported, allowing
1204      * the policy to adjust what is actually reported.
1205      * @param visibility The raw visibility reported by the status bar.
1206      * @return The new desired visibility.
1207      */
1208     public int adjustSystemUiVisibilityLw(int visibility) {
1209         mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
1210         mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
1211
1212         // Reset any bits in mForceClearingStatusBarVisibility that
1213         // are now clear.
1214         mResettingSystemUiFlags &= visibility;
1215         // Clear any bits in the new visibility that are currently being
1216         // force cleared, before reporting it.
1217         return visibility & ~mResettingSystemUiFlags
1218                 & ~mForceClearedSystemUiFlags;
1219     }
1220
1221     /**
1222      * @return true if the system bars are forced to stay visible
1223      */
1224     public boolean areSystemBarsForcedShownLw(WindowState windowState) {
1225         return mForceShowSystemBars;
1226     }
1227
1228     // TODO: Should probably be moved into DisplayFrames.
1229     /**
1230      * Return the layout hints for a newly added window. These values are computed on the
1231      * most recent layout, so they are not guaranteed to be correct.
1232      *
1233      * @param attrs The LayoutParams of the window.
1234      * @param taskBounds The bounds of the task this window is on or {@code null} if no task is
1235      *                   associated with the window.
1236      * @param displayFrames display frames.
1237      * @param floatingStack Whether the window's stack is floating.
1238      * @param outFrame The frame of the window.
1239      * @param outContentInsets The areas covered by system windows, expressed as positive insets.
1240      * @param outStableInsets The areas covered by stable system windows irrespective of their
1241      *                        current visibility. Expressed as positive insets.
1242      * @param outOutsets The areas that are not real display, but we would like to treat as such.
1243      * @param outDisplayCutout The area that has been cut away from the display.
1244      * @return Whether to always consume the system bars.
1245      *         See {@link #areSystemBarsForcedShownLw(WindowState)}.
1246      */
1247     public boolean getLayoutHintLw(LayoutParams attrs, Rect taskBounds,
1248             DisplayFrames displayFrames, boolean floatingStack, Rect outFrame,
1249             Rect outContentInsets, Rect outStableInsets,
1250             Rect outOutsets, DisplayCutout.ParcelableWrapper outDisplayCutout) {
1251         final int fl = PolicyControl.getWindowFlags(null, attrs);
1252         final int pfl = attrs.privateFlags;
1253         final int requestedSysUiVis = PolicyControl.getSystemUiVisibility(null, attrs);
1254         final int sysUiVis = requestedSysUiVis | getImpliedSysUiFlagsForLayout(attrs);
1255         final int displayRotation = displayFrames.mRotation;
1256
1257         final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
1258         if (useOutsets) {
1259             int outset = mWindowOutsetBottom;
1260             if (outset > 0) {
1261                 if (displayRotation == Surface.ROTATION_0) {
1262                     outOutsets.bottom += outset;
1263                 } else if (displayRotation == Surface.ROTATION_90) {
1264                     outOutsets.right += outset;
1265                 } else if (displayRotation == Surface.ROTATION_180) {
1266                     outOutsets.top += outset;
1267                 } else if (displayRotation == Surface.ROTATION_270) {
1268                     outOutsets.left += outset;
1269                 }
1270             }
1271         }
1272
1273         final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) != 0;
1274         final boolean layoutInScreenAndInsetDecor = layoutInScreen
1275                 && (fl & FLAG_LAYOUT_INSET_DECOR) != 0;
1276         final boolean screenDecor = (pfl & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0;
1277
1278         if (layoutInScreenAndInsetDecor && !screenDecor) {
1279             if ((sysUiVis & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
1280                 outFrame.set(displayFrames.mUnrestricted);
1281             } else {
1282                 outFrame.set(displayFrames.mRestricted);
1283             }
1284
1285             final Rect sf;
1286             if (floatingStack) {
1287                 sf = null;
1288             } else {
1289                 sf = displayFrames.mStable;
1290             }
1291
1292             final Rect cf;
1293             if (floatingStack) {
1294                 cf = null;
1295             } else if ((sysUiVis & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
1296                 if ((fl & FLAG_FULLSCREEN) != 0) {
1297                     cf = displayFrames.mStableFullscreen;
1298                 } else {
1299                     cf = displayFrames.mStable;
1300                 }
1301             } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
1302                 cf = displayFrames.mOverscan;
1303             } else {
1304                 cf = displayFrames.mCurrent;
1305             }
1306
1307             if (taskBounds != null) {
1308                 outFrame.intersect(taskBounds);
1309             }
1310             InsetUtils.insetsBetweenFrames(outFrame, cf, outContentInsets);
1311             InsetUtils.insetsBetweenFrames(outFrame, sf, outStableInsets);
1312             outDisplayCutout.set(displayFrames.mDisplayCutout.calculateRelativeTo(outFrame)
1313                     .getDisplayCutout());
1314             return mForceShowSystemBars;
1315         } else {
1316             if (layoutInScreen) {
1317                 outFrame.set(displayFrames.mUnrestricted);
1318             } else {
1319                 outFrame.set(displayFrames.mStable);
1320             }
1321             if (taskBounds != null) {
1322                 outFrame.intersect(taskBounds);
1323             }
1324
1325             outContentInsets.setEmpty();
1326             outStableInsets.setEmpty();
1327             outDisplayCutout.set(DisplayCutout.NO_CUTOUT);
1328             return mForceShowSystemBars;
1329         }
1330     }
1331
1332     private static int getImpliedSysUiFlagsForLayout(LayoutParams attrs) {
1333         int impliedFlags = 0;
1334         final boolean forceWindowDrawsBarBackgrounds =
1335                 (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0
1336                 && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT;
1337         if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
1338                 || forceWindowDrawsBarBackgrounds) {
1339             impliedFlags |= SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
1340             impliedFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
1341         }
1342         return impliedFlags;
1343     }
1344
1345     private static boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
1346         return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
1347                 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
1348     }
1349
1350     private final Runnable mClearHideNavigationFlag = new Runnable() {
1351         @Override
1352         public void run() {
1353             synchronized (mLock) {
1354                 mForceClearedSystemUiFlags &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
1355                 mDisplayContent.reevaluateStatusBarVisibility();
1356             }
1357         }
1358     };
1359
1360     /**
1361      * Input handler used while nav bar is hidden.  Captures any touch on the screen,
1362      * to determine when the nav bar should be shown and prevent applications from
1363      * receiving those touches.
1364      */
1365     private final class HideNavInputEventReceiver extends InputEventReceiver {
1366         HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
1367             super(inputChannel, looper);
1368         }
1369
1370         @Override
1371         public void onInputEvent(InputEvent event) {
1372             try {
1373                 if (event instanceof MotionEvent
1374                         && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
1375                     final MotionEvent motionEvent = (MotionEvent) event;
1376                     if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
1377                         // When the user taps down, we re-show the nav bar.
1378                         boolean changed = false;
1379                         synchronized (mLock) {
1380                             if (mInputConsumer == null) {
1381                                 return;
1382                             }
1383                             // Any user activity always causes us to show the
1384                             // navigation controls, if they had been hidden.
1385                             // We also clear the low profile and only content
1386                             // flags so that tapping on the screen will atomically
1387                             // restore all currently hidden screen decorations.
1388                             int newVal = mResettingSystemUiFlags
1389                                     | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
1390                                     | View.SYSTEM_UI_FLAG_LOW_PROFILE
1391                                     | View.SYSTEM_UI_FLAG_FULLSCREEN;
1392                             if (mResettingSystemUiFlags != newVal) {
1393                                 mResettingSystemUiFlags = newVal;
1394                                 changed = true;
1395                             }
1396                             // We don't allow the system's nav bar to be hidden
1397                             // again for 1 second, to prevent applications from
1398                             // spamming us and keeping it from being shown.
1399                             newVal = mForceClearedSystemUiFlags
1400                                     | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
1401                             if (mForceClearedSystemUiFlags != newVal) {
1402                                 mForceClearedSystemUiFlags = newVal;
1403                                 changed = true;
1404                                 mHandler.postDelayed(mClearHideNavigationFlag, 1000);
1405                             }
1406                             if (changed) {
1407                                 mDisplayContent.reevaluateStatusBarVisibility();
1408                             }
1409                         }
1410                     }
1411                 }
1412             } finally {
1413                 finishInputEvent(event, false /* handled */);
1414             }
1415         }
1416     }
1417
1418     /**
1419      * Called when layout of the windows is about to start.
1420      *
1421      * @param displayFrames frames of the display we are doing layout on.
1422      * @param uiMode The current uiMode in configuration.
1423      */
1424     public void beginLayoutLw(DisplayFrames displayFrames, int uiMode) {
1425         displayFrames.onBeginLayout();
1426         mSystemGestures.screenWidth = displayFrames.mUnrestricted.width();
1427         mSystemGestures.screenHeight = displayFrames.mUnrestricted.height();
1428
1429         // For purposes of putting out fake window up to steal focus, we will
1430         // drive nav being hidden only by whether it is requested.
1431         final int sysui = mLastSystemUiFlags;
1432         boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
1433         boolean navTranslucent = (sysui
1434                 & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
1435         boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
1436         boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
1437         boolean navAllowedHidden = immersive || immersiveSticky;
1438         navTranslucent &= !immersiveSticky;  // transient trumps translucent
1439         boolean isKeyguardShowing = isStatusBarKeyguard()
1440                 && !mService.mPolicy.isKeyguardOccluded();
1441         boolean statusBarForcesShowingNavigation = !isKeyguardShowing && mStatusBar != null
1442                 && (mStatusBar.getAttrs().privateFlags
1443                 & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0;
1444
1445         // When the navigation bar isn't visible, we put up a fake input window to catch all
1446         // touch events. This way we can detect when the user presses anywhere to bring back the
1447         // nav bar and ensure the application doesn't see the event.
1448         if (navVisible || navAllowedHidden) {
1449             if (mInputConsumer != null) {
1450                 mHandler.sendMessage(
1451                         mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
1452                 mInputConsumer = null;
1453             }
1454         } else if (mInputConsumer == null && mStatusBar != null && canHideNavigationBar()) {
1455             mInputConsumer = mService.createInputConsumer(mHandler.getLooper(),
1456                     INPUT_CONSUMER_NAVIGATION,
1457                     HideNavInputEventReceiver::new,
1458                     displayFrames.mDisplayId);
1459             // As long as mInputConsumer is active, hover events are not dispatched to the app
1460             // and the pointer icon is likely to become stale. Hide it to avoid confusion.
1461             InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL);
1462         }
1463
1464         // For purposes of positioning and showing the nav bar, if we have decided that it can't
1465         // be hidden (because of the screen aspect ratio), then take that into account.
1466         navVisible |= !canHideNavigationBar();
1467
1468         boolean updateSysUiVisibility = layoutNavigationBar(displayFrames, uiMode, navVisible,
1469                 navTranslucent, navAllowedHidden, statusBarForcesShowingNavigation);
1470         if (DEBUG_LAYOUT) Slog.i(TAG, "mDock rect:" + displayFrames.mDock);
1471         updateSysUiVisibility |= layoutStatusBar(displayFrames, sysui, isKeyguardShowing);
1472         if (updateSysUiVisibility) {
1473             updateSystemUiVisibilityLw();
1474         }
1475         layoutScreenDecorWindows(displayFrames);
1476
1477         if (displayFrames.mDisplayCutoutSafe.top > displayFrames.mUnrestricted.top) {
1478             // Make sure that the zone we're avoiding for the cutout is at least as tall as the
1479             // status bar; otherwise fullscreen apps will end up cutting halfway into the status
1480             // bar.
1481             displayFrames.mDisplayCutoutSafe.top = Math.max(displayFrames.mDisplayCutoutSafe.top,
1482                     displayFrames.mStable.top);
1483         }
1484
1485         // In case this is a virtual display, and the host display has insets that overlap this
1486         // virtual display, apply the insets of the overlapped area onto the current and content
1487         // frame of this virtual display. This let us layout windows in the virtual display as
1488         // expected when the window needs to avoid overlap with the system windows.
1489         // TODO: Generalize the forwarded insets, so that we can handle system windows other than
1490         // IME.
1491         displayFrames.mCurrent.inset(mForwardedInsets);
1492         displayFrames.mContent.inset(mForwardedInsets);
1493     }
1494
1495     private void layoutScreenDecorWindows(DisplayFrames displayFrames) {
1496         if (mScreenDecorWindows.isEmpty()) {
1497             return;
1498         }
1499
1500         sTmpRect.setEmpty();
1501         final int displayId = displayFrames.mDisplayId;
1502         final Rect dockFrame = displayFrames.mDock;
1503         final int displayHeight = displayFrames.mDisplayHeight;
1504         final int displayWidth = displayFrames.mDisplayWidth;
1505
1506         for (int i = mScreenDecorWindows.size() - 1; i >= 0; --i) {
1507             final WindowState w = mScreenDecorWindows.valueAt(i);
1508             if (w.getDisplayId() != displayId || !w.isVisibleLw()) {
1509                 // Skip if not on the same display or not visible.
1510                 continue;
1511             }
1512
1513             w.getWindowFrames().setFrames(displayFrames.mUnrestricted /* parentFrame */,
1514                     displayFrames.mUnrestricted /* displayFrame */,
1515                     displayFrames.mUnrestricted /* overscanFrame */,
1516                     displayFrames.mUnrestricted /* contentFrame */,
1517                     displayFrames.mUnrestricted /* visibleFrame */, sTmpRect /* decorFrame */,
1518                     displayFrames.mUnrestricted /* stableFrame */,
1519                     displayFrames.mUnrestricted /* outsetFrame */);
1520             w.getWindowFrames().setDisplayCutout(displayFrames.mDisplayCutout);
1521             w.computeFrameLw();
1522             final Rect frame = w.getFrameLw();
1523
1524             if (frame.left <= 0 && frame.top <= 0) {
1525                 // Docked at left or top.
1526                 if (frame.bottom >= displayHeight) {
1527                     // Docked left.
1528                     dockFrame.left = Math.max(frame.right, dockFrame.left);
1529                 } else if (frame.right >= displayWidth) {
1530                     // Docked top.
1531                     dockFrame.top = Math.max(frame.bottom, dockFrame.top);
1532                 } else {
1533                     Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w
1534                             + " not docked on left or top of display. frame=" + frame
1535                             + " displayWidth=" + displayWidth + " displayHeight=" + displayHeight);
1536                 }
1537             } else if (frame.right >= displayWidth && frame.bottom >= displayHeight) {
1538                 // Docked at right or bottom.
1539                 if (frame.top <= 0) {
1540                     // Docked right.
1541                     dockFrame.right = Math.min(frame.left, dockFrame.right);
1542                 } else if (frame.left <= 0) {
1543                     // Docked bottom.
1544                     dockFrame.bottom = Math.min(frame.top, dockFrame.bottom);
1545                 } else {
1546                     Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w
1547                             + " not docked on right or bottom" + " of display. frame=" + frame
1548                             + " displayWidth=" + displayWidth + " displayHeight=" + displayHeight);
1549                 }
1550             } else {
1551                 // Screen decor windows are required to be docked on one of the sides of the screen.
1552                 Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w
1553                         + " not docked on one of the sides of the display. frame=" + frame
1554                         + " displayWidth=" + displayWidth + " displayHeight=" + displayHeight);
1555             }
1556         }
1557
1558         displayFrames.mRestricted.set(dockFrame);
1559         displayFrames.mCurrent.set(dockFrame);
1560         displayFrames.mVoiceContent.set(dockFrame);
1561         displayFrames.mSystem.set(dockFrame);
1562         displayFrames.mContent.set(dockFrame);
1563         displayFrames.mRestrictedOverscan.set(dockFrame);
1564     }
1565
1566     private boolean layoutStatusBar(DisplayFrames displayFrames, int sysui,
1567             boolean isKeyguardShowing) {
1568         // decide where the status bar goes ahead of time
1569         if (mStatusBar == null) {
1570             return false;
1571         }
1572         // apply any navigation bar insets
1573         sTmpRect.setEmpty();
1574         final WindowFrames windowFrames = mStatusBar.getWindowFrames();
1575         windowFrames.setFrames(displayFrames.mUnrestricted /* parentFrame */,
1576                 displayFrames.mUnrestricted /* displayFrame */,
1577                 displayFrames.mStable /* overscanFrame */, displayFrames.mStable /* contentFrame */,
1578                 displayFrames.mStable /* visibleFrame */, sTmpRect /* decorFrame */,
1579                 displayFrames.mStable /* stableFrame */, displayFrames.mStable /* outsetFrame */);
1580         windowFrames.setDisplayCutout(displayFrames.mDisplayCutout);
1581
1582         // Let the status bar determine its size.
1583         mStatusBar.computeFrameLw();
1584
1585         // For layout, the status bar is always at the top with our fixed height.
1586         displayFrames.mStable.top = displayFrames.mUnrestricted.top
1587                 + mStatusBarHeightForRotation[displayFrames.mRotation];
1588         // Make sure the status bar covers the entire cutout height
1589         displayFrames.mStable.top = Math.max(displayFrames.mStable.top,
1590                 displayFrames.mDisplayCutoutSafe.top);
1591
1592         // Tell the bar controller where the collapsed status bar content is
1593         sTmpRect.set(mStatusBar.getContentFrameLw());
1594         sTmpRect.intersect(displayFrames.mDisplayCutoutSafe);
1595         sTmpRect.top = mStatusBar.getContentFrameLw().top;  // Ignore top display cutout inset
1596         sTmpRect.bottom = displayFrames.mStable.top;  // Use collapsed status bar size
1597         mStatusBarController.setContentFrame(sTmpRect);
1598
1599         boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
1600         boolean statusBarTranslucent = (sysui
1601                 & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
1602
1603         // If the status bar is hidden, we don't want to cause windows behind it to scroll.
1604         if (mStatusBar.isVisibleLw() && !statusBarTransient) {
1605             // Status bar may go away, so the screen area it occupies is available to apps but just
1606             // covering them when the status bar is visible.
1607             final Rect dockFrame = displayFrames.mDock;
1608             dockFrame.top = displayFrames.mStable.top;
1609             displayFrames.mContent.set(dockFrame);
1610             displayFrames.mVoiceContent.set(dockFrame);
1611             displayFrames.mCurrent.set(dockFrame);
1612
1613             if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " + String.format(
1614                     "dock=%s content=%s cur=%s", dockFrame.toString(),
1615                     displayFrames.mContent.toString(), displayFrames.mCurrent.toString()));
1616
1617             if (!statusBarTranslucent && !mStatusBarController.wasRecentlyTranslucent()
1618                     && !mStatusBar.isAnimatingLw()) {
1619
1620                 // If the opaque status bar is currently requested to be visible, and not in the
1621                 // process of animating on or off, then we can tell the app that it is covered by
1622                 // it.
1623                 displayFrames.mSystem.top = displayFrames.mStable.top;
1624             }
1625         }
1626         return mStatusBarController.checkHiddenLw();
1627     }
1628
1629     private boolean layoutNavigationBar(DisplayFrames displayFrames, int uiMode, boolean navVisible,
1630             boolean navTranslucent, boolean navAllowedHidden,
1631             boolean statusBarForcesShowingNavigation) {
1632         if (mNavigationBar == null) {
1633             return false;
1634         }
1635
1636         final Rect navigationFrame = sTmpNavFrame;
1637         boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
1638         // Force the navigation bar to its appropriate place and size. We need to do this directly,
1639         // instead of relying on it to bubble up from the nav bar, because this needs to change
1640         // atomically with screen rotations.
1641         final int rotation = displayFrames.mRotation;
1642         final int displayHeight = displayFrames.mDisplayHeight;
1643         final int displayWidth = displayFrames.mDisplayWidth;
1644         final Rect dockFrame = displayFrames.mDock;
1645         mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight, rotation);
1646
1647         final Rect cutoutSafeUnrestricted = sTmpRect;
1648         cutoutSafeUnrestricted.set(displayFrames.mUnrestricted);
1649         cutoutSafeUnrestricted.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
1650
1651         if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
1652             // It's a system nav bar or a portrait screen; nav bar goes on bottom.
1653             final int top = cutoutSafeUnrestricted.bottom
1654                     - getNavigationBarHeight(rotation, uiMode);
1655             final int topNavBar = cutoutSafeUnrestricted.bottom
1656                     - getNavigationBarFrameHeight(rotation, uiMode);
1657             navigationFrame.set(0, topNavBar, displayWidth, displayFrames.mUnrestricted.bottom);
1658             displayFrames.mStable.bottom = displayFrames.mStableFullscreen.bottom = top;
1659             if (transientNavBarShowing) {
1660                 mNavigationBarController.setBarShowingLw(true);
1661             } else if (navVisible) {
1662                 mNavigationBarController.setBarShowingLw(true);
1663                 dockFrame.bottom = displayFrames.mRestricted.bottom =
1664                         displayFrames.mRestrictedOverscan.bottom = top;
1665             } else {
1666                 // We currently want to hide the navigation UI - unless we expanded the status bar.
1667                 mNavigationBarController.setBarShowingLw(statusBarForcesShowingNavigation);
1668             }
1669             if (navVisible && !navTranslucent && !navAllowedHidden
1670                     && !mNavigationBar.isAnimatingLw()
1671                     && !mNavigationBarController.wasRecentlyTranslucent()) {
1672                 // If the opaque nav bar is currently requested to be visible and not in the process
1673                 // of animating on or off, then we can tell the app that it is covered by it.
1674                 displayFrames.mSystem.bottom = top;
1675             }
1676         } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
1677             // Landscape screen; nav bar goes to the right.
1678             final int left = cutoutSafeUnrestricted.right
1679                     - getNavigationBarWidth(rotation, uiMode);
1680             navigationFrame.set(left, 0, displayFrames.mUnrestricted.right, displayHeight);
1681             displayFrames.mStable.right = displayFrames.mStableFullscreen.right = left;
1682             if (transientNavBarShowing) {
1683                 mNavigationBarController.setBarShowingLw(true);
1684             } else if (navVisible) {
1685                 mNavigationBarController.setBarShowingLw(true);
1686                 dockFrame.right = displayFrames.mRestricted.right =
1687                         displayFrames.mRestrictedOverscan.right = left;
1688             } else {
1689                 // We currently want to hide the navigation UI - unless we expanded the status bar.
1690                 mNavigationBarController.setBarShowingLw(statusBarForcesShowingNavigation);
1691             }
1692             if (navVisible && !navTranslucent && !navAllowedHidden
1693                     && !mNavigationBar.isAnimatingLw()
1694                     && !mNavigationBarController.wasRecentlyTranslucent()) {
1695                 // If the nav bar is currently requested to be visible, and not in the process of
1696                 // animating on or off, then we can tell the app that it is covered by it.
1697                 displayFrames.mSystem.right = left;
1698             }
1699         } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
1700             // Seascape screen; nav bar goes to the left.
1701             final int right = cutoutSafeUnrestricted.left
1702                     + getNavigationBarWidth(rotation, uiMode);
1703             navigationFrame.set(displayFrames.mUnrestricted.left, 0, right, displayHeight);
1704             displayFrames.mStable.left = displayFrames.mStableFullscreen.left = right;
1705             if (transientNavBarShowing) {
1706                 mNavigationBarController.setBarShowingLw(true);
1707             } else if (navVisible) {
1708                 mNavigationBarController.setBarShowingLw(true);
1709                 dockFrame.left = displayFrames.mRestricted.left =
1710                         displayFrames.mRestrictedOverscan.left = right;
1711             } else {
1712                 // We currently want to hide the navigation UI - unless we expanded the status bar.
1713                 mNavigationBarController.setBarShowingLw(statusBarForcesShowingNavigation);
1714             }
1715             if (navVisible && !navTranslucent && !navAllowedHidden
1716                     && !mNavigationBar.isAnimatingLw()
1717                     && !mNavigationBarController.wasRecentlyTranslucent()) {
1718                 // If the nav bar is currently requested to be visible, and not in the process of
1719                 // animating on or off, then we can tell the app that it is covered by it.
1720                 displayFrames.mSystem.left = right;
1721             }
1722         }
1723
1724         // Make sure the content and current rectangles are updated to account for the restrictions
1725         // from the navigation bar.
1726         displayFrames.mCurrent.set(dockFrame);
1727         displayFrames.mVoiceContent.set(dockFrame);
1728         displayFrames.mContent.set(dockFrame);
1729         // And compute the final frame.
1730         sTmpRect.setEmpty();
1731         mNavigationBar.getWindowFrames().setFrames(navigationFrame /* parentFrame */,
1732                 navigationFrame /* displayFrame */, navigationFrame /* overscanFrame */,
1733                 displayFrames.mDisplayCutoutSafe /* contentFrame */,
1734                 navigationFrame /* visibleFrame */, sTmpRect /* decorFrame */,
1735                 navigationFrame /* stableFrame */,
1736                 displayFrames.mDisplayCutoutSafe /* outsetFrame */);
1737         mNavigationBar.getWindowFrames().setDisplayCutout(displayFrames.mDisplayCutout);
1738         mNavigationBar.computeFrameLw();
1739         mNavigationBarController.setContentFrame(mNavigationBar.getContentFrameLw());
1740
1741         if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + navigationFrame);
1742         return mNavigationBarController.checkHiddenLw();
1743     }
1744
1745     private void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
1746             boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf,
1747             DisplayFrames displayFrames) {
1748         if (!win.isInputMethodTarget() && attached.isInputMethodTarget()) {
1749             // Here's a special case: if the child window is not the 'dock window'
1750             // or input method target, and the window it is attached to is below
1751             // the dock window, then the frames we computed for the window it is
1752             // attached to can not be used because the dock is effectively part
1753             // of the underlying window and the attached window is floating on top
1754             // of the whole thing. So, we ignore the attached window and explicitly
1755             // compute the frames that would be appropriate without the dock.
1756             vf.set(displayFrames.mDock);
1757             cf.set(displayFrames.mDock);
1758             of.set(displayFrames.mDock);
1759             df.set(displayFrames.mDock);
1760         } else {
1761
1762             // In case we forced the window to draw behind the navigation bar, restrict df/of to
1763             // DF.RestrictedOverscan to simulate old compat behavior.
1764             Rect parentDisplayFrame = attached.getDisplayFrameLw();
1765             Rect parentOverscan = attached.getOverscanFrameLw();
1766             final WindowManager.LayoutParams attachedAttrs = attached.mAttrs;
1767             if ((attachedAttrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0
1768                     && (attachedAttrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
1769                     && (attachedAttrs.systemUiVisibility
1770                             & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0) {
1771                 parentOverscan = new Rect(parentOverscan);
1772                 parentOverscan.intersect(displayFrames.mRestrictedOverscan);
1773                 parentDisplayFrame = new Rect(parentDisplayFrame);
1774                 parentDisplayFrame.intersect(displayFrames.mRestrictedOverscan);
1775             }
1776
1777             // The effective display frame of the attached window depends on whether it is taking
1778             // care of insetting its content. If not, we need to use the parent's content frame so
1779             // that the entire window is positioned within that content. Otherwise we can use the
1780             // overscan frame and let the attached window take care of positioning its content
1781             // appropriately.
1782             if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
1783                 // Set the content frame of the attached window to the parent's decor frame
1784                 // (same as content frame when IME isn't present) if specifically requested by
1785                 // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
1786                 // Otherwise, use the overscan frame.
1787                 cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
1788                         ? attached.getContentFrameLw() : parentOverscan);
1789             } else {
1790                 // If the window is resizing, then we want to base the content frame on our attached
1791                 // content frame to resize...however, things can be tricky if the attached window is
1792                 // NOT in resize mode, in which case its content frame will be larger.
1793                 // Ungh. So to deal with that, make sure the content frame we end up using is not
1794                 // covering the IM dock.
1795                 cf.set(attached.getContentFrameLw());
1796                 if (attached.isVoiceInteraction()) {
1797                     cf.intersectUnchecked(displayFrames.mVoiceContent);
1798                 } else if (win.isInputMethodTarget() || attached.isInputMethodTarget()) {
1799                     cf.intersectUnchecked(displayFrames.mContent);
1800                 }
1801             }
1802             df.set(insetDecors ? parentDisplayFrame : cf);
1803             of.set(insetDecors ? parentOverscan : cf);
1804             vf.set(attached.getVisibleFrameLw());
1805         }
1806         // The LAYOUT_IN_SCREEN flag is used to determine whether the attached window should be
1807         // positioned relative to its parent or the entire screen.
1808         pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 ? attached.getFrameLw() : df);
1809     }
1810
1811     private void applyStableConstraints(int sysui, int fl, Rect r, DisplayFrames displayFrames) {
1812         if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) == 0) {
1813             return;
1814         }
1815         // If app is requesting a stable layout, don't let the content insets go below the stable
1816         // values.
1817         if ((fl & FLAG_FULLSCREEN) != 0) {
1818             r.intersectUnchecked(displayFrames.mStableFullscreen);
1819         } else {
1820             r.intersectUnchecked(displayFrames.mStable);
1821         }
1822     }
1823
1824     private boolean canReceiveInput(WindowState win) {
1825         boolean notFocusable =
1826                 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
1827         boolean altFocusableIm =
1828                 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
1829         boolean notFocusableForIm = notFocusable ^ altFocusableIm;
1830         return !notFocusableForIm;
1831     }
1832
1833     /**
1834      * Called for each window attached to the window manager as layout is proceeding. The
1835      * implementation of this function must take care of setting the window's frame, either here or
1836      * in finishLayout().
1837      *
1838      * @param win The window being positioned.
1839      * @param attached For sub-windows, the window it is attached to; this
1840      *                 window will already have had layoutWindow() called on it
1841      *                 so you can use its Rect.  Otherwise null.
1842      * @param displayFrames The display frames.
1843      */
1844     public void layoutWindowLw(WindowState win, WindowState attached, DisplayFrames displayFrames) {
1845         // We've already done the navigation bar, status bar, and all screen decor windows. If the
1846         // status bar can receive input, we need to layout it again to accommodate for the IME
1847         // window.
1848         if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar
1849                 || mScreenDecorWindows.contains(win)) {
1850             return;
1851         }
1852         final WindowManager.LayoutParams attrs = win.getAttrs();
1853         final boolean isDefaultDisplay = win.isDefaultDisplay();
1854
1855         final int type = attrs.type;
1856         final int fl = PolicyControl.getWindowFlags(win, attrs);
1857         final int pfl = attrs.privateFlags;
1858         final int sim = attrs.softInputMode;
1859         final int requestedSysUiFl = PolicyControl.getSystemUiVisibility(null, attrs);
1860         final int sysUiFl = requestedSysUiFl | getImpliedSysUiFlagsForLayout(attrs);
1861
1862         final WindowFrames windowFrames = win.getWindowFrames();
1863
1864         windowFrames.setHasOutsets(false);
1865         sTmpLastParentFrame.set(windowFrames.mParentFrame);
1866         final Rect pf = windowFrames.mParentFrame;
1867         final Rect df = windowFrames.mDisplayFrame;
1868         final Rect of = windowFrames.mOverscanFrame;
1869         final Rect cf = windowFrames.mContentFrame;
1870         final Rect vf = windowFrames.mVisibleFrame;
1871         final Rect dcf = windowFrames.mDecorFrame;
1872         final Rect sf = windowFrames.mStableFrame;
1873         dcf.setEmpty();
1874         windowFrames.setParentFrameWasClippedByDisplayCutout(false);
1875         windowFrames.setDisplayCutout(displayFrames.mDisplayCutout);
1876
1877         final boolean hasNavBar = hasNavigationBar() && mNavigationBar != null
1878                 && mNavigationBar.isVisibleLw();
1879
1880         final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
1881
1882         final boolean requestedFullscreen = (fl & FLAG_FULLSCREEN) != 0
1883                 || (requestedSysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
1884
1885         final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) == FLAG_LAYOUT_IN_SCREEN;
1886         final boolean layoutInsetDecor = (fl & FLAG_LAYOUT_INSET_DECOR) == FLAG_LAYOUT_INSET_DECOR;
1887
1888         sf.set(displayFrames.mStable);
1889
1890         if (type == TYPE_INPUT_METHOD) {
1891             vf.set(displayFrames.mDock);
1892             cf.set(displayFrames.mDock);
1893             of.set(displayFrames.mDock);
1894             df.set(displayFrames.mDock);
1895             windowFrames.mParentFrame.set(displayFrames.mDock);
1896             // IM dock windows layout below the nav bar...
1897             pf.bottom = df.bottom = of.bottom = displayFrames.mUnrestricted.bottom;
1898             // ...with content insets above the nav bar
1899             cf.bottom = vf.bottom = displayFrames.mStable.bottom;
1900             if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
1901                 // The status bar forces the navigation bar while it's visible. Make sure the IME
1902                 // avoids the navigation bar in that case.
1903                 if (mNavigationBarPosition == NAV_BAR_RIGHT) {
1904                     pf.right = df.right = of.right = cf.right = vf.right =
1905                             displayFrames.mStable.right;
1906                 } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
1907                     pf.left = df.left = of.left = cf.left = vf.left = displayFrames.mStable.left;
1908                 }
1909             }
1910
1911             // In case the navigation bar is on the bottom, we use the frame height instead of the
1912             // regular height for the insets we send to the IME as we need some space to show
1913             // additional buttons in SystemUI when the IME is up.
1914             if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
1915                 final int rotation = displayFrames.mRotation;
1916                 final int uimode = mService.mPolicy.getUiMode();
1917                 final int navHeightOffset = getNavigationBarFrameHeight(rotation, uimode)
1918                         - getNavigationBarHeight(rotation, uimode);
1919                 if (navHeightOffset > 0) {
1920                     cf.bottom -= navHeightOffset;
1921                     sf.bottom -= navHeightOffset;
1922                     vf.bottom -= navHeightOffset;
1923                     dcf.bottom -= navHeightOffset;
1924                 }
1925             }
1926
1927             // IM dock windows always go to the bottom of the screen.
1928             attrs.gravity = Gravity.BOTTOM;
1929         } else if (type == TYPE_VOICE_INTERACTION) {
1930             of.set(displayFrames.mUnrestricted);
1931             df.set(displayFrames.mUnrestricted);
1932             pf.set(displayFrames.mUnrestricted);
1933             if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
1934                 cf.set(displayFrames.mDock);
1935             } else {
1936                 cf.set(displayFrames.mContent);
1937             }
1938             if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
1939                 vf.set(displayFrames.mCurrent);
1940             } else {
1941                 vf.set(cf);
1942             }
1943         } else if (type == TYPE_WALLPAPER) {
1944             layoutWallpaper(displayFrames, pf, df, of, cf);
1945         } else if (win == mStatusBar) {
1946             of.set(displayFrames.mUnrestricted);
1947             df.set(displayFrames.mUnrestricted);
1948             pf.set(displayFrames.mUnrestricted);
1949             cf.set(displayFrames.mStable);
1950             vf.set(displayFrames.mStable);
1951
1952             if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
1953                 cf.bottom = displayFrames.mContent.bottom;
1954             } else {
1955                 cf.bottom = displayFrames.mDock.bottom;
1956                 vf.bottom = displayFrames.mContent.bottom;
1957             }
1958         } else {
1959             dcf.set(displayFrames.mSystem);
1960             final boolean inheritTranslucentDecor =
1961                     (attrs.privateFlags & PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0;
1962             final boolean isAppWindow =
1963                     type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW;
1964             final boolean topAtRest =
1965                     win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
1966             if (isAppWindow && !inheritTranslucentDecor && !topAtRest) {
1967                 if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
1968                         && (fl & FLAG_FULLSCREEN) == 0
1969                         && (fl & FLAG_TRANSLUCENT_STATUS) == 0
1970                         && (fl & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
1971                         && (pfl & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) == 0) {
1972                     // Ensure policy decor includes status bar
1973                     dcf.top = displayFrames.mStable.top;
1974                 }
1975                 if ((fl & FLAG_TRANSLUCENT_NAVIGATION) == 0
1976                         && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
1977                         && (fl & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
1978                         && (pfl & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) == 0) {
1979                     // Ensure policy decor includes navigation bar
1980                     dcf.bottom = displayFrames.mStable.bottom;
1981                     dcf.right = displayFrames.mStable.right;
1982                 }
1983             }
1984
1985             if (layoutInScreen && layoutInsetDecor) {
1986                 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
1987                         + "): IN_SCREEN, INSET_DECOR");
1988                 // This is the case for a normal activity window: we want it to cover all of the
1989                 // screen space, and it can take care of moving its contents to account for screen
1990                 // decorations that intrude into that space.
1991                 if (attached != null) {
1992                     // If this window is attached to another, our display
1993                     // frame is the same as the one we are attached to.
1994                     setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf,
1995                             displayFrames);
1996                 } else {
1997                     if (type == TYPE_STATUS_BAR_PANEL || type == TYPE_STATUS_BAR_SUB_PANEL) {
1998                         // Status bar panels are the only windows who can go on top of the status
1999                         // bar. They are protected by the STATUS_BAR_SERVICE permission, so they
2000                         // have the same privileges as the status bar itself.
2001                         //
2002                         // However, they should still dodge the navigation bar if it exists.
2003
2004                         pf.left = df.left = of.left = hasNavBar
2005                                 ? displayFrames.mDock.left : displayFrames.mUnrestricted.left;
2006                         pf.top = df.top = of.top = displayFrames.mUnrestricted.top;
2007                         pf.right = df.right = of.right = hasNavBar
2008                                 ? displayFrames.mRestricted.right
2009                                 : displayFrames.mUnrestricted.right;
2010                         pf.bottom = df.bottom = of.bottom = hasNavBar
2011                                 ? displayFrames.mRestricted.bottom
2012                                 : displayFrames.mUnrestricted.bottom;
2013
2014                         if (DEBUG_LAYOUT) Slog.v(TAG, "Laying out status bar window: " + pf);
2015                     } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
2016                             && type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW) {
2017                         // Asking to layout into the overscan region, so give it that pure
2018                         // unrestricted area.
2019                         of.set(displayFrames.mOverscan);
2020                         df.set(displayFrames.mOverscan);
2021                         pf.set(displayFrames.mOverscan);
2022                     } else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
2023                             && (type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW
2024                             || type == TYPE_VOLUME_OVERLAY
2025                             || type == TYPE_KEYGUARD_DIALOG)) {
2026                         // Asking for layout as if the nav bar is hidden, lets the application
2027                         // extend into the unrestricted overscan screen area. We only do this for
2028                         // application windows and certain system windows to ensure no window that
2029                         // can be above the nav bar can do this.
2030                         df.set(displayFrames.mOverscan);
2031                         pf.set(displayFrames.mOverscan);
2032                         // We need to tell the app about where the frame inside the overscan is, so
2033                         // it can inset its content by that amount -- it didn't ask to actually
2034                         // extend itself into the overscan region.
2035                         of.set(displayFrames.mUnrestricted);
2036                     } else {
2037                         df.set(displayFrames.mRestrictedOverscan);
2038                         pf.set(displayFrames.mRestrictedOverscan);
2039                         // We need to tell the app about where the frame inside the overscan
2040                         // is, so it can inset its content by that amount -- it didn't ask
2041                         // to actually extend itself into the overscan region.
2042                         of.set(displayFrames.mUnrestricted);
2043                     }
2044
2045                     if ((fl & FLAG_FULLSCREEN) == 0) {
2046                         if (win.isVoiceInteraction()) {
2047                             cf.set(displayFrames.mVoiceContent);
2048                         } else {
2049                             // IME Insets are handled on the client for ADJUST_RESIZE in the new
2050                             // insets world
2051                             if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_NONE
2052                                     || adjust != SOFT_INPUT_ADJUST_RESIZE) {
2053                                 cf.set(displayFrames.mDock);
2054                             } else {
2055                                 cf.set(displayFrames.mContent);
2056                             }
2057                         }
2058                     } else {
2059                         // Full screen windows are always given a layout that is as if the status
2060                         // bar and other transient decors are gone. This is to avoid bad states when
2061                         // moving from a window that is not hiding the status bar to one that is.
2062                         cf.set(displayFrames.mRestricted);
2063                     }
2064                     applyStableConstraints(sysUiFl, fl, cf, displayFrames);
2065                     if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
2066                         vf.set(displayFrames.mCurrent);
2067                     } else {
2068                         vf.set(cf);
2069                     }
2070                 }
2071             } else if (layoutInScreen || (sysUiFl
2072                     & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
2073                     | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
2074                 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
2075                         + "): IN_SCREEN");
2076                 // A window that has requested to fill the entire screen just
2077                 // gets everything, period.
2078                 if (type == TYPE_STATUS_BAR_PANEL || type == TYPE_STATUS_BAR_SUB_PANEL) {
2079                     cf.set(displayFrames.mUnrestricted);
2080                     of.set(displayFrames.mUnrestricted);
2081                     df.set(displayFrames.mUnrestricted);
2082                     pf.set(displayFrames.mUnrestricted);
2083                     if (hasNavBar) {
2084                         pf.left = df.left = of.left = cf.left = displayFrames.mDock.left;
2085                         pf.right = df.right = of.right = cf.right = displayFrames.mRestricted.right;
2086                         pf.bottom = df.bottom = of.bottom = cf.bottom =
2087                                 displayFrames.mRestricted.bottom;
2088                     }
2089                     if (DEBUG_LAYOUT) Slog.v(TAG, "Laying out IN_SCREEN status bar window: " + pf);
2090                 } else if (type == TYPE_NAVIGATION_BAR || type == TYPE_NAVIGATION_BAR_PANEL) {
2091                     // The navigation bar has Real Ultimate Power.
2092                     of.set(displayFrames.mUnrestricted);
2093                     df.set(displayFrames.mUnrestricted);
2094                     pf.set(displayFrames.mUnrestricted);
2095                     if (DEBUG_LAYOUT) Slog.v(TAG, "Laying out navigation bar window: " + pf);
2096                 } else if ((type == TYPE_SECURE_SYSTEM_OVERLAY || type == TYPE_SCREENSHOT)
2097                         && ((fl & FLAG_FULLSCREEN) != 0)) {
2098                     // Fullscreen secure system overlays get what they ask for. Screenshot region
2099                     // selection overlay should also expand to full screen.
2100                     cf.set(displayFrames.mOverscan);
2101                     of.set(displayFrames.mOverscan);
2102                     df.set(displayFrames.mOverscan);
2103                     pf.set(displayFrames.mOverscan);
2104                 } else if (type == TYPE_BOOT_PROGRESS) {
2105                     // Boot progress screen always covers entire display.
2106                     cf.set(displayFrames.mOverscan);
2107                     of.set(displayFrames.mOverscan);
2108                     df.set(displayFrames.mOverscan);
2109                     pf.set(displayFrames.mOverscan);
2110                 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
2111                         && type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW) {
2112                     // Asking to layout into the overscan region, so give it that pure unrestricted
2113                     // area.
2114                     cf.set(displayFrames.mOverscan);
2115                     of.set(displayFrames.mOverscan);
2116                     df.set(displayFrames.mOverscan);
2117                     pf.set(displayFrames.mOverscan);
2118                 } else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
2119                         && (type == TYPE_STATUS_BAR
2120                         || type == TYPE_TOAST
2121                         || type == TYPE_DOCK_DIVIDER
2122                         || type == TYPE_VOICE_INTERACTION_STARTING
2123                         || (type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW))) {
2124                     // Asking for layout as if the nav bar is hidden, lets the
2125                     // application extend into the unrestricted screen area.  We
2126                     // only do this for application windows (or toasts) to ensure no window that
2127                     // can be above the nav bar can do this.
2128                     // XXX This assumes that an app asking for this will also
2129                     // ask for layout in only content.  We can't currently figure out
2130                     // what the screen would be if only laying out to hide the nav bar.
2131                     cf.set(displayFrames.mUnrestricted);
2132                     of.set(displayFrames.mUnrestricted);
2133                     df.set(displayFrames.mUnrestricted);
2134                     pf.set(displayFrames.mUnrestricted);
2135                 } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
2136                     of.set(displayFrames.mRestricted);
2137                     df.set(displayFrames.mRestricted);
2138                     pf.set(displayFrames.mRestricted);
2139
2140                     // IME Insets are handled on the client for ADJUST_RESIZE in the new insets
2141                     // world
2142                     if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_NONE
2143                             || adjust != SOFT_INPUT_ADJUST_RESIZE) {
2144                         cf.set(displayFrames.mDock);
2145                     } else {
2146                         cf.set(displayFrames.mContent);
2147                     }
2148                 } else {
2149                     cf.set(displayFrames.mRestricted);
2150                     of.set(displayFrames.mRestricted);
2151                     df.set(displayFrames.mRestricted);
2152                     pf.set(displayFrames.mRestricted);
2153                 }
2154
2155                 applyStableConstraints(sysUiFl, fl, cf, displayFrames);
2156
2157                 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
2158                     vf.set(displayFrames.mCurrent);
2159                 } else {
2160                     vf.set(cf);
2161                 }
2162             } else if (attached != null) {
2163                 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
2164                         + "): attached to " + attached);
2165                 // A child window should be placed inside of the same visible
2166                 // frame that its parent had.
2167                 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf,
2168                         displayFrames);
2169             } else {
2170                 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
2171                         + "): normal window");
2172                 // Otherwise, a normal window must be placed inside the content
2173                 // of all screen decorations.
2174                 if (type == TYPE_STATUS_BAR_PANEL) {
2175                     // Status bar panels can go on
2176                     // top of the status bar. They are protected by the STATUS_BAR_SERVICE
2177                     // permission, so they have the same privileges as the status bar itself.
2178                     cf.set(displayFrames.mRestricted);
2179                     of.set(displayFrames.mRestricted);
2180                     df.set(displayFrames.mRestricted);
2181                     pf.set(displayFrames.mRestricted);
2182                 } else if (type == TYPE_TOAST || type == TYPE_SYSTEM_ALERT) {
2183                     // These dialogs are stable to interim decor changes.
2184                     cf.set(displayFrames.mStable);
2185                     of.set(displayFrames.mStable);
2186                     df.set(displayFrames.mStable);
2187                     pf.set(displayFrames.mStable);
2188                 } else {
2189                     pf.set(displayFrames.mContent);
2190                     if (win.isVoiceInteraction()) {
2191                         cf.set(displayFrames.mVoiceContent);
2192                         of.set(displayFrames.mVoiceContent);
2193                         df.set(displayFrames.mVoiceContent);
2194                     } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
2195                         cf.set(displayFrames.mDock);
2196                         of.set(displayFrames.mDock);
2197                         df.set(displayFrames.mDock);
2198                     } else {
2199                         cf.set(displayFrames.mContent);
2200                         of.set(displayFrames.mContent);
2201                         df.set(displayFrames.mContent);
2202                     }
2203                     if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
2204                         vf.set(displayFrames.mCurrent);
2205                     } else {
2206                         vf.set(cf);
2207                     }
2208                 }
2209             }
2210         }
2211
2212         final int cutoutMode = attrs.layoutInDisplayCutoutMode;
2213         final boolean attachedInParent = attached != null && !layoutInScreen;
2214         final boolean requestedHideNavigation =
2215                 (requestedSysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
2216
2217         // TYPE_BASE_APPLICATION windows are never considered floating here because they don't get
2218         // cropped / shifted to the displayFrame in WindowState.
2219         final boolean floatingInScreenWindow = !attrs.isFullscreen() && layoutInScreen
2220                 && type != TYPE_BASE_APPLICATION;
2221
2222         // Ensure that windows with a DEFAULT or NEVER display cutout mode are laid out in
2223         // the cutout safe zone.
2224         if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES) {
2225             final Rect displayCutoutSafeExceptMaybeBars = sTmpDisplayCutoutSafeExceptMaybeBarsRect;
2226             displayCutoutSafeExceptMaybeBars.set(displayFrames.mDisplayCutoutSafe);
2227             if (layoutInScreen && layoutInsetDecor && !requestedFullscreen
2228                     && cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT) {
2229                 // At the top we have the status bar, so apps that are
2230                 // LAYOUT_IN_SCREEN | LAYOUT_INSET_DECOR but not FULLSCREEN
2231                 // already expect that there's an inset there and we don't need to exclude
2232                 // the window from that area.
2233                 displayCutoutSafeExceptMaybeBars.top = Integer.MIN_VALUE;
2234             }
2235             if (layoutInScreen && layoutInsetDecor && !requestedHideNavigation
2236                     && cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT) {
2237                 // Same for the navigation bar.
2238                 switch (mNavigationBarPosition) {
2239                     case NAV_BAR_BOTTOM:
2240                         displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
2241                         break;
2242                     case NAV_BAR_RIGHT:
2243                         displayCutoutSafeExceptMaybeBars.right = Integer.MAX_VALUE;
2244                         break;
2245                     case NAV_BAR_LEFT:
2246                         displayCutoutSafeExceptMaybeBars.left = Integer.MIN_VALUE;
2247                         break;
2248                 }
2249             }
2250             if (type == TYPE_INPUT_METHOD && mNavigationBarPosition == NAV_BAR_BOTTOM) {
2251                 // The IME can always extend under the bottom cutout if the navbar is there.
2252                 displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
2253             }
2254             // Windows that are attached to a parent and laid out in said parent already avoid
2255             // the cutout according to that parent and don't need to be further constrained.
2256             // Floating IN_SCREEN windows get what they ask for and lay out in the full screen.
2257             // They will later be cropped or shifted using the displayFrame in WindowState,
2258             // which prevents overlap with the DisplayCutout.
2259             if (!attachedInParent && !floatingInScreenWindow) {
2260                 sTmpRect.set(pf);
2261                 pf.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
2262                 windowFrames.setParentFrameWasClippedByDisplayCutout(!sTmpRect.equals(pf));
2263             }
2264             // Make sure that NO_LIMITS windows clipped to the display don't extend under the
2265             // cutout.
2266             df.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
2267         }
2268
2269         // Content should never appear in the cutout.
2270         cf.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
2271
2272         // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
2273         // Also, we don't allow windows in multi-window mode to extend out of the screen.
2274         if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && type != TYPE_SYSTEM_ERROR
2275                 && !win.inMultiWindowMode()) {
2276             df.left = df.top = -10000;
2277             df.right = df.bottom = 10000;
2278             if (type != TYPE_WALLPAPER) {
2279                 of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
2280                 of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
2281             }
2282         }
2283
2284         // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we
2285         // need to provide information to the clients that want to pretend that you can draw there.
2286         // We only want to apply outsets to certain types of windows. For example, we never want to
2287         // apply the outsets to floating dialogs, because they wouldn't make sense there.
2288         final boolean useOutsets = shouldUseOutsets(attrs, fl);
2289         if (isDefaultDisplay && useOutsets) {
2290             final Rect osf = windowFrames.mOutsetFrame;
2291             osf.set(cf.left, cf.top, cf.right, cf.bottom);
2292             windowFrames.setHasOutsets(true);
2293             int outset = mWindowOutsetBottom;
2294             if (outset > 0) {
2295                 int rotation = displayFrames.mRotation;
2296                 if (rotation == Surface.ROTATION_0) {
2297                     osf.bottom += outset;
2298                 } else if (rotation == Surface.ROTATION_90) {
2299                     osf.right += outset;
2300                 } else if (rotation == Surface.ROTATION_180) {
2301                     osf.top -= outset;
2302                 } else if (rotation == Surface.ROTATION_270) {
2303                     osf.left -= outset;
2304                 }
2305                 if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset
2306                         + " with rotation " + rotation + ", result: " + osf);
2307             }
2308         }
2309
2310         if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
2311                 + ": sim=#" + Integer.toHexString(sim)
2312                 + " attach=" + attached + " type=" + type
2313                 + String.format(" flags=0x%08x", fl)
2314                 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
2315                 + " of=" + of.toShortString()
2316                 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
2317                 + " dcf=" + dcf.toShortString()
2318                 + " sf=" + sf.toShortString()
2319                 + " osf=" + windowFrames.mOutsetFrame.toShortString() + " " + win);
2320
2321         if (!sTmpLastParentFrame.equals(pf)) {
2322             windowFrames.setContentChanged(true);
2323         }
2324
2325         win.computeFrameLw();
2326         // Dock windows carve out the bottom of the screen, so normal windows
2327         // can't appear underneath them.
2328         if (type == TYPE_INPUT_METHOD && win.isVisibleLw()
2329                 && !win.getGivenInsetsPendingLw()) {
2330             offsetInputMethodWindowLw(win, displayFrames);
2331         }
2332         if (type == TYPE_VOICE_INTERACTION && win.isVisibleLw()
2333                 && !win.getGivenInsetsPendingLw()) {
2334             offsetVoiceInputWindowLw(win, displayFrames);
2335         }
2336     }
2337
2338     private void layoutWallpaper(DisplayFrames displayFrames, Rect pf, Rect df, Rect of, Rect cf) {
2339         // The wallpaper has Real Ultimate Power, but we want to tell it about the overscan area.
2340         df.set(displayFrames.mOverscan);
2341         pf.set(displayFrames.mOverscan);
2342         cf.set(displayFrames.mUnrestricted);
2343         of.set(displayFrames.mUnrestricted);
2344     }
2345
2346     private void offsetInputMethodWindowLw(WindowState win, DisplayFrames displayFrames) {
2347         int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
2348         top += win.getGivenContentInsetsLw().top;
2349         displayFrames.mContent.bottom = Math.min(displayFrames.mContent.bottom, top);
2350         displayFrames.mVoiceContent.bottom = Math.min(displayFrames.mVoiceContent.bottom, top);
2351         top = win.getVisibleFrameLw().top;
2352         top += win.getGivenVisibleInsetsLw().top;
2353         displayFrames.mCurrent.bottom = Math.min(displayFrames.mCurrent.bottom, top);
2354         if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
2355                 + displayFrames.mDock.bottom + " mContentBottom="
2356                 + displayFrames.mContent.bottom + " mCurBottom=" + displayFrames.mCurrent.bottom);
2357     }
2358
2359     private void offsetVoiceInputWindowLw(WindowState win, DisplayFrames displayFrames) {
2360         int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
2361         top += win.getGivenContentInsetsLw().top;
2362         displayFrames.mVoiceContent.bottom = Math.min(displayFrames.mVoiceContent.bottom, top);
2363     }
2364
2365     /**
2366      * Called following layout of all windows before each window has policy applied.
2367      */
2368     public void beginPostLayoutPolicyLw() {
2369         mTopFullscreenOpaqueWindowState = null;
2370         mTopFullscreenOpaqueOrDimmingWindowState = null;
2371         mTopDockedOpaqueWindowState = null;
2372         mTopDockedOpaqueOrDimmingWindowState = null;
2373         mForceStatusBar = false;
2374         mForceStatusBarFromKeyguard = false;
2375         mForceStatusBarTransparent = false;
2376         mForcingShowNavBar = false;
2377         mForcingShowNavBarLayer = -1;
2378
2379         mAllowLockscreenWhenOn = false;
2380         mShowingDream = false;
2381         mWindowSleepTokenNeeded = false;
2382     }
2383
2384     /**
2385      * Called following layout of all window to apply policy to each window.
2386      *
2387      * @param win The window being positioned.
2388      * @param attrs The LayoutParams of the window.
2389      * @param attached For sub-windows, the window it is attached to. Otherwise null.
2390      */
2391     public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
2392             WindowState attached, WindowState imeTarget) {
2393         final boolean affectsSystemUi = win.canAffectSystemUiFlags();
2394         if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": affectsSystemUi=" + affectsSystemUi);
2395         mService.mPolicy.applyKeyguardPolicyLw(win, imeTarget);
2396         final int fl = PolicyControl.getWindowFlags(win, attrs);
2397         if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi
2398                 && attrs.type == TYPE_INPUT_METHOD) {
2399             mForcingShowNavBar = true;
2400             mForcingShowNavBarLayer = win.getSurfaceLayer();
2401         }
2402         if (attrs.type == TYPE_STATUS_BAR) {
2403             if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
2404                 mForceStatusBarFromKeyguard = true;
2405             }
2406             if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
2407                 mForceStatusBarTransparent = true;
2408             }
2409         }
2410
2411         boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
2412                 && attrs.type < FIRST_SYSTEM_WINDOW;
2413         final int windowingMode = win.getWindowingMode();
2414         final boolean inFullScreenOrSplitScreenSecondaryWindowingMode =
2415                 windowingMode == WINDOWING_MODE_FULLSCREEN
2416                         || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
2417         if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi) {
2418             if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
2419                 mForceStatusBar = true;
2420             }
2421             if (attrs.type == TYPE_DREAM) {
2422                 // If the lockscreen was showing when the dream started then wait
2423                 // for the dream to draw before hiding the lockscreen.
2424                 if (!mDreamingLockscreen
2425                         || (win.isVisibleLw() && win.hasDrawnLw())) {
2426                     mShowingDream = true;
2427                     appWindow = true;
2428                 }
2429             }
2430
2431             // For app windows that are not attached, we decide if all windows in the app they
2432             // represent should be hidden or if we should hide the lockscreen. For attached app
2433             // windows we defer the decision to the window it is attached to.
2434             if (appWindow && attached == null) {
2435                 if (attrs.isFullscreen() && inFullScreenOrSplitScreenSecondaryWindowingMode) {
2436                     if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
2437                     mTopFullscreenOpaqueWindowState = win;
2438                     if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
2439                         mTopFullscreenOpaqueOrDimmingWindowState = win;
2440                     }
2441                     if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
2442                         mAllowLockscreenWhenOn = true;
2443                     }
2444                 }
2445             }
2446         }
2447
2448         // Voice interaction overrides both top fullscreen and top docked.
2449         if (affectsSystemUi && attrs.type == TYPE_VOICE_INTERACTION) {
2450             if (mTopFullscreenOpaqueWindowState == null) {
2451                 mTopFullscreenOpaqueWindowState = win;
2452                 if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
2453                     mTopFullscreenOpaqueOrDimmingWindowState = win;
2454                 }
2455             }
2456             if (mTopDockedOpaqueWindowState == null) {
2457                 mTopDockedOpaqueWindowState = win;
2458                 if (mTopDockedOpaqueOrDimmingWindowState == null) {
2459                     mTopDockedOpaqueOrDimmingWindowState = win;
2460                 }
2461             }
2462         }
2463
2464         // Keep track of the window if it's dimming but not necessarily fullscreen.
2465         if (mTopFullscreenOpaqueOrDimmingWindowState == null && affectsSystemUi
2466                 && win.isDimming() && inFullScreenOrSplitScreenSecondaryWindowingMode) {
2467             mTopFullscreenOpaqueOrDimmingWindowState = win;
2468         }
2469
2470         // We need to keep track of the top "fullscreen" opaque window for the docked stack
2471         // separately, because both the "real fullscreen" opaque window and the one for the docked
2472         // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
2473         if (mTopDockedOpaqueWindowState == null && affectsSystemUi && appWindow && attached == null
2474                 && attrs.isFullscreen() && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
2475             mTopDockedOpaqueWindowState = win;
2476             if (mTopDockedOpaqueOrDimmingWindowState == null) {
2477                 mTopDockedOpaqueOrDimmingWindowState = win;
2478             }
2479         }
2480
2481         // Also keep track of any windows that are dimming but not necessarily fullscreen in the
2482         // docked stack.
2483         if (mTopDockedOpaqueOrDimmingWindowState == null && affectsSystemUi && win.isDimming()
2484                 && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
2485             mTopDockedOpaqueOrDimmingWindowState = win;
2486         }
2487     }
2488
2489     /**
2490      * Called following layout of all windows and after policy has been applied
2491      * to each window. If in this function you do
2492      * something that may have modified the animation state of another window,
2493      * be sure to return non-zero in order to perform another pass through layout.
2494      *
2495      * @return Return any bit set of
2496      *         {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_LAYOUT},
2497      *         {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_CONFIG},
2498      *         {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_WALLPAPER}, or
2499      *         {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_ANIM}.
2500      */
2501     public int finishPostLayoutPolicyLw() {
2502         int changes = 0;
2503         boolean topIsFullscreen = false;
2504
2505         // If we are not currently showing a dream then remember the current
2506         // lockscreen state.  We will use this to determine whether the dream
2507         // started while the lockscreen was showing and remember this state
2508         // while the dream is showing.
2509         if (!mShowingDream) {
2510             mDreamingLockscreen = mService.mPolicy.isKeyguardShowingAndNotOccluded();
2511             if (mDreamingSleepTokenNeeded) {
2512                 mDreamingSleepTokenNeeded = false;
2513                 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
2514             }
2515         } else {
2516             if (!mDreamingSleepTokenNeeded) {
2517                 mDreamingSleepTokenNeeded = true;
2518                 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget();
2519             }
2520         }
2521
2522         if (mStatusBar != null) {
2523             if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
2524                     + " forcefkg=" + mForceStatusBarFromKeyguard
2525                     + " top=" + mTopFullscreenOpaqueWindowState);
2526             boolean shouldBeTransparent = mForceStatusBarTransparent
2527                     && !mForceStatusBar
2528                     && !mForceStatusBarFromKeyguard;
2529             if (!shouldBeTransparent) {
2530                 mStatusBarController.setShowTransparent(false /* transparent */);
2531             } else if (!mStatusBar.isVisibleLw()) {
2532                 mStatusBarController.setShowTransparent(true /* transparent */);
2533             }
2534
2535             boolean statusBarForcesShowingNavigation =
2536                     (mStatusBar.getAttrs().privateFlags
2537                             & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0;
2538             boolean topAppHidesStatusBar = topAppHidesStatusBar();
2539             if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
2540                     || statusBarForcesShowingNavigation) {
2541                 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
2542                 if (mStatusBarController.setBarShowingLw(true)) {
2543                     changes |= FINISH_LAYOUT_REDO_LAYOUT;
2544                 }
2545                 // Maintain fullscreen layout until incoming animation is complete.
2546                 topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
2547                 // Transient status bar is not allowed if status bar is on lockscreen or status bar
2548                 // is expecting the navigation keys from the user.
2549                 if ((mForceStatusBarFromKeyguard || statusBarForcesShowingNavigation)
2550                         && mStatusBarController.isTransientShowing()) {
2551                     mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
2552                             mLastSystemUiFlags, mLastSystemUiFlags);
2553                 }
2554             } else if (mTopFullscreenOpaqueWindowState != null) {
2555                 topIsFullscreen = topAppHidesStatusBar;
2556                 // The subtle difference between the window for mTopFullscreenOpaqueWindowState
2557                 // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
2558                 // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
2559                 // case though.
2560                 if (mStatusBarController.isTransientShowing()) {
2561                     if (mStatusBarController.setBarShowingLw(true)) {
2562                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
2563                     }
2564                 } else if (topIsFullscreen
2565                         && !mDisplayContent.isStackVisible(WINDOWING_MODE_FREEFORM)
2566                         && !mDisplayContent.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
2567                     if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
2568                     if (mStatusBarController.setBarShowingLw(false)) {
2569                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
2570                     } else {
2571                         if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
2572                     }
2573                 } else {
2574                     if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
2575                     if (mStatusBarController.setBarShowingLw(true)) {
2576                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
2577                     }
2578                     topAppHidesStatusBar = false;
2579                 }
2580             }
2581             mStatusBarController.setTopAppHidesStatusBar(topAppHidesStatusBar);
2582         }
2583
2584         if (mTopIsFullscreen != topIsFullscreen) {
2585             if (!topIsFullscreen) {
2586                 // Force another layout when status bar becomes fully shown.
2587                 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2588             }
2589             mTopIsFullscreen = topIsFullscreen;
2590         }
2591
2592         if ((updateSystemUiVisibilityLw() & SYSTEM_UI_CHANGING_LAYOUT) != 0) {
2593             // If the navigation bar has been hidden or shown, we need to do another
2594             // layout pass to update that window.
2595             changes |= FINISH_LAYOUT_REDO_LAYOUT;
2596         }
2597
2598         if (mShowingDream != mLastShowingDream) {
2599             mLastShowingDream = mShowingDream;
2600             mService.notifyShowingDreamChanged();
2601         }
2602
2603         updateWindowSleepToken();
2604
2605         mService.mPolicy.setAllowLockscreenWhenOn(getDisplayId(), mAllowLockscreenWhenOn);
2606         return changes;
2607     }
2608
2609     private void updateWindowSleepToken() {
2610         if (mWindowSleepTokenNeeded && !mLastWindowSleepTokenNeeded) {
2611             mHandler.removeCallbacks(mReleaseSleepTokenRunnable);
2612             mHandler.post(mAcquireSleepTokenRunnable);
2613         } else if (!mWindowSleepTokenNeeded && mLastWindowSleepTokenNeeded) {
2614             mHandler.removeCallbacks(mAcquireSleepTokenRunnable);
2615             mHandler.post(mReleaseSleepTokenRunnable);
2616         }
2617         mLastWindowSleepTokenNeeded = mWindowSleepTokenNeeded;
2618     }
2619
2620     /**
2621      * @return Whether the top app should hide the statusbar based on the top fullscreen opaque
2622      *         window.
2623      */
2624     private boolean topAppHidesStatusBar() {
2625         if (mTopFullscreenOpaqueWindowState == null) {
2626             return false;
2627         }
2628         final int fl = PolicyControl.getWindowFlags(null,
2629                 mTopFullscreenOpaqueWindowState.getAttrs());
2630         if (localLOGV) {
2631             Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw());
2632             Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
2633                     + " lp.flags=0x" + Integer.toHexString(fl));
2634         }
2635         return (fl & LayoutParams.FLAG_FULLSCREEN) != 0
2636                 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
2637     }
2638
2639     /**
2640      * Called when the user is switched.
2641      */
2642     public void switchUser() {
2643         updateCurrentUserResources();
2644     }
2645
2646     /**
2647      * Called when the resource overlays change.
2648      */
2649     public void onOverlayChangedLw() {
2650         updateCurrentUserResources();
2651         onConfigurationChanged();
2652         mSystemGestures.onConfigurationChanged();
2653     }
2654
2655     /**
2656      * Called when the configuration has changed, and it's safe to load new values from resources.
2657      */
2658     public void onConfigurationChanged() {
2659         final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation();
2660
2661         final Resources res = getCurrentUserResources();
2662         final int portraitRotation = displayRotation.getPortraitRotation();
2663         final int upsideDownRotation = displayRotation.getUpsideDownRotation();
2664         final int landscapeRotation = displayRotation.getLandscapeRotation();
2665         final int seascapeRotation = displayRotation.getSeascapeRotation();
2666         final int uiMode = mService.mPolicy.getUiMode();
2667
2668         if (hasStatusBar()) {
2669             mStatusBarHeightForRotation[portraitRotation] =
2670                     mStatusBarHeightForRotation[upsideDownRotation] =
2671                             res.getDimensionPixelSize(R.dimen.status_bar_height_portrait);
2672             mStatusBarHeightForRotation[landscapeRotation] =
2673                     mStatusBarHeightForRotation[seascapeRotation] =
2674                             res.getDimensionPixelSize(R.dimen.status_bar_height_landscape);
2675         } else {
2676             mStatusBarHeightForRotation[portraitRotation] =
2677                     mStatusBarHeightForRotation[upsideDownRotation] =
2678                             mStatusBarHeightForRotation[landscapeRotation] =
2679                                     mStatusBarHeightForRotation[seascapeRotation] = 0;
2680         }
2681
2682         // Height of the navigation bar when presented horizontally at bottom
2683         mNavigationBarHeightForRotationDefault[portraitRotation] =
2684         mNavigationBarHeightForRotationDefault[upsideDownRotation] =
2685                 res.getDimensionPixelSize(R.dimen.navigation_bar_height);
2686         mNavigationBarHeightForRotationDefault[landscapeRotation] =
2687         mNavigationBarHeightForRotationDefault[seascapeRotation] =
2688                 res.getDimensionPixelSize(R.dimen.navigation_bar_height_landscape);
2689
2690         // Height of the navigation bar frame when presented horizontally at bottom
2691         mNavigationBarFrameHeightForRotationDefault[portraitRotation] =
2692         mNavigationBarFrameHeightForRotationDefault[upsideDownRotation] =
2693                 res.getDimensionPixelSize(R.dimen.navigation_bar_frame_height);
2694         mNavigationBarFrameHeightForRotationDefault[landscapeRotation] =
2695         mNavigationBarFrameHeightForRotationDefault[seascapeRotation] =
2696                 res.getDimensionPixelSize(R.dimen.navigation_bar_frame_height_landscape);
2697
2698         // Width of the navigation bar when presented vertically along one side
2699         mNavigationBarWidthForRotationDefault[portraitRotation] =
2700         mNavigationBarWidthForRotationDefault[upsideDownRotation] =
2701         mNavigationBarWidthForRotationDefault[landscapeRotation] =
2702         mNavigationBarWidthForRotationDefault[seascapeRotation] =
2703                 res.getDimensionPixelSize(R.dimen.navigation_bar_width);
2704
2705         if (ALTERNATE_CAR_MODE_NAV_SIZE) {
2706             // Height of the navigation bar when presented horizontally at bottom
2707             mNavigationBarHeightForRotationInCarMode[portraitRotation] =
2708             mNavigationBarHeightForRotationInCarMode[upsideDownRotation] =
2709                     res.getDimensionPixelSize(R.dimen.navigation_bar_height_car_mode);
2710             mNavigationBarHeightForRotationInCarMode[landscapeRotation] =
2711             mNavigationBarHeightForRotationInCarMode[seascapeRotation] =
2712                     res.getDimensionPixelSize(R.dimen.navigation_bar_height_landscape_car_mode);
2713
2714             // Width of the navigation bar when presented vertically along one side
2715             mNavigationBarWidthForRotationInCarMode[portraitRotation] =
2716             mNavigationBarWidthForRotationInCarMode[upsideDownRotation] =
2717             mNavigationBarWidthForRotationInCarMode[landscapeRotation] =
2718             mNavigationBarWidthForRotationInCarMode[seascapeRotation] =
2719                     res.getDimensionPixelSize(R.dimen.navigation_bar_width_car_mode);
2720         }
2721
2722         mNavBarOpacityMode = res.getInteger(R.integer.config_navBarOpacityMode);
2723         mSideGestureInset = res.getDimensionPixelSize(R.dimen.config_backGestureInset);
2724         mNavigationBarLetsThroughTaps = res.getBoolean(R.bool.config_navBarTapThrough);
2725         mNavigationBarAlwaysShowOnSideGesture =
2726                 res.getBoolean(R.bool.config_navBarAlwaysShowOnSideEdgeGesture);
2727
2728         // This should calculate how much above the frame we accept gestures.
2729         mBottomGestureAdditionalInset =
2730                 res.getDimensionPixelSize(R.dimen.navigation_bar_gesture_height)
2731                         - getNavigationBarFrameHeight(portraitRotation, uiMode);
2732
2733         updateConfigurationAndScreenSizeDependentBehaviors();
2734         mWindowOutsetBottom = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
2735     }
2736
2737     void updateConfigurationAndScreenSizeDependentBehaviors() {
2738         final Resources res = getCurrentUserResources();
2739         mNavigationBarCanMove =
2740                 mDisplayContent.mBaseDisplayWidth != mDisplayContent.mBaseDisplayHeight
2741                         && res.getBoolean(R.bool.config_navBarCanMove);
2742         mAllowSeamlessRotationDespiteNavBarMoving =
2743                 res.getBoolean(R.bool.config_allowSeamlessRotationDespiteNavBarMoving);
2744     }
2745
2746     /**
2747      * Updates the current user's resources to pick up any changes for the current user (including
2748      * overlay paths)
2749      */
2750     private void updateCurrentUserResources() {
2751         final int userId = mService.mAmInternal.getCurrentUserId();
2752         final Context uiContext = getSystemUiContext();
2753
2754         if (userId == UserHandle.USER_SYSTEM) {
2755             // Skip the (expensive) recreation of resources for the system user below and just
2756             // use the resources from the system ui context
2757             mCurrentUserResources = uiContext.getResources();
2758             return;
2759         }
2760
2761         // For non-system users, ensure that the resources are loaded from the current
2762         // user's package info (see ContextImpl.createDisplayContext)
2763         final LoadedApk pi = ActivityThread.currentActivityThread().getPackageInfo(
2764                 uiContext.getPackageName(), null, 0, userId);
2765         mCurrentUserResources = ResourcesManager.getInstance().getResources(null,
2766                 pi.getResDir(),
2767                 null /* splitResDirs */,
2768                 pi.getOverlayDirs(),
2769                 pi.getApplicationInfo().sharedLibraryFiles,
2770                 mDisplayContent.getDisplayId(),
2771                 null /* overrideConfig */,
2772                 uiContext.getResources().getCompatibilityInfo(),
2773                 null /* classLoader */);
2774     }
2775
2776     @VisibleForTesting
2777     Resources getCurrentUserResources() {
2778         if (mCurrentUserResources == null) {
2779             updateCurrentUserResources();
2780         }
2781         return mCurrentUserResources;
2782     }
2783
2784     @VisibleForTesting
2785     Context getContext() {
2786         return mContext;
2787     }
2788
2789     private Context getSystemUiContext() {
2790         final Context uiContext = ActivityThread.currentActivityThread().getSystemUiContext();
2791         return mDisplayContent.isDefaultDisplay
2792                 ? uiContext : uiContext.createDisplayContext(mDisplayContent.getDisplay());
2793     }
2794
2795     private int getNavigationBarWidth(int rotation, int uiMode) {
2796         if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2797             return mNavigationBarWidthForRotationInCarMode[rotation];
2798         } else {
2799             return mNavigationBarWidthForRotationDefault[rotation];
2800         }
2801     }
2802
2803     void notifyDisplayReady() {
2804         mHandler.post(() -> {
2805             final int displayId = getDisplayId();
2806             getStatusBarManagerInternal().onDisplayReady(displayId);
2807             LocalServices.getService(WallpaperManagerInternal.class).onDisplayReady(displayId);
2808         });
2809     }
2810
2811     /**
2812      * Return the display width available after excluding any screen
2813      * decorations that could never be removed in Honeycomb. That is, system bar or
2814      * button bar.
2815      */
2816     public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
2817             DisplayCutout displayCutout) {
2818         int width = fullWidth;
2819         if (hasNavigationBar()) {
2820             final int navBarPosition = navigationBarPosition(fullWidth, fullHeight, rotation);
2821             if (navBarPosition == NAV_BAR_LEFT || navBarPosition == NAV_BAR_RIGHT) {
2822                 width -= getNavigationBarWidth(rotation, uiMode);
2823             }
2824         }
2825         if (displayCutout != null) {
2826             width -= displayCutout.getSafeInsetLeft() + displayCutout.getSafeInsetRight();
2827         }
2828         return width;
2829     }
2830
2831     private int getNavigationBarHeight(int rotation, int uiMode) {
2832         if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2833             return mNavigationBarHeightForRotationInCarMode[rotation];
2834         } else {
2835             return mNavigationBarHeightForRotationDefault[rotation];
2836         }
2837     }
2838
2839     /**
2840      * Get the Navigation Bar Frame height. This dimension is the height of the navigation bar that
2841      * is used for spacing to show additional buttons on the navigation bar (such as the ime
2842      * switcher when ime is visible) while {@link #getNavigationBarHeight} is used for the visible
2843      * height that we send to the app as content insets that can be smaller.
2844      * <p>
2845      * In car mode it will return the same height as {@link #getNavigationBarHeight}
2846      *
2847      * @param rotation specifies rotation to return dimension from
2848      * @param uiMode to determine if in car mode
2849      * @return navigation bar frame height
2850      */
2851     private int getNavigationBarFrameHeight(int rotation, int uiMode) {
2852         if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2853             return mNavigationBarHeightForRotationInCarMode[rotation];
2854         } else {
2855             return mNavigationBarFrameHeightForRotationDefault[rotation];
2856         }
2857     }
2858
2859     /**
2860      * Return the display height available after excluding any screen
2861      * decorations that could never be removed in Honeycomb. That is, system bar or
2862      * button bar.
2863      */
2864     public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
2865             DisplayCutout displayCutout) {
2866         int height = fullHeight;
2867         if (hasNavigationBar()) {
2868             final int navBarPosition = navigationBarPosition(fullWidth, fullHeight, rotation);
2869             if (navBarPosition == NAV_BAR_BOTTOM) {
2870                 height -= getNavigationBarHeight(rotation, uiMode);
2871             }
2872         }
2873         if (displayCutout != null) {
2874             height -= displayCutout.getSafeInsetTop() + displayCutout.getSafeInsetBottom();
2875         }
2876         return height;
2877     }
2878
2879     /**
2880      * Return the available screen width that we should report for the
2881      * configuration.  This must be no larger than
2882      * {@link #getNonDecorDisplayWidth(int, int, int, int, DisplayCutout)}; it may be smaller
2883      * than that to account for more transient decoration like a status bar.
2884      */
2885     public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
2886             DisplayCutout displayCutout) {
2887         return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode, displayCutout);
2888     }
2889
2890     /**
2891      * Return the available screen height that we should report for the
2892      * configuration.  This must be no larger than
2893      * {@link #getNonDecorDisplayHeight(int, int, int, int, DisplayCutout)}; it may be smaller
2894      * than that to account for more transient decoration like a status bar.
2895      */
2896     public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
2897             DisplayCutout displayCutout) {
2898         // There is a separate status bar at the top of the display.  We don't count that as part
2899         // of the fixed decor, since it can hide; however, for purposes of configurations,
2900         // we do want to exclude it since applications can't generally use that part
2901         // of the screen.
2902         int statusBarHeight = mStatusBarHeightForRotation[rotation];
2903         if (displayCutout != null) {
2904             // If there is a cutout, it may already have accounted for some part of the status
2905             // bar height.
2906             statusBarHeight = Math.max(0, statusBarHeight - displayCutout.getSafeInsetTop());
2907         }
2908         return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayCutout)
2909                 - statusBarHeight;
2910     }
2911
2912     /**
2913      * Return corner radius in pixels that should be used on windows in order to cover the display.
2914      * The radius is only valid for built-in displays since the one who configures window corner
2915      * radius cannot know the corner radius of non-built-in display.
2916      */
2917     float getWindowCornerRadius() {
2918         return mDisplayContent.getDisplay().getType() == TYPE_BUILT_IN
2919                 ? ScreenDecorationsUtils.getWindowCornerRadius(mContext.getResources()) : 0f;
2920     }
2921
2922     boolean isShowingDreamLw() {
2923         return mShowingDream;
2924     }
2925
2926     /**
2927      * Calculates the stable insets if we already have the non-decor insets.
2928      *
2929      * @param inOutInsets The known non-decor insets. It will be modified to stable insets.
2930      * @param rotation The current display rotation.
2931      */
2932     void convertNonDecorInsetsToStableInsets(Rect inOutInsets, int rotation) {
2933         inOutInsets.top = Math.max(inOutInsets.top, mStatusBarHeightForRotation[rotation]);
2934     }
2935
2936     /**
2937      * Calculates the stable insets without running a layout.
2938      *
2939      * @param displayRotation the current display rotation
2940      * @param displayWidth the current display width
2941      * @param displayHeight the current display height
2942      * @param displayCutout the current display cutout
2943      * @param outInsets the insets to return
2944      */
2945     public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
2946             DisplayCutout displayCutout, Rect outInsets) {
2947         outInsets.setEmpty();
2948
2949         // Navigation bar and status bar.
2950         getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, displayCutout, outInsets);
2951         convertNonDecorInsetsToStableInsets(outInsets, displayRotation);
2952     }
2953
2954     /**
2955      * Calculates the insets for the areas that could never be removed in Honeycomb, i.e. system
2956      * bar or button bar. See {@link #getNonDecorDisplayWidth}.
2957      *
2958      * @param displayRotation the current display rotation
2959      * @param displayWidth the current display width
2960      * @param displayHeight the current display height
2961      * @param displayCutout the current display cutout
2962      * @param outInsets the insets to return
2963      */
2964     public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
2965             DisplayCutout displayCutout, Rect outInsets) {
2966         outInsets.setEmpty();
2967
2968         // Only navigation bar
2969         if (hasNavigationBar()) {
2970             final int uiMode = mService.mPolicy.getUiMode();
2971             int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
2972             if (position == NAV_BAR_BOTTOM) {
2973                 outInsets.bottom = getNavigationBarHeight(displayRotation, uiMode);
2974             } else if (position == NAV_BAR_RIGHT) {
2975                 outInsets.right = getNavigationBarWidth(displayRotation, uiMode);
2976             } else if (position == NAV_BAR_LEFT) {
2977                 outInsets.left = getNavigationBarWidth(displayRotation, uiMode);
2978             }
2979         }
2980
2981         if (displayCutout != null) {
2982             outInsets.left += displayCutout.getSafeInsetLeft();
2983             outInsets.top += displayCutout.getSafeInsetTop();
2984             outInsets.right += displayCutout.getSafeInsetRight();
2985             outInsets.bottom += displayCutout.getSafeInsetBottom();
2986         }
2987     }
2988
2989     /**
2990      * @see IWindowManager#setForwardedInsets
2991      */
2992     public void setForwardedInsets(@NonNull Insets forwardedInsets) {
2993         mForwardedInsets = forwardedInsets;
2994     }
2995
2996     @NonNull
2997     public Insets getForwardedInsets() {
2998         return mForwardedInsets;
2999     }
3000
3001     @NavigationBarPosition
3002     int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
3003         if (navigationBarCanMove() && displayWidth > displayHeight) {
3004             if (displayRotation == Surface.ROTATION_270) {
3005                 return NAV_BAR_LEFT;
3006             } else if (displayRotation == Surface.ROTATION_90) {
3007                 return NAV_BAR_RIGHT;
3008             }
3009         }
3010         return NAV_BAR_BOTTOM;
3011     }
3012
3013     /**
3014      * @return The side of the screen where navigation bar is positioned.
3015      * @see WindowManagerPolicyConstants#NAV_BAR_LEFT
3016      * @see WindowManagerPolicyConstants#NAV_BAR_RIGHT
3017      * @see WindowManagerPolicyConstants#NAV_BAR_BOTTOM
3018      */
3019     @NavigationBarPosition
3020     public int getNavBarPosition() {
3021         return mNavigationBarPosition;
3022     }
3023
3024     /**
3025      * A new window has been focused.
3026      */
3027     public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
3028         mFocusedWindow = newFocus;
3029         mLastFocusedWindow = lastFocus;
3030         if (mDisplayContent.isDefaultDisplay) {
3031             mService.mPolicy.onDefaultDisplayFocusChangedLw(newFocus);
3032         }
3033         if ((updateSystemUiVisibilityLw() & SYSTEM_UI_CHANGING_LAYOUT) != 0) {
3034             // If the navigation bar has been hidden or shown, we need to do another
3035             // layout pass to update that window.
3036             return FINISH_LAYOUT_REDO_LAYOUT;
3037         }
3038         return 0;
3039     }
3040
3041     /**
3042      * Return true if it is okay to perform animations for an app transition
3043      * that is about to occur. You may return false for this if, for example,
3044      * the dream window is currently displayed so the switch should happen
3045      * immediately.
3046      */
3047     public boolean allowAppAnimationsLw() {
3048         return !mShowingDream;
3049     }
3050
3051     private void updateDreamingSleepToken(boolean acquire) {
3052         if (acquire) {
3053             final int displayId = getDisplayId();
3054             if (mDreamingSleepToken == null) {
3055                 mDreamingSleepToken = mService.mAtmInternal.acquireSleepToken(
3056                         "DreamOnDisplay" + displayId, displayId);
3057             }
3058         } else {
3059             if (mDreamingSleepToken != null) {
3060                 mDreamingSleepToken.release();
3061                 mDreamingSleepToken = null;
3062             }
3063         }
3064     }
3065
3066     private void requestTransientBars(WindowState swipeTarget) {
3067         synchronized (mLock) {
3068             if (!mService.mPolicy.isUserSetupComplete()) {
3069                 // Swipe-up for navigation bar is disabled during setup
3070                 return;
3071             }
3072             boolean sb = mStatusBarController.checkShowTransientBarLw();
3073             boolean nb = mNavigationBarController.checkShowTransientBarLw()
3074                     && !isNavBarEmpty(mLastSystemUiFlags);
3075             if (sb || nb) {
3076                 // Don't show status bar when swiping on already visible navigation bar
3077                 if (!nb && swipeTarget == mNavigationBar) {
3078                     if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
3079                     return;
3080                 }
3081                 if (sb) mStatusBarController.showTransient();
3082                 if (nb) mNavigationBarController.showTransient();
3083                 mImmersiveModeConfirmation.confirmCurrentPrompt();
3084                 updateSystemUiVisibilityLw();
3085             }
3086         }
3087     }
3088
3089     private void disposeInputConsumer(InputConsumer inputConsumer) {
3090         if (inputConsumer != null) {
3091             inputConsumer.dismiss();
3092         }
3093     }
3094
3095     private boolean isStatusBarKeyguard() {
3096         return mStatusBar != null
3097                 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
3098     }
3099
3100     private boolean isKeyguardOccluded() {
3101         // TODO (b/113840485): Handle per display keyguard.
3102         return mService.mPolicy.isKeyguardOccluded();
3103     }
3104
3105     void resetSystemUiVisibilityLw() {
3106         mLastSystemUiFlags = 0;
3107         updateSystemUiVisibilityLw();
3108     }
3109
3110     private int updateSystemUiVisibilityLw() {
3111         // If there is no window focused, there will be nobody to handle the events
3112         // anyway, so just hang on in whatever state we're in until things settle down.
3113         WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
3114                 : mTopFullscreenOpaqueWindowState;
3115         if (winCandidate == null) {
3116             return 0;
3117         }
3118
3119         // The immersive mode confirmation should never affect the system bar visibility, otherwise
3120         // it will unhide the navigation bar and hide itself.
3121         if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
3122
3123             // The immersive mode confirmation took the focus from mLastFocusedWindow which was
3124             // controlling the system ui visibility. So if mLastFocusedWindow can still receive
3125             // keys, we let it keep controlling the visibility.
3126             final boolean lastFocusCanReceiveKeys =
3127                     (mLastFocusedWindow != null && mLastFocusedWindow.canReceiveKeys());
3128             winCandidate = isStatusBarKeyguard() ? mStatusBar
3129                     : lastFocusCanReceiveKeys ? mLastFocusedWindow
3130                             : mTopFullscreenOpaqueWindowState;
3131             if (winCandidate == null) {
3132                 return 0;
3133             }
3134         }
3135         final WindowState win = winCandidate;
3136         if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && isKeyguardOccluded()) {
3137             // We are updating at a point where the keyguard has gotten
3138             // focus, but we were last in a state where the top window is
3139             // hiding it.  This is probably because the keyguard as been
3140             // shown while the top window was displayed, so we want to ignore
3141             // it here because this is just a very transient change and it
3142             // will quickly lose focus once it correctly gets hidden.
3143             return 0;
3144         }
3145
3146         mDisplayContent.getInsetsStateController().onBarControllingWindowChanged(
3147                 mTopFullscreenOpaqueWindowState);
3148
3149         int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
3150                 & ~mResettingSystemUiFlags
3151                 & ~mForceClearedSystemUiFlags;
3152         if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
3153             tmpVisibility
3154                     &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
3155         }
3156
3157         final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
3158                 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
3159         final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
3160                 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
3161         mService.getStackBounds(
3162                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, mNonDockedStackBounds);
3163         mService.getStackBounds(
3164                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, mDockedStackBounds);
3165         final Pair<Integer, Boolean> result =
3166                 updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
3167         final int visibility = result.first;
3168         final int diff = visibility ^ mLastSystemUiFlags;
3169         final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
3170         final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
3171         final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
3172         if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
3173                 && mFocusedApp == win.getAppToken()
3174                 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
3175                 && mLastDockedStackBounds.equals(mDockedStackBounds)) {
3176             return 0;
3177         }
3178         mLastSystemUiFlags = visibility;
3179         mLastFullscreenStackSysUiFlags = fullscreenVisibility;
3180         mLastDockedStackSysUiFlags = dockedVisibility;
3181         mLastFocusNeedsMenu = needsMenu;
3182         mFocusedApp = win.getAppToken();
3183         mLastNonDockedStackBounds.set(mNonDockedStackBounds);
3184         mLastDockedStackBounds.set(mDockedStackBounds);
3185         final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
3186         final Rect dockedStackBounds = new Rect(mDockedStackBounds);
3187         final boolean isNavbarColorManagedByIme = result.second;
3188         mHandler.post(() -> {
3189             StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
3190             if (statusBar != null) {
3191                 final int displayId = getDisplayId();
3192                 statusBar.setSystemUiVisibility(displayId, visibility, fullscreenVisibility,
3193                         dockedVisibility, 0xffffffff, fullscreenStackBounds,
3194                         dockedStackBounds, isNavbarColorManagedByIme, win.toString());
3195                 statusBar.topAppWindowChanged(displayId, needsMenu);
3196             }
3197         });
3198         return diff;
3199     }
3200
3201     private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
3202         final boolean onKeyguard = isStatusBarKeyguard() && !isKeyguardOccluded();
3203         final WindowState statusColorWin = onKeyguard ? mStatusBar : opaqueOrDimming;
3204         if (statusColorWin != null && (statusColorWin == opaque || onKeyguard)) {
3205             // If the top fullscreen-or-dimming window is also the top fullscreen, respect
3206             // its light flag.
3207             vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
3208             vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
3209                     & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
3210         } else if (statusColorWin != null && statusColorWin.isDimming()) {
3211             // Otherwise if it's dimming, clear the light flag.
3212             vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
3213         }
3214         return vis;
3215     }
3216
3217     @VisibleForTesting
3218     @Nullable
3219     static WindowState chooseNavigationColorWindowLw(WindowState opaque,
3220             WindowState opaqueOrDimming, WindowState imeWindow,
3221             @NavigationBarPosition int navBarPosition) {
3222         // If the IME window is visible and FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS is set, then IME
3223         // window can be navigation color window.
3224         final boolean imeWindowCanNavColorWindow = imeWindow != null
3225                 && imeWindow.isVisibleLw()
3226                 && navBarPosition == NAV_BAR_BOTTOM
3227                 && (PolicyControl.getWindowFlags(imeWindow, null)
3228                 & WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
3229
3230         if (opaque != null && opaqueOrDimming == opaque) {
3231             // If the top fullscreen-or-dimming window is also the top fullscreen, respect it
3232             // unless IME window is also eligible, since currently the IME window is always show
3233             // above the opaque fullscreen app window, regardless of the IME target window.
3234             // TODO(b/31559891): Maybe we need to revisit this condition once b/31559891 is fixed.
3235             return imeWindowCanNavColorWindow ? imeWindow : opaque;
3236         }
3237
3238         if (opaqueOrDimming == null || !opaqueOrDimming.isDimming()) {
3239             // No dimming window is involved. Determine the result only with the IME window.
3240             return imeWindowCanNavColorWindow ? imeWindow : null;
3241         }
3242
3243         if (!imeWindowCanNavColorWindow) {
3244             // No IME window is involved. Determine the result only with opaqueOrDimming.
3245             return opaqueOrDimming;
3246         }
3247
3248         // The IME window and the dimming window are competing.  Check if the dimming window can be
3249         // IME target or not.
3250         if (LayoutParams.mayUseInputMethod(PolicyControl.getWindowFlags(opaqueOrDimming, null))) {
3251             // The IME window is above the dimming window.
3252             return imeWindow;
3253         } else {
3254             // The dimming window is above the IME window.
3255             return opaqueOrDimming;
3256         }
3257     }
3258
3259     @VisibleForTesting
3260     static int updateLightNavigationBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming,
3261             WindowState imeWindow, WindowState navColorWin) {
3262
3263         if (navColorWin != null) {
3264             if (navColorWin == imeWindow || navColorWin == opaque) {
3265                 // Respect the light flag.
3266                 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
3267                 vis |= PolicyControl.getSystemUiVisibility(navColorWin, null)
3268                         & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
3269             } else if (navColorWin == opaqueOrDimming && navColorWin.isDimming()) {
3270                 // Clear the light flag for dimming window.
3271                 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
3272             }
3273         }
3274         return vis;
3275     }
3276
3277     private Pair<Integer, Boolean> updateSystemBarsLw(WindowState win, int oldVis, int vis) {
3278         final boolean dockedStackVisible =
3279                 mDisplayContent.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
3280         final boolean freeformStackVisible =
3281                 mDisplayContent.isStackVisible(WINDOWING_MODE_FREEFORM);
3282         final boolean resizing = mDisplayContent.getDockedDividerController().isResizing();
3283
3284         // We need to force system bars when the docked stack is visible, when the freeform stack
3285         // is visible but also when we are resizing for the transitions when docked stack
3286         // visibility changes.
3287         mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing
3288                 || mForceShowSystemBarsFromExternal;
3289         final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
3290
3291         // apply translucent bar vis flags
3292         WindowState fullscreenTransWin = isStatusBarKeyguard() && !isKeyguardOccluded()
3293                 ? mStatusBar
3294                 : mTopFullscreenOpaqueWindowState;
3295         vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
3296         vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
3297         int dockedVis = mStatusBarController.applyTranslucentFlagLw(
3298                 mTopDockedOpaqueWindowState, 0, 0);
3299         dockedVis = mNavigationBarController.applyTranslucentFlagLw(
3300                 mTopDockedOpaqueWindowState, dockedVis, 0);
3301
3302         final boolean fullscreenDrawsStatusBarBackground =
3303                 drawsStatusBarBackground(vis, mTopFullscreenOpaqueWindowState);
3304         final boolean dockedDrawsStatusBarBackground =
3305                 drawsStatusBarBackground(dockedVis, mTopDockedOpaqueWindowState);
3306         final boolean fullscreenDrawsNavBarBackground =
3307                 drawsNavigationBarBackground(vis, mTopFullscreenOpaqueWindowState);
3308         final boolean dockedDrawsNavigationBarBackground =
3309                 drawsNavigationBarBackground(dockedVis, mTopDockedOpaqueWindowState);
3310
3311         // prevent status bar interaction from clearing certain flags
3312         int type = win.getAttrs().type;
3313         boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
3314         if (statusBarHasFocus && !isStatusBarKeyguard()) {
3315             int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
3316                     | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
3317                     | View.SYSTEM_UI_FLAG_IMMERSIVE
3318                     | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
3319                     | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
3320             if (isKeyguardOccluded()) {
3321                 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
3322             }
3323             vis = (vis & ~flags) | (oldVis & flags);
3324         }
3325
3326         if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
3327             vis |= View.STATUS_BAR_TRANSPARENT;
3328             vis &= ~View.STATUS_BAR_TRANSLUCENT;
3329         } else if (forceOpaqueStatusBar) {
3330             vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
3331         }
3332
3333         vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing,
3334                 fullscreenDrawsNavBarBackground, dockedDrawsNavigationBarBackground);
3335
3336         // update status bar
3337         boolean immersiveSticky =
3338                 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
3339         final boolean hideStatusBarWM =
3340                 mTopFullscreenOpaqueWindowState != null
3341                         && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
3342                         & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
3343         final boolean hideStatusBarSysui =
3344                 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
3345         final boolean hideNavBarSysui =
3346                 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
3347
3348         final boolean transientStatusBarAllowed = mStatusBar != null
3349                 && (statusBarHasFocus || (!mForceShowSystemBars
3350                 && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
3351
3352         final boolean transientNavBarAllowed = mNavigationBar != null
3353                 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
3354
3355         final long now = SystemClock.uptimeMillis();
3356         final boolean pendingPanic = mPendingPanicGestureUptime != 0
3357                 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
3358         final DisplayPolicy defaultDisplayPolicy =
3359                 mService.getDefaultDisplayContentLocked().getDisplayPolicy();
3360         if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard()
3361                 // TODO (b/111955725): Show keyguard presentation on all external displays
3362                 && defaultDisplayPolicy.isKeyguardDrawComplete()) {
3363             // The user performed the panic gesture recently, we're about to hide the bars,
3364             // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
3365             mPendingPanicGestureUptime = 0;
3366             mStatusBarController.showTransient();
3367             if (!isNavBarEmpty(vis)) {
3368                 mNavigationBarController.showTransient();
3369             }
3370         }
3371
3372         final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
3373                 && !transientStatusBarAllowed && hideStatusBarSysui;
3374         final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
3375                 && !transientNavBarAllowed;
3376         if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
3377             // clear the clearable flags instead
3378             clearClearableFlagsLw();
3379             vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
3380         }
3381
3382         final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
3383         immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
3384         final boolean navAllowedHidden = immersive || immersiveSticky;
3385
3386         if (hideNavBarSysui && !navAllowedHidden
3387                 && mService.mPolicy.getWindowLayerLw(win)
3388                         > mService.mPolicy.getWindowLayerFromTypeLw(TYPE_INPUT_CONSUMER)) {
3389             // We can't hide the navbar from this window otherwise the input consumer would not get
3390             // the input events.
3391             vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
3392         }
3393
3394         vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
3395
3396         // update navigation bar
3397         boolean oldImmersiveMode = isImmersiveMode(oldVis);
3398         boolean newImmersiveMode = isImmersiveMode(vis);
3399         if (oldImmersiveMode != newImmersiveMode) {
3400             final String pkg = win.getOwningPackage();
3401             mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
3402                     mService.mPolicy.isUserSetupComplete(),
3403                     isNavBarEmpty(win.getSystemUiVisibility()));
3404         }
3405
3406         vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
3407
3408         final WindowState navColorWin = chooseNavigationColorWindowLw(
3409                 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState,
3410                 mDisplayContent.mInputMethodWindow, mNavigationBarPosition);
3411         vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState,
3412                 mTopFullscreenOpaqueOrDimmingWindowState,
3413                 mDisplayContent.mInputMethodWindow, navColorWin);
3414         // Navbar color is controlled by the IME.
3415         final boolean isManagedByIme =
3416                 navColorWin != null && navColorWin == mDisplayContent.mInputMethodWindow;
3417
3418         return Pair.create(vis, isManagedByIme);
3419     }
3420
3421     private boolean drawsBarBackground(int vis, WindowState win, BarController controller,
3422             int translucentFlag) {
3423         if (!controller.isTransparentAllowed(win)) {
3424             return false;
3425         }
3426         if (win == null) {
3427             return true;
3428         }
3429
3430         final boolean drawsSystemBars =
3431                 (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
3432         final boolean forceDrawsSystemBars =
3433                 (win.getAttrs().privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
3434
3435         return forceDrawsSystemBars || drawsSystemBars && (vis & translucentFlag) == 0;
3436     }
3437
3438     private boolean drawsStatusBarBackground(int vis, WindowState win) {
3439         return drawsBarBackground(vis, win, mStatusBarController, FLAG_TRANSLUCENT_STATUS);
3440     }
3441
3442     private boolean drawsNavigationBarBackground(int vis, WindowState win) {
3443         return drawsBarBackground(vis, win, mNavigationBarController, FLAG_TRANSLUCENT_NAVIGATION);
3444     }
3445
3446     /**
3447      * @return the current visibility flags with the nav-bar opacity related flags toggled based
3448      *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
3449      */
3450     private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
3451             boolean freeformStackVisible, boolean isDockedDividerResizing,
3452             boolean fullscreenDrawsBackground, boolean dockedDrawsNavigationBarBackground) {
3453         if (mNavBarOpacityMode == NAV_BAR_FORCE_TRANSPARENT) {
3454             if (fullscreenDrawsBackground && dockedDrawsNavigationBarBackground) {
3455                 visibility = setNavBarTransparentFlag(visibility);
3456             } else if (dockedStackVisible) {
3457                 visibility = setNavBarOpaqueFlag(visibility);
3458             }
3459         } else if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
3460             if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
3461                 visibility = setNavBarOpaqueFlag(visibility);
3462             } else if (fullscreenDrawsBackground) {
3463                 visibility = setNavBarTransparentFlag(visibility);
3464             }
3465         } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
3466             if (isDockedDividerResizing) {
3467                 visibility = setNavBarOpaqueFlag(visibility);
3468             } else if (freeformStackVisible) {
3469                 visibility = setNavBarTranslucentFlag(visibility);
3470             } else {
3471                 visibility = setNavBarOpaqueFlag(visibility);
3472             }
3473         }
3474
3475         return visibility;
3476     }
3477
3478     private int setNavBarOpaqueFlag(int visibility) {
3479         return visibility & ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
3480     }
3481
3482     private int setNavBarTranslucentFlag(int visibility) {
3483         visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
3484         return visibility | View.NAVIGATION_BAR_TRANSLUCENT;
3485     }
3486
3487     private int setNavBarTransparentFlag(int visibility) {
3488         visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
3489         return visibility | View.NAVIGATION_BAR_TRANSPARENT;
3490     }
3491
3492     private void clearClearableFlagsLw() {
3493         int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
3494         if (newVal != mResettingSystemUiFlags) {
3495             mResettingSystemUiFlags = newVal;
3496             mDisplayContent.reevaluateStatusBarVisibility();
3497         }
3498     }
3499
3500     private boolean isImmersiveMode(int vis) {
3501         final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
3502         return mNavigationBar != null
3503                 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
3504                 && (vis & flags) != 0
3505                 && canHideNavigationBar();
3506     }
3507
3508     /**
3509      * @return whether the navigation bar can be hidden, e.g. the device has a navigation bar
3510      */
3511     private boolean canHideNavigationBar() {
3512         return hasNavigationBar();
3513     }
3514
3515     private static boolean isNavBarEmpty(int systemUiFlags) {
3516         final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
3517                 | View.STATUS_BAR_DISABLE_BACK
3518                 | View.STATUS_BAR_DISABLE_RECENT);
3519
3520         return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
3521     }
3522
3523     boolean shouldRotateSeamlessly(DisplayRotation displayRotation, int oldRotation,
3524             int newRotation) {
3525         // For the upside down rotation we don't rotate seamlessly as the navigation
3526         // bar moves position.
3527         // Note most apps (using orientation:sensor or user as opposed to fullSensor)
3528         // will not enter the reverse portrait orientation, so actually the
3529         // orientation won't change at all.
3530         if (oldRotation == displayRotation.getUpsideDownRotation()
3531                 || newRotation == displayRotation.getUpsideDownRotation()) {
3532             return false;
3533         }
3534         // If the navigation bar can't change sides, then it will
3535         // jump when we change orientations and we don't rotate
3536         // seamlessly - unless that is allowed, eg. with gesture
3537         // navigation where the navbar is low-profile enough that this isn't very noticeable.
3538         if (!navigationBarCanMove() && !mAllowSeamlessRotationDespiteNavBarMoving) {
3539             return false;
3540         }
3541
3542         final WindowState w = mTopFullscreenOpaqueWindowState;
3543         if (w == null || w != mFocusedWindow) {
3544             return false;
3545         }
3546         // If the bounds of activity window is different from its parent, then reject to be seamless
3547         // because the window position may change after rotation that will look like a sudden jump.
3548         if (w.mAppToken != null && !w.mAppToken.matchParentBounds()) {
3549             return false;
3550         }
3551
3552         // We only enable seamless rotation if the top window has requested
3553         // it and is in the fullscreen opaque state. Seamless rotation
3554         // requires freezing various Surface states and won't work well
3555         // with animations, so we disable it in the animation case for now.
3556         if (!w.isAnimatingLw() && w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS) {
3557             return true;
3558         }
3559         return false;
3560     }
3561
3562     private final Runnable mHiddenNavPanic = new Runnable() {
3563         @Override
3564         public void run() {
3565             synchronized (mLock) {
3566                 if (!mService.mPolicy.isUserSetupComplete()) {
3567                     // Swipe-up for navigation bar is disabled during setup
3568                     return;
3569                 }
3570                 mPendingPanicGestureUptime = SystemClock.uptimeMillis();
3571                 if (!isNavBarEmpty(mLastSystemUiFlags)) {
3572                     mNavigationBarController.showTransient();
3573                 }
3574             }
3575         }
3576     };
3577
3578     void onPowerKeyDown(boolean isScreenOn) {
3579         // Detect user pressing the power button in panic when an application has
3580         // taken over the whole screen.
3581         boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(isScreenOn,
3582                 SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags),
3583                 isNavBarEmpty(mLastSystemUiFlags));
3584         if (panic) {
3585             mHandler.post(mHiddenNavPanic);
3586         }
3587     }
3588
3589     void onVrStateChangedLw(boolean enabled) {
3590         mImmersiveModeConfirmation.onVrStateChangedLw(enabled);
3591     }
3592
3593     /**
3594      * Called when the state of lock task mode changes. This should be used to disable immersive
3595      * mode confirmation.
3596      *
3597      * @param lockTaskState the new lock task mode state. One of
3598      *                      {@link ActivityManager#LOCK_TASK_MODE_NONE},
3599      *                      {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
3600      *                      {@link ActivityManager#LOCK_TASK_MODE_PINNED}.
3601      */
3602     public void onLockTaskStateChangedLw(int lockTaskState) {
3603         mImmersiveModeConfirmation.onLockTaskModeChangedLw(lockTaskState);
3604     }
3605
3606     /**
3607      * Request a screenshot be taken.
3608      *
3609      * @param screenshotType The type of screenshot, for example either
3610      *                       {@link WindowManager#TAKE_SCREENSHOT_FULLSCREEN} or
3611      *                       {@link WindowManager#TAKE_SCREENSHOT_SELECTED_REGION}
3612      */
3613     public void takeScreenshot(int screenshotType) {
3614         if (mScreenshotHelper != null) {
3615             mScreenshotHelper.takeScreenshot(screenshotType,
3616                     mStatusBar != null && mStatusBar.isVisibleLw(),
3617                     mNavigationBar != null && mNavigationBar.isVisibleLw(), mHandler);
3618         }
3619     }
3620
3621     RefreshRatePolicy getRefreshRatePolicy() {
3622         return mRefreshRatePolicy;
3623     }
3624
3625     void dump(String prefix, PrintWriter pw) {
3626         pw.print(prefix); pw.print("DisplayPolicy");
3627         prefix += "  ";
3628         pw.print(prefix);
3629         pw.print("mCarDockEnablesAccelerometer="); pw.print(mCarDockEnablesAccelerometer);
3630         pw.print(" mDeskDockEnablesAccelerometer=");
3631         pw.println(mDeskDockEnablesAccelerometer);
3632         pw.print(prefix); pw.print("mDockMode="); pw.print(Intent.dockStateToString(mDockMode));
3633         pw.print(" mLidState="); pw.println(WindowManagerFuncs.lidStateToString(mLidState));
3634         pw.print(prefix); pw.print("mAwake="); pw.print(mAwake);
3635         pw.print(" mScreenOnEarly="); pw.print(mScreenOnEarly);
3636         pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
3637         pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
3638         pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
3639         pw.print(prefix); pw.print("mHdmiPlugged="); pw.println(mHdmiPlugged);
3640         if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
3641                 || mForceClearedSystemUiFlags != 0) {
3642             pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
3643             pw.print(Integer.toHexString(mLastSystemUiFlags));
3644             pw.print(" mResettingSystemUiFlags=0x");
3645             pw.print(Integer.toHexString(mResettingSystemUiFlags));
3646             pw.print(" mForceClearedSystemUiFlags=0x");
3647             pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
3648         }
3649         if (mLastFocusNeedsMenu) {
3650             pw.print(prefix); pw.print("mLastFocusNeedsMenu="); pw.println(mLastFocusNeedsMenu);
3651         }
3652         pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
3653         pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
3654         pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
3655         if (mStatusBar != null) {
3656             pw.print(prefix); pw.print("mStatusBar="); pw.print(mStatusBar);
3657                     pw.print(" isStatusBarKeyguard="); pw.println(isStatusBarKeyguard());
3658         }
3659         if (mNavigationBar != null) {
3660             pw.print(prefix); pw.print("mNavigationBar="); pw.println(mNavigationBar);
3661             pw.print(prefix); pw.print("mNavBarOpacityMode="); pw.println(mNavBarOpacityMode);
3662             pw.print(prefix); pw.print("mNavigationBarCanMove="); pw.println(mNavigationBarCanMove);
3663             pw.print(prefix); pw.print("mNavigationBarPosition=");
3664             pw.println(mNavigationBarPosition);
3665         }
3666         if (mFocusedWindow != null) {
3667             pw.print(prefix); pw.print("mFocusedWindow="); pw.println(mFocusedWindow);
3668         }
3669         if (mFocusedApp != null) {
3670             pw.print(prefix); pw.print("mFocusedApp="); pw.println(mFocusedApp);
3671         }
3672         if (mTopFullscreenOpaqueWindowState != null) {
3673             pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
3674             pw.println(mTopFullscreenOpaqueWindowState);
3675         }
3676         if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
3677             pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
3678             pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
3679         }
3680         if (mForcingShowNavBar) {
3681             pw.print(prefix); pw.print("mForcingShowNavBar="); pw.println(mForcingShowNavBar);
3682             pw.print(prefix); pw.print("mForcingShowNavBarLayer=");
3683             pw.println(mForcingShowNavBarLayer);
3684         }
3685         pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
3686         pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
3687         pw.print(" mForceStatusBarFromKeyguard="); pw.println(mForceStatusBarFromKeyguard);
3688         pw.print(" mForceShowSystemBarsFromExternal=");
3689         pw.println(mForceShowSystemBarsFromExternal);
3690         pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn);
3691         mStatusBarController.dump(pw, prefix);
3692         mNavigationBarController.dump(pw, prefix);
3693
3694         pw.print(prefix); pw.println("Looper state:");
3695         mHandler.getLooper().dump(new PrintWriterPrinter(pw), prefix + "  ");
3696     }
3697
3698     private boolean supportsPointerLocation() {
3699         return mDisplayContent.isDefaultDisplay || !mDisplayContent.isPrivate();
3700     }
3701
3702     void setPointerLocationEnabled(boolean pointerLocationEnabled) {
3703         if (!supportsPointerLocation()) {
3704             return;
3705         }
3706
3707         mHandler.sendEmptyMessage(pointerLocationEnabled
3708                 ? MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
3709     }
3710
3711     private void enablePointerLocation() {
3712         if (mPointerLocationView != null) {
3713             return;
3714         }
3715
3716         mPointerLocationView = new PointerLocationView(mContext);
3717         mPointerLocationView.setPrintCoords(false);
3718         final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
3719                 WindowManager.LayoutParams.MATCH_PARENT,
3720                 WindowManager.LayoutParams.MATCH_PARENT);
3721         lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
3722         lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
3723                 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
3724                 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
3725                 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
3726         lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
3727         if (ActivityManager.isHighEndGfx()) {
3728             lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
3729             lp.privateFlags |=
3730                     WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
3731         }
3732         lp.format = PixelFormat.TRANSLUCENT;
3733         lp.setTitle("PointerLocation - display " + getDisplayId());
3734         lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
3735         final WindowManager wm = mContext.getSystemService(WindowManager.class);
3736         wm.addView(mPointerLocationView, lp);
3737         mDisplayContent.registerPointerEventListener(mPointerLocationView);
3738     }
3739
3740     private void disablePointerLocation() {
3741         if (mPointerLocationView == null) {
3742             return;
3743         }
3744
3745         mDisplayContent.unregisterPointerEventListener(mPointerLocationView);
3746         final WindowManager wm = mContext.getSystemService(WindowManager.class);
3747         wm.removeView(mPointerLocationView);
3748         mPointerLocationView = null;
3749     }
3750 }