OSDN Git Service

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