OSDN Git Service

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