blob: 72b014cab2bba368f8bf7da4fca2305d0a7afaf7 [file] [log] [blame]
Riddle Hsu5ce4bb32018-07-18 16:11:30 +08001/*
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
17package com.android.server.wm;
18
Tiger Huang7c610aa2018-10-27 00:01:01 +080019import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
Tiger Huangd5f0b9a2019-10-10 10:34:57 +020020import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
Tiger Huang7c610aa2018-10-27 00:01:01 +080021import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
22import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
23import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
24import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
Tiger Huang7c610aa2018-10-27 00:01:01 +080025import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
26import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
Dominik Laskowski26290bb2020-01-15 16:09:55 -080027import static android.view.Display.TYPE_INTERNAL;
Tiger Huange16645a2020-02-25 22:24:39 +080028import static android.view.InsetsState.ITYPE_BOTTOM_DISPLAY_CUTOUT;
Tiger Huang332793b2019-10-29 23:21:27 +080029import static android.view.InsetsState.ITYPE_BOTTOM_GESTURES;
30import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
Yuncheol Heo13a6eb62020-03-04 23:50:37 -080031import static android.view.InsetsState.ITYPE_CAPTION_BAR;
Tiger Huange16645a2020-02-25 22:24:39 +080032import static android.view.InsetsState.ITYPE_LEFT_DISPLAY_CUTOUT;
Tiger Huang332793b2019-10-29 23:21:27 +080033import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
34import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
Tiger Huange16645a2020-02-25 22:24:39 +080035import static android.view.InsetsState.ITYPE_RIGHT_DISPLAY_CUTOUT;
Tiger Huang332793b2019-10-29 23:21:27 +080036import static android.view.InsetsState.ITYPE_RIGHT_GESTURES;
37import static android.view.InsetsState.ITYPE_STATUS_BAR;
Tiger Huange16645a2020-02-25 22:24:39 +080038import static android.view.InsetsState.ITYPE_TOP_DISPLAY_CUTOUT;
Tiger Huang332793b2019-10-29 23:21:27 +080039import static android.view.InsetsState.ITYPE_TOP_GESTURES;
40import static android.view.InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT;
Tiger Huang4a7835f2019-11-06 00:07:56 +080041import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
Jorim Jaggid6490572019-04-16 14:57:56 +020042import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
Tiger Huang7c610aa2018-10-27 00:01:01 +080043import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
Jorim Jaggi956ca412019-01-07 14:49:14 +010044import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
Jorim Jaggi648e5882019-01-24 13:24:02 +010045import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
Tiger Huange218e422020-03-06 21:36:12 +080046import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
Tiger Huang332793b2019-10-29 23:21:27 +080047import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
Tiger Huange218e422020-03-06 21:36:12 +080048import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_NAVIGATION_BARS;
49import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS;
Jorim Jaggi956ca412019-01-07 14:49:14 +010050import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE;
Tiger Huang9ff42bd2020-05-01 03:27:33 +080051import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_TOUCH;
Jorim Jaggi956ca412019-01-07 14:49:14 +010052import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
Tiger Huang7c610aa2018-10-27 00:01:01 +080053import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
54import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
55import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
56import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
57import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
58import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
59import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
60import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR;
61import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
Tiger Huang7c610aa2018-10-27 00:01:01 +080062import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
63import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
Adrian Roos11dfd272019-03-25 19:21:26 +010064import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
Tiger Huang7c610aa2018-10-27 00:01:01 +080065import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
66import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
67import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
68import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
shawnlin465b7de2020-02-11 20:45:35 +080069import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
Tiger Huang7c610aa2018-10-27 00:01:01 +080070import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
Arthur Hung20479922019-02-27 17:13:22 +080071import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
Jorim Jaggia6aabac2019-03-11 14:23:16 -070072import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
wilsonshihe8321942019-10-18 18:39:46 +080073import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
Tiger Huang7c610aa2018-10-27 00:01:01 +080074import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
Tiger Huang7c610aa2018-10-27 00:01:01 +080075import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
Tiger Huang7c610aa2018-10-27 00:01:01 +080076import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
77import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
78import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
79import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
80import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
81import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
Tiger Huang7c610aa2018-10-27 00:01:01 +080082import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
83import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
Charles Chen64172bb2019-04-22 17:30:29 +080084import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
Tiger Huang7c610aa2018-10-27 00:01:01 +080085import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
86import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
wilsonshihe8321942019-10-18 18:39:46 +080087import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
Tiger Huang7c610aa2018-10-27 00:01:01 +080088import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
89import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
90import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
Heemin Seog2cf45dd2020-02-24 15:43:29 -080091import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
Tiger Huang7c610aa2018-10-27 00:01:01 +080092import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
93import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
94import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
95import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
96import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
97import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
Joshua Tsuji94d4c342020-05-04 14:00:24 -040098import static android.view.WindowManager.LayoutParams.TYPE_TRUSTED_APPLICATION_OVERLAY;
Tiger Huang7c610aa2018-10-27 00:01:01 +080099import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
100import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING;
101import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
102import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
103import static android.view.WindowManagerGlobal.ADD_OKAY;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800104import static android.view.WindowManagerPolicyConstants.ACTION_HDMI_PLUGGED;
105import static android.view.WindowManagerPolicyConstants.EXTRA_HDMI_PLUGGED_STATE;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800106import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
107import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
108import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;
109
110import static com.android.server.policy.PhoneWindowManager.TOAST_WINDOW_TIMEOUT;
111import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
112import static com.android.server.policy.WindowManagerPolicy.TRANSIT_ENTER;
113import static com.android.server.policy.WindowManagerPolicy.TRANSIT_EXIT;
114import static com.android.server.policy.WindowManagerPolicy.TRANSIT_HIDE;
115import static com.android.server.policy.WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
116import static com.android.server.policy.WindowManagerPolicy.TRANSIT_SHOW;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800117import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200118import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800119import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
120import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800121import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
122import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
123
Jorim Jaggi4981f152019-03-26 18:58:45 +0100124import android.Manifest.permission;
Issei Suzukia5dbf522019-02-01 17:58:15 +0100125import android.annotation.NonNull;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800126import android.annotation.Nullable;
Jorim Jaggi4981f152019-03-26 18:58:45 +0100127import android.annotation.Px;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800128import android.app.ActivityManager;
129import android.app.ActivityThread;
Winson Chungda20fec2019-04-10 12:19:59 -0700130import android.app.LoadedApk;
131import android.app.ResourcesManager;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800132import android.app.StatusBarManager;
133import android.content.Context;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800134import android.content.Intent;
Jorim Jaggi4981f152019-03-26 18:58:45 +0100135import android.content.pm.PackageManager;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800136import android.content.res.Resources;
Issei Suzukia5dbf522019-02-01 17:58:15 +0100137import android.graphics.Insets;
Arthur Hung20479922019-02-27 17:13:22 +0800138import android.graphics.PixelFormat;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800139import android.graphics.Rect;
Winson Chung36941632019-04-19 15:21:38 -0700140import android.graphics.Region;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800141import android.hardware.input.InputManager;
142import android.hardware.power.V1_0.PowerHint;
143import android.os.Handler;
144import android.os.Looper;
145import android.os.Message;
146import android.os.SystemClock;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800147import android.os.SystemProperties;
148import android.os.UserHandle;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800149import android.util.ArraySet;
Jorim Jaggi956ca412019-01-07 14:49:14 +0100150import android.util.IntArray;
Tarandeep Singhe439dec2019-04-22 12:28:43 -0700151import android.util.Pair;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800152import android.util.PrintWriterPrinter;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800153import android.util.Slog;
Riddle Hsu80f4f7c2020-05-05 23:07:59 +0800154import android.util.SparseArray;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800155import android.view.DisplayCutout;
156import android.view.Gravity;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800157import android.view.InputChannel;
158import android.view.InputDevice;
159import android.view.InputEvent;
160import android.view.InputEventReceiver;
Tiger Huang0dbd5372019-10-26 00:24:22 +0800161import android.view.InsetsFlags;
Tiger Huang9ff42bd2020-05-01 03:27:33 +0800162import android.view.InsetsSource;
Tiger Huang4a7835f2019-11-06 00:07:56 +0800163import android.view.InsetsState;
Tiger Huang332793b2019-10-29 23:21:27 +0800164import android.view.InsetsState.InternalInsetsType;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800165import android.view.MotionEvent;
166import android.view.PointerIcon;
167import android.view.Surface;
168import android.view.View;
Jorim Jaggi648e5882019-01-24 13:24:02 +0100169import android.view.ViewRootImpl;
Tiger Huang4a7835f2019-11-06 00:07:56 +0800170import android.view.WindowInsets.Side;
171import android.view.WindowInsets.Side.InsetsSide;
172import android.view.WindowInsets.Type;
173import android.view.WindowInsets.Type.InsetsType;
Tiger Huang0dbd5372019-10-26 00:24:22 +0800174import android.view.WindowInsetsController.Appearance;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800175import android.view.WindowManager;
176import android.view.WindowManager.LayoutParams;
177import android.view.WindowManagerGlobal;
178import android.view.WindowManagerPolicyConstants;
179import android.view.accessibility.AccessibilityManager;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800180
Tiger Huang7c610aa2018-10-27 00:01:01 +0800181import com.android.internal.R;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800182import com.android.internal.annotations.VisibleForTesting;
Mehdi Alizadehf2b28e92019-12-05 20:13:49 -0800183import com.android.internal.policy.GestureNavigationSettingsObserver;
Tiger Huang43b8fc22019-04-26 11:49:29 +0800184import com.android.internal.policy.ScreenDecorationsUtils;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800185import com.android.internal.util.ScreenshotHelper;
Adrian Roos11dfd272019-03-25 19:21:26 +0100186import com.android.internal.util.function.TriConsumer;
Jorim Jaggi956ca412019-01-07 14:49:14 +0100187import com.android.internal.view.AppearanceRegion;
Arthur Hung20479922019-02-27 17:13:22 +0800188import com.android.internal.widget.PointerLocationView;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800189import com.android.server.LocalServices;
190import com.android.server.UiThread;
191import com.android.server.policy.WindowManagerPolicy;
192import com.android.server.policy.WindowManagerPolicy.InputConsumer;
193import com.android.server.policy.WindowManagerPolicy.NavigationBarPosition;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800194import com.android.server.policy.WindowManagerPolicy.ScreenOnListener;
195import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800196import com.android.server.policy.WindowOrientationListener;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200197import com.android.server.protolog.common.ProtoLog;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800198import com.android.server.statusbar.StatusBarManagerInternal;
wilsonshih643bf132019-02-27 12:49:19 +0800199import com.android.server.wallpaper.WallpaperManagerInternal;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800200import com.android.server.wm.utils.InsetUtils;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800201
202import java.io.PrintWriter;
Riddle Hsu80f4f7c2020-05-05 23:07:59 +0800203import java.util.function.Consumer;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800204
205/**
206 * The policy that provides the basic behaviors and states of a display to show UI.
207 */
208public class DisplayPolicy {
209 private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayPolicy" : TAG_WM;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800210 private static final boolean DEBUG = false;
211
212 private static final boolean ALTERNATE_CAR_MODE_NAV_SIZE = false;
213
214 // The panic gesture may become active only after the keyguard is dismissed and the immersive
215 // app shows again. If that doesn't happen for 30s we drop the gesture.
216 private static final long PANIC_GESTURE_EXPIRATION = 30000;
217
218 // Controls navigation bar opacity depending on which workspace stacks are currently
219 // visible.
220 // Nav bar is always opaque when either the freeform stack or docked stack is visible.
221 private static final int NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED = 0;
222 // Nav bar is always translucent when the freeform stack is visible, otherwise always opaque.
223 private static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1;
Adrian Roosfaba4062019-05-14 15:27:17 +0200224 // Nav bar is never forced opaque.
225 private static final int NAV_BAR_FORCE_TRANSPARENT = 2;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800226
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800227 /** Don't apply window animation (see {@link #selectAnimation}). */
228 static final int ANIMATION_NONE = -1;
229 /** Use the transit animation in style resource (see {@link #selectAnimation}). */
230 static final int ANIMATION_STYLEABLE = 0;
231
Tiger Huang7c610aa2018-10-27 00:01:01 +0800232 /**
233 * These are the system UI flags that, when changing, can cause the layout
234 * of the screen to change.
235 */
236 private static final int SYSTEM_UI_CHANGING_LAYOUT =
237 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
238 | View.SYSTEM_UI_FLAG_FULLSCREEN
239 | View.STATUS_BAR_TRANSLUCENT
240 | View.NAVIGATION_BAR_TRANSLUCENT
241 | View.STATUS_BAR_TRANSPARENT
242 | View.NAVIGATION_BAR_TRANSPARENT;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800243
244 private final WindowManagerService mService;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800245 private final Context mContext;
Charles Chen173ae782019-11-11 20:39:02 +0800246 private final Context mUiContext;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800247 private final DisplayContent mDisplayContent;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800248 private final Object mLock;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800249 private final Handler mHandler;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800250
Winson Chungda20fec2019-04-10 12:19:59 -0700251 private Resources mCurrentUserResources;
252
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800253 private final boolean mCarDockEnablesAccelerometer;
254 private final boolean mDeskDockEnablesAccelerometer;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800255 private final AccessibilityManager mAccessibilityManager;
256 private final ImmersiveModeConfirmation mImmersiveModeConfirmation;
257 private final ScreenshotHelper mScreenshotHelper;
258
259 private final Object mServiceAcquireLock = new Object();
260 private StatusBarManagerInternal mStatusBarManagerInternal;
261
Adrian Roos11dfd272019-03-25 19:21:26 +0100262 @Px
263 private int mBottomGestureAdditionalInset;
264 @Px
Mehdi Alizadehf2b28e92019-12-05 20:13:49 -0800265 private int mLeftGestureInset;
266 @Px
267 private int mRightGestureInset;
Adrian Roos11dfd272019-03-25 19:21:26 +0100268
Sunny Goyal38412952020-04-17 11:35:37 -0700269 private boolean mNavButtonForcedVisible;
270
Jorim Jaggi956ca412019-01-07 14:49:14 +0100271 StatusBarManagerInternal getStatusBarManagerInternal() {
Tiger Huang7c610aa2018-10-27 00:01:01 +0800272 synchronized (mServiceAcquireLock) {
273 if (mStatusBarManagerInternal == null) {
274 mStatusBarManagerInternal =
275 LocalServices.getService(StatusBarManagerInternal.class);
276 }
277 return mStatusBarManagerInternal;
278 }
279 }
280
Tiger Huang7c610aa2018-10-27 00:01:01 +0800281 private final SystemGesturesPointerEventListener mSystemGestures;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800282
283 private volatile int mLidState = LID_ABSENT;
284 private volatile int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
285 private volatile boolean mHdmiPlugged;
286
Louis Changfc64c832018-12-04 11:38:26 +0800287 private volatile boolean mHasStatusBar;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800288 private volatile boolean mHasNavigationBar;
289 // Can the navigation bar ever move to the side?
290 private volatile boolean mNavigationBarCanMove;
Winson Chung36941632019-04-19 15:21:38 -0700291 private volatile boolean mNavigationBarLetsThroughTaps;
292 private volatile boolean mNavigationBarAlwaysShowOnSideGesture;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800293
294 // Written by vr manager thread, only read in this class.
295 private volatile boolean mPersistentVrModeEnabled;
296
297 private volatile boolean mAwake;
298 private volatile boolean mScreenOnEarly;
299 private volatile boolean mScreenOnFully;
300 private volatile ScreenOnListener mScreenOnListener;
301
302 private volatile boolean mKeyguardDrawComplete;
303 private volatile boolean mWindowManagerDrawComplete;
304
Tiger Huang7c610aa2018-10-27 00:01:01 +0800305 private final ArraySet<WindowState> mScreenDecorWindows = new ArraySet<>();
306 private WindowState mStatusBar = null;
wilsonshihe8321942019-10-18 18:39:46 +0800307 private WindowState mNotificationShade = null;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800308 private final int[] mStatusBarHeightForRotation = new int[4];
309 private WindowState mNavigationBar = null;
310 @NavigationBarPosition
311 private int mNavigationBarPosition = NAV_BAR_BOTTOM;
312 private int[] mNavigationBarHeightForRotationDefault = new int[4];
313 private int[] mNavigationBarWidthForRotationDefault = new int[4];
314 private int[] mNavigationBarHeightForRotationInCarMode = new int[4];
315 private int[] mNavigationBarWidthForRotationInCarMode = new int[4];
316
Matthew Nga7f24bc2019-04-09 17:06:41 -0700317 /** See {@link #getNavigationBarFrameHeight} */
318 private int[] mNavigationBarFrameHeightForRotationDefault = new int[4];
319
HEO SEUNG22d3ec22019-05-30 20:28:53 +0900320 private boolean mIsFreeformWindowOverlappingWithNavBar;
321
Tiger Huangdd6db472020-02-13 21:38:46 +0800322 private boolean mLastImmersiveMode;
323
Riddle Hsud80ae9b2019-03-26 00:40:35 +0800324 private final StatusBarController mStatusBarController;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800325
Riddle Hsud80ae9b2019-03-26 00:40:35 +0800326 private final BarController mNavigationBarController;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800327
328 private final BarController.OnBarVisibilityChangedListener mNavBarVisibilityListener =
329 new BarController.OnBarVisibilityChangedListener() {
330 @Override
331 public void onBarVisibilityChanged(boolean visible) {
332 if (mAccessibilityManager == null) {
333 return;
334 }
335 mAccessibilityManager.notifyAccessibilityButtonVisibilityChanged(visible);
336 }
337 };
338
Tiger Huang7c610aa2018-10-27 00:01:01 +0800339 // The windows we were told about in focusChanged.
340 private WindowState mFocusedWindow;
341 private WindowState mLastFocusedWindow;
342
Riddle Hsuc7175762020-01-10 21:03:48 +0800343 // The states of decor windows from the last layout. These are used to generate another display
344 // layout in different bounds but with the same states.
345 private boolean mLastNavVisible;
346 private boolean mLastNavTranslucent;
347 private boolean mLastNavAllowedHidden;
348 private boolean mLastNotificationShadeForcesShowingNavigation;
349
Tiger Huang7c610aa2018-10-27 00:01:01 +0800350 int mLastSystemUiFlags;
351 // Bits that we are in the process of clearing, so we want to prevent
352 // them from being set by applications until everything has been updated
353 // to have them clear.
354 private int mResettingSystemUiFlags = 0;
355 // Bits that we are currently always keeping cleared.
356 private int mForceClearedSystemUiFlags = 0;
Jorim Jaggi956ca412019-01-07 14:49:14 +0100357 private int mLastAppearance;
358 private int mLastFullscreenAppearance;
359 private int mLastDockedAppearance;
Tiger Huang4a7835f2019-11-06 00:07:56 +0800360 private int mLastBehavior;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800361 private final Rect mNonDockedStackBounds = new Rect();
362 private final Rect mDockedStackBounds = new Rect();
363 private final Rect mLastNonDockedStackBounds = new Rect();
364 private final Rect mLastDockedStackBounds = new Rect();
365
Jorim Jaggi956ca412019-01-07 14:49:14 +0100366 // What we last reported to system UI about whether the focused window is fullscreen/immersive.
367 private boolean mLastFocusIsFullscreen = false;
368 private boolean mLastFocusIsImmersive = false;
369
Tiger Huang7c610aa2018-10-27 00:01:01 +0800370 // If nonzero, a panic gesture was performed at that time in uptime millis and is still pending.
371 private long mPendingPanicGestureUptime;
372
373 private static final Rect sTmpDisplayCutoutSafeExceptMaybeBarsRect = new Rect();
374 private static final Rect sTmpRect = new Rect();
Tiger Huang7c610aa2018-10-27 00:01:01 +0800375 private static final Rect sTmpNavFrame = new Rect();
376 private static final Rect sTmpLastParentFrame = new Rect();
377
378 private WindowState mTopFullscreenOpaqueWindowState;
379 private WindowState mTopFullscreenOpaqueOrDimmingWindowState;
380 private WindowState mTopDockedOpaqueWindowState;
381 private WindowState mTopDockedOpaqueOrDimmingWindowState;
382 private boolean mTopIsFullscreen;
383 private boolean mForceStatusBar;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800384 private int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
385 private boolean mForcingShowNavBar;
386 private int mForcingShowNavBarLayer;
387 private boolean mForceShowSystemBars;
388
Brad Stenninge0573692019-03-11 13:52:46 -0700389 /**
390 * Force the display of system bars regardless of other settings.
391 */
392 private boolean mForceShowSystemBarsFromExternal;
393
Tiger Huang7c610aa2018-10-27 00:01:01 +0800394 private boolean mShowingDream;
395 private boolean mLastShowingDream;
396 private boolean mDreamingLockscreen;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800397 private boolean mAllowLockscreenWhenOn;
398
Tiger Huang9ff42bd2020-05-01 03:27:33 +0800399 @VisibleForTesting
400 InputConsumer mInputConsumer = null;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800401
Arthur Hung20479922019-02-27 17:13:22 +0800402 private PointerLocationView mPointerLocationView;
403
Issei Suzukia5dbf522019-02-01 17:58:15 +0100404 /**
405 * The area covered by system windows which belong to another display. Forwarded insets is set
406 * in case this is a virtual display, this is displayed on another display that has insets, and
407 * the bounds of this display is overlapping with the insets of the host display (e.g. IME is
408 * displayed on the host display, and it covers a part of this virtual display.)
409 * The forwarded insets is used to compute display frames of this virtual display, which will
410 * be then used to layout windows in the virtual display.
411 */
412 @NonNull private Insets mForwardedInsets = Insets.NONE;
413
Ady Abrahamf3e05312019-05-13 18:04:59 -0700414 private RefreshRatePolicy mRefreshRatePolicy;
415
Tiger Huang7c610aa2018-10-27 00:01:01 +0800416 // -------- PolicyHandler --------
Tiger Huang7c610aa2018-10-27 00:01:01 +0800417 private static final int MSG_REQUEST_TRANSIENT_BARS = 2;
418 private static final int MSG_DISPOSE_INPUT_CONSUMER = 3;
Arthur Hung20479922019-02-27 17:13:22 +0800419 private static final int MSG_ENABLE_POINTER_LOCATION = 4;
420 private static final int MSG_DISABLE_POINTER_LOCATION = 5;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800421
422 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
423 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
424
Mehdi Alizadehf2b28e92019-12-05 20:13:49 -0800425 private final GestureNavigationSettingsObserver mGestureNavigationSettingsObserver;
426
Tiger Huang7c610aa2018-10-27 00:01:01 +0800427 private class PolicyHandler extends Handler {
428
429 PolicyHandler(Looper looper) {
430 super(looper);
431 }
432
433 @Override
434 public void handleMessage(Message msg) {
435 switch (msg.what) {
Tiger Huang7c610aa2018-10-27 00:01:01 +0800436 case MSG_REQUEST_TRANSIENT_BARS:
Tiger Huang82fd0ad2020-03-09 17:55:47 +0800437 synchronized (mLock) {
438 WindowState targetBar = (msg.arg1 == MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS)
439 ? mStatusBar : mNavigationBar;
440 if (targetBar != null) {
441 requestTransientBars(targetBar);
442 }
Tiger Huang7c610aa2018-10-27 00:01:01 +0800443 }
444 break;
445 case MSG_DISPOSE_INPUT_CONSUMER:
446 disposeInputConsumer((InputConsumer) msg.obj);
447 break;
Arthur Hung20479922019-02-27 17:13:22 +0800448 case MSG_ENABLE_POINTER_LOCATION:
449 enablePointerLocation();
450 break;
451 case MSG_DISABLE_POINTER_LOCATION:
452 disablePointerLocation();
453 break;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800454 }
455 }
456 }
457
458 DisplayPolicy(WindowManagerService service, DisplayContent displayContent) {
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800459 mService = service;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800460 mContext = displayContent.isDefaultDisplay ? service.mContext
461 : service.mContext.createDisplayContext(displayContent.getDisplay());
Charles Chen173ae782019-11-11 20:39:02 +0800462 mUiContext = displayContent.isDefaultDisplay ? service.mAtmService.mUiContext
463 : service.mAtmService.mSystemThread
464 .createSystemUiContext(displayContent.getDisplayId());
Tiger Huang7c610aa2018-10-27 00:01:01 +0800465 mDisplayContent = displayContent;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800466 mLock = service.getWindowManagerLock();
Tiger Huang7c610aa2018-10-27 00:01:01 +0800467
Riddle Hsud80ae9b2019-03-26 00:40:35 +0800468 final int displayId = displayContent.getDisplayId();
469 mStatusBarController = new StatusBarController(displayId);
470 mNavigationBarController = new BarController("NavigationBar",
471 displayId,
472 View.NAVIGATION_BAR_TRANSIENT,
473 View.NAVIGATION_BAR_UNHIDE,
474 View.NAVIGATION_BAR_TRANSLUCENT,
475 StatusBarManager.WINDOW_NAVIGATION_BAR,
Riddle Hsu80f4f7c2020-05-05 23:07:59 +0800476 TYPE_NAVIGATION_BAR,
Riddle Hsud80ae9b2019-03-26 00:40:35 +0800477 FLAG_TRANSLUCENT_NAVIGATION,
478 View.NAVIGATION_BAR_TRANSPARENT);
479
Tiger Huang7c610aa2018-10-27 00:01:01 +0800480 final Resources r = mContext.getResources();
481 mCarDockEnablesAccelerometer = r.getBoolean(R.bool.config_carDockEnablesAccelerometer);
482 mDeskDockEnablesAccelerometer = r.getBoolean(R.bool.config_deskDockEnablesAccelerometer);
Brad Stenninge0573692019-03-11 13:52:46 -0700483 mForceShowSystemBarsFromExternal = r.getBoolean(R.bool.config_forceShowSystemBars);
Tiger Huang7c610aa2018-10-27 00:01:01 +0800484
485 mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(
486 Context.ACCESSIBILITY_SERVICE);
487 if (!displayContent.isDefaultDisplay) {
488 mAwake = true;
489 mScreenOnEarly = true;
490 mScreenOnFully = true;
491 }
492
493 final Looper looper = UiThread.getHandler().getLooper();
494 mHandler = new PolicyHandler(looper);
495 mSystemGestures = new SystemGesturesPointerEventListener(mContext, mHandler,
496 new SystemGesturesPointerEventListener.Callbacks() {
497 @Override
498 public void onSwipeFromTop() {
Tiger Huang82fd0ad2020-03-09 17:55:47 +0800499 synchronized (mLock) {
500 if (mStatusBar != null) {
501 requestTransientBars(mStatusBar);
502 }
Tiger Huang7c610aa2018-10-27 00:01:01 +0800503 }
504 }
505
506 @Override
507 public void onSwipeFromBottom() {
Tiger Huang82fd0ad2020-03-09 17:55:47 +0800508 synchronized (mLock) {
509 if (mNavigationBar != null
510 && mNavigationBarPosition == NAV_BAR_BOTTOM) {
511 requestTransientBars(mNavigationBar);
512 }
Tiger Huang7c610aa2018-10-27 00:01:01 +0800513 }
514 }
515
516 @Override
517 public void onSwipeFromRight() {
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200518 final Region excludedRegion = Region.obtain();
Jeff Chang3cf3e562019-06-18 11:51:25 +0800519 synchronized (mLock) {
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200520 mDisplayContent.calculateSystemGestureExclusion(
521 excludedRegion, null /* outUnrestricted */);
Tiger Huang82fd0ad2020-03-09 17:55:47 +0800522 final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
523 || mNavigationBarPosition == NAV_BAR_RIGHT;
524 if (mNavigationBar != null && sideAllowed
525 && !mSystemGestures.currentGestureStartedInRegion(
526 excludedRegion)) {
527 requestTransientBars(mNavigationBar);
528 }
Tiger Huang7c610aa2018-10-27 00:01:01 +0800529 }
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200530 excludedRegion.recycle();
Tiger Huang7c610aa2018-10-27 00:01:01 +0800531 }
532
533 @Override
534 public void onSwipeFromLeft() {
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200535 final Region excludedRegion = Region.obtain();
Jeff Chang3cf3e562019-06-18 11:51:25 +0800536 synchronized (mLock) {
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200537 mDisplayContent.calculateSystemGestureExclusion(
538 excludedRegion, null /* outUnrestricted */);
Tiger Huang82fd0ad2020-03-09 17:55:47 +0800539 final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
540 || mNavigationBarPosition == NAV_BAR_LEFT;
541 if (mNavigationBar != null && sideAllowed
542 && !mSystemGestures.currentGestureStartedInRegion(
543 excludedRegion)) {
544 requestTransientBars(mNavigationBar);
545 }
Tiger Huang7c610aa2018-10-27 00:01:01 +0800546 }
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200547 excludedRegion.recycle();
Tiger Huang7c610aa2018-10-27 00:01:01 +0800548 }
549
550 @Override
551 public void onFling(int duration) {
552 if (mService.mPowerManagerInternal != null) {
553 mService.mPowerManagerInternal.powerHint(
554 PowerHint.INTERACTION, duration);
555 }
556 }
557
558 @Override
559 public void onDebug() {
560 // no-op
561 }
562
563 private WindowOrientationListener getOrientationListener() {
564 final DisplayRotation rotation = mDisplayContent.getDisplayRotation();
565 return rotation != null ? rotation.getOrientationListener() : null;
566 }
567
568 @Override
569 public void onDown() {
570 final WindowOrientationListener listener = getOrientationListener();
571 if (listener != null) {
572 listener.onTouchStart();
573 }
574 }
575
576 @Override
577 public void onUpOrCancel() {
578 final WindowOrientationListener listener = getOrientationListener();
579 if (listener != null) {
580 listener.onTouchEnd();
581 }
582 }
583
584 @Override
585 public void onMouseHoverAtTop() {
586 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
587 Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
588 msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
589 mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
590 }
591
592 @Override
593 public void onMouseHoverAtBottom() {
594 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
595 Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
596 msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
597 mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
598 }
599
600 @Override
601 public void onMouseLeaveFromEdge() {
602 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
603 }
604 });
605 displayContent.registerPointerEventListener(mSystemGestures);
606 displayContent.mAppTransition.registerListenerLocked(
607 mStatusBarController.getAppTransitionListener());
608 mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext, looper,
609 mService.mVrModeEnabled);
Tiger Huang7c610aa2018-10-27 00:01:01 +0800610
611 // TODO: Make it can take screenshot on external display
612 mScreenshotHelper = displayContent.isDefaultDisplay
613 ? new ScreenshotHelper(mContext) : null;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800614
Tiger Huang7c610aa2018-10-27 00:01:01 +0800615 if (mDisplayContent.isDefaultDisplay) {
Louis Changfc64c832018-12-04 11:38:26 +0800616 mHasStatusBar = true;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800617 mHasNavigationBar = mContext.getResources().getBoolean(R.bool.config_showNavigationBar);
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800618
Tiger Huang7c610aa2018-10-27 00:01:01 +0800619 // Allow a system property to override this. Used by the emulator.
620 // See also hasNavigationBar().
621 String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
622 if ("1".equals(navBarOverride)) {
623 mHasNavigationBar = false;
624 } else if ("0".equals(navBarOverride)) {
625 mHasNavigationBar = true;
626 }
627 } else {
Louis Changfc64c832018-12-04 11:38:26 +0800628 mHasStatusBar = false;
Andrii Kuliandd989612019-02-21 12:13:28 -0800629 mHasNavigationBar = mDisplayContent.supportsSystemDecorations();
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800630 }
Ady Abrahamf3e05312019-05-13 18:04:59 -0700631
632 mRefreshRatePolicy = new RefreshRatePolicy(mService,
633 mDisplayContent.getDisplayInfo(),
634 mService.mHighRefreshRateBlacklist);
Mehdi Alizadehf2b28e92019-12-05 20:13:49 -0800635
636 mGestureNavigationSettingsObserver = new GestureNavigationSettingsObserver(mHandler,
637 mContext, () -> {
638 synchronized (mLock) {
639 onConfigurationChanged();
640 mSystemGestures.onConfigurationChanged();
641 mDisplayContent.updateSystemGestureExclusion();
642 }
643 });
644 mHandler.post(mGestureNavigationSettingsObserver::register);
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800645 }
646
Charles Chen5bdd3e22018-12-18 17:51:56 +0800647 void systemReady() {
648 mSystemGestures.systemReady();
Arthur Hung20479922019-02-27 17:13:22 +0800649 if (mService.mPointerLocationEnabled) {
650 setPointerLocationEnabled(true);
651 }
Charles Chen5bdd3e22018-12-18 17:51:56 +0800652 }
653
654 private int getDisplayId() {
655 return mDisplayContent.getDisplayId();
656 }
657
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800658 public void setHdmiPlugged(boolean plugged) {
659 setHdmiPlugged(plugged, false /* force */);
660 }
661
662 public void setHdmiPlugged(boolean plugged, boolean force) {
663 if (force || mHdmiPlugged != plugged) {
664 mHdmiPlugged = plugged;
665 mService.updateRotation(true /* alwaysSendConfiguration */, true /* forceRelayout */);
666 final Intent intent = new Intent(ACTION_HDMI_PLUGGED);
667 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
668 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
Tiger Huang7c610aa2018-10-27 00:01:01 +0800669 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800670 }
671 }
672
673 boolean isHdmiPlugged() {
674 return mHdmiPlugged;
675 }
676
677 boolean isCarDockEnablesAccelerometer() {
678 return mCarDockEnablesAccelerometer;
679 }
680
681 boolean isDeskDockEnablesAccelerometer() {
682 return mDeskDockEnablesAccelerometer;
683 }
684
685 public void setPersistentVrModeEnabled(boolean persistentVrModeEnabled) {
686 mPersistentVrModeEnabled = persistentVrModeEnabled;
687 }
688
689 public boolean isPersistentVrModeEnabled() {
690 return mPersistentVrModeEnabled;
691 }
692
693 public void setDockMode(int dockMode) {
694 mDockMode = dockMode;
695 }
696
697 public int getDockMode() {
698 return mDockMode;
699 }
700
Brad Stenninge0573692019-03-11 13:52:46 -0700701 /**
702 * @see WindowManagerService.setForceShowSystemBars
703 */
704 void setForceShowSystemBars(boolean forceShowSystemBars) {
705 mForceShowSystemBarsFromExternal = forceShowSystemBars;
706 }
707
JianYang Liuae86b3f2020-04-03 20:20:35 -0700708 boolean getForceShowSystemBars() {
709 return mForceShowSystemBarsFromExternal;
710 }
711
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800712 public boolean hasNavigationBar() {
713 return mHasNavigationBar;
714 }
715
Louis Changfc64c832018-12-04 11:38:26 +0800716 public boolean hasStatusBar() {
717 return mHasStatusBar;
718 }
719
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200720 boolean hasSideGestures() {
Mehdi Alizadehf2b28e92019-12-05 20:13:49 -0800721 return mHasNavigationBar && (mLeftGestureInset > 0 || mRightGestureInset > 0);
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200722 }
723
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800724 public boolean navigationBarCanMove() {
725 return mNavigationBarCanMove;
726 }
727
728 public void setLidState(int lidState) {
729 mLidState = lidState;
730 }
731
732 public int getLidState() {
733 return mLidState;
734 }
735
736 public void setAwake(boolean awake) {
737 mAwake = awake;
738 }
739
740 public boolean isAwake() {
741 return mAwake;
742 }
743
744 public boolean isScreenOnEarly() {
745 return mScreenOnEarly;
746 }
747
748 public boolean isScreenOnFully() {
749 return mScreenOnFully;
750 }
751
752 public boolean isKeyguardDrawComplete() {
753 return mKeyguardDrawComplete;
754 }
755
756 public boolean isWindowManagerDrawComplete() {
757 return mWindowManagerDrawComplete;
758 }
759
760 public ScreenOnListener getScreenOnListener() {
761 return mScreenOnListener;
762 }
763
764 public void screenTurnedOn(ScreenOnListener screenOnListener) {
765 synchronized (mLock) {
766 mScreenOnEarly = true;
767 mScreenOnFully = false;
768 mKeyguardDrawComplete = false;
769 mWindowManagerDrawComplete = false;
770 mScreenOnListener = screenOnListener;
771 }
772 }
773
774 public void screenTurnedOff() {
775 synchronized (mLock) {
776 mScreenOnEarly = false;
777 mScreenOnFully = false;
778 mKeyguardDrawComplete = false;
779 mWindowManagerDrawComplete = false;
780 mScreenOnListener = null;
781 }
782 }
783
784 /** Return false if we are not awake yet or we have already informed of this event. */
785 public boolean finishKeyguardDrawn() {
786 synchronized (mLock) {
787 if (!mScreenOnEarly || mKeyguardDrawComplete) {
788 return false;
789 }
790
791 mKeyguardDrawComplete = true;
792 mWindowManagerDrawComplete = false;
793 }
794 return true;
795 }
796
797 /** Return false if screen is not turned on or we did already handle this case earlier. */
798 public boolean finishWindowsDrawn() {
799 synchronized (mLock) {
800 if (!mScreenOnEarly || mWindowManagerDrawComplete) {
801 return false;
802 }
803
804 mWindowManagerDrawComplete = true;
805 }
806 return true;
807 }
808
809 /** Return false if it is not ready to turn on. */
810 public boolean finishScreenTurningOn() {
811 synchronized (mLock) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200812 ProtoLog.d(WM_DEBUG_SCREEN_ON,
813 "finishScreenTurningOn: mAwake=%b, mScreenOnEarly=%b, "
814 + "mScreenOnFully=%b, mKeyguardDrawComplete=%b, "
815 + "mWindowManagerDrawComplete=%b",
816 mAwake, mScreenOnEarly, mScreenOnFully, mKeyguardDrawComplete,
817 mWindowManagerDrawComplete);
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800818
819 if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
820 || (mAwake && !mKeyguardDrawComplete)) {
821 return false;
822 }
823
Adrian Roosb125e0b2019-10-02 14:55:14 +0200824 ProtoLog.i(WM_DEBUG_SCREEN_ON, "Finished screen turning on...");
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800825 mScreenOnListener = null;
826 mScreenOnFully = true;
827 }
828 return true;
829 }
830
Jorim Jaggi4981f152019-03-26 18:58:45 +0100831 private boolean hasStatusBarServicePermission(int pid, int uid) {
832 return mContext.checkPermission(permission.STATUS_BAR_SERVICE, pid, uid)
833 == PackageManager.PERMISSION_GRANTED;
834 }
835
Tiger Huang7c610aa2018-10-27 00:01:01 +0800836 /**
837 * Sanitize the layout parameters coming from a client. Allows the policy
838 * to do things like ensure that windows of a specific type can't take
839 * input focus.
840 *
841 * @param attrs The window layout parameters to be modified. These values
842 * are modified in-place.
843 */
844 public void adjustWindowParamsLw(WindowState win, WindowManager.LayoutParams attrs,
Jorim Jaggi4981f152019-03-26 18:58:45 +0100845 int callingPid, int callingUid) {
Tiger Huang7c610aa2018-10-27 00:01:01 +0800846
847 final boolean isScreenDecor = (attrs.privateFlags & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0;
848 if (mScreenDecorWindows.contains(win)) {
849 if (!isScreenDecor) {
850 // No longer has the flag set, so remove from the set.
851 mScreenDecorWindows.remove(win);
852 }
Jorim Jaggi4981f152019-03-26 18:58:45 +0100853 } else if (isScreenDecor && hasStatusBarServicePermission(callingPid, callingUid)) {
Tiger Huang7c610aa2018-10-27 00:01:01 +0800854 mScreenDecorWindows.add(win);
855 }
856
857 switch (attrs.type) {
858 case TYPE_SYSTEM_OVERLAY:
859 case TYPE_SECURE_SYSTEM_OVERLAY:
860 // These types of windows can't receive input events.
861 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
862 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
863 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
864 break;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800865 case TYPE_WALLPAPER:
866 // Dreams and wallpapers don't have an app window token and can thus not be
867 // letterboxed. Hence always let them extend under the cutout.
shawnlin465b7de2020-02-11 20:45:35 +0800868 attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800869 break;
wilsonshihe8321942019-10-18 18:39:46 +0800870 case TYPE_NOTIFICATION_SHADE:
Tiger Huang7c610aa2018-10-27 00:01:01 +0800871 // If the Keyguard is in a hidden state (occluded by another window), we force to
872 // remove the wallpaper and keyguard flag so that any change in-flight after setting
873 // the keyguard as occluded wouldn't set these flags again.
874 // See {@link #processKeyguardSetHiddenResultLw}.
875 if (mService.mPolicy.isKeyguardOccluded()) {
876 attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800877 }
878 break;
879
Tiger Huang7c610aa2018-10-27 00:01:01 +0800880 case TYPE_TOAST:
881 // While apps should use the dedicated toast APIs to add such windows
882 // it possible legacy apps to add the window directly. Therefore, we
883 // make windows added directly by the app behave as a toast as much
884 // as possible in terms of timeout and animation.
885 if (attrs.hideTimeoutMilliseconds < 0
886 || attrs.hideTimeoutMilliseconds > TOAST_WINDOW_TIMEOUT) {
887 attrs.hideTimeoutMilliseconds = TOAST_WINDOW_TIMEOUT;
888 }
Rhed Jao406d3a22018-11-30 19:28:58 +0800889 // Accessibility users may need longer timeout duration. This api compares
890 // original timeout with user's preference and return longer one. It returns
891 // original timeout if there's no preference.
892 attrs.hideTimeoutMilliseconds = mAccessibilityManager.getRecommendedTimeoutMillis(
893 (int) attrs.hideTimeoutMilliseconds,
894 AccessibilityManager.FLAG_CONTENT_TEXT);
Tiger Huang7c610aa2018-10-27 00:01:01 +0800895 attrs.windowAnimations = com.android.internal.R.style.Animation_Toast;
Jeff Changb10fac72019-04-09 17:28:30 +0800896 // Toast can show with below conditions when the screen is locked.
897 if (canToastShowWhenLocked(callingPid)) {
898 attrs.flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
899 }
Bernardo Rufino974de952019-10-22 11:53:42 +0100900 // Toasts can't be clickable
901 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800902 break;
Jorim Jaggi0da8fd12020-01-10 01:23:21 +0100903
904 case TYPE_BASE_APPLICATION:
905
906 // A non-translucent main app window isn't allowed to fit insets, as it would create
907 // a hole on the display!
908 if (attrs.isFullscreen() && win.mActivityRecord != null
909 && win.mActivityRecord.fillsParent()
910 && (win.mAttrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0
Tiger Huang52724442020-01-20 21:38:42 +0800911 && attrs.getFitInsetsTypes() != 0) {
Jorim Jaggi0da8fd12020-01-10 01:23:21 +0100912 throw new RuntimeException("Illegal attributes: Main activity window that isn't"
913 + " translucent trying to fit insets: "
Tiger Huang52724442020-01-20 21:38:42 +0800914 + attrs.getFitInsetsTypes()
Jorim Jaggi0da8fd12020-01-10 01:23:21 +0100915 + " attrs=" + attrs);
916 }
917 break;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800918 }
Tiger Huang7c610aa2018-10-27 00:01:01 +0800919 }
920
921 /**
Jeff Changb10fac72019-04-09 17:28:30 +0800922 * @return {@code true} if the calling activity initiate toast and is visible with
923 * {@link WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} flag.
924 */
925 boolean canToastShowWhenLocked(int callingPid) {
926 return mDisplayContent.forAllWindows(w -> {
927 return callingPid == w.mSession.mPid && w.isVisible() && w.canShowWhenLocked();
928 }, true /* traverseTopToBottom */);
929 }
930
931 /**
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800932 * Check if a window can be added to the system.
Tiger Huang7c610aa2018-10-27 00:01:01 +0800933 *
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800934 * Currently enforces that two window types are singletons per display:
Tiger Huang7c610aa2018-10-27 00:01:01 +0800935 * <ul>
936 * <li>{@link WindowManager.LayoutParams#TYPE_STATUS_BAR}</li>
wilsonshihe8321942019-10-18 18:39:46 +0800937 * <li>{@link WindowManager.LayoutParams#TYPE_NOTIFICATION_SHADE}</li>
Tiger Huang7c610aa2018-10-27 00:01:01 +0800938 * <li>{@link WindowManager.LayoutParams#TYPE_NAVIGATION_BAR}</li>
939 * </ul>
940 *
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800941 * @param attrs Information about the window to be added.
Tiger Huang7c610aa2018-10-27 00:01:01 +0800942 *
943 * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons,
944 * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
945 */
Riddle Hsu1371c572020-02-13 13:41:53 +0800946 int validateAddingWindowLw(WindowManager.LayoutParams attrs, int callingPid, int callingUid) {
Tiger Huang7c610aa2018-10-27 00:01:01 +0800947 if ((attrs.privateFlags & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0) {
Riddle Hsu1371c572020-02-13 13:41:53 +0800948 mContext.enforcePermission(
949 android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
Tiger Huang7c610aa2018-10-27 00:01:01 +0800950 "DisplayPolicy");
Tiger Huang7c610aa2018-10-27 00:01:01 +0800951 }
952
953 switch (attrs.type) {
954 case TYPE_STATUS_BAR:
Riddle Hsu1371c572020-02-13 13:41:53 +0800955 mContext.enforcePermission(
956 android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
Tiger Huang7c610aa2018-10-27 00:01:01 +0800957 "DisplayPolicy");
958 if (mStatusBar != null) {
959 if (mStatusBar.isAlive()) {
960 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
961 }
962 }
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800963 break;
wilsonshihe8321942019-10-18 18:39:46 +0800964 case TYPE_NOTIFICATION_SHADE:
Riddle Hsu1371c572020-02-13 13:41:53 +0800965 mContext.enforcePermission(
966 android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
wilsonshihe8321942019-10-18 18:39:46 +0800967 "DisplayPolicy");
968 if (mNotificationShade != null) {
969 if (mNotificationShade.isAlive()) {
970 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
971 }
972 }
973 break;
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800974 case TYPE_NAVIGATION_BAR:
Riddle Hsu1371c572020-02-13 13:41:53 +0800975 mContext.enforcePermission(
976 android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800977 "DisplayPolicy");
978 if (mNavigationBar != null) {
979 if (mNavigationBar.isAlive()) {
980 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
981 }
982 }
983 break;
984 case TYPE_NAVIGATION_BAR_PANEL:
Matt Casey27f0bdd2020-01-28 12:19:28 -0500985 // Check for permission if the caller is not the recents component.
Riddle Hsu1371c572020-02-13 13:41:53 +0800986 if (!mService.mAtmInternal.isCallerRecents(callingUid)) {
987 mContext.enforcePermission(
988 android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
989 "DisplayPolicy");
Matt Casey27f0bdd2020-01-28 12:19:28 -0500990 }
991 break;
Heemin Seog2cf45dd2020-02-24 15:43:29 -0800992 case TYPE_STATUS_BAR_ADDITIONAL:
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800993 case TYPE_STATUS_BAR_SUB_PANEL:
994 case TYPE_VOICE_INTERACTION_STARTING:
Riddle Hsu1371c572020-02-13 13:41:53 +0800995 mContext.enforcePermission(
996 android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800997 "DisplayPolicy");
998 break;
Joshua Tsuji94d4c342020-05-04 14:00:24 -0400999 case TYPE_TRUSTED_APPLICATION_OVERLAY:
1000 mContext.enforcePermission(
1001 android.Manifest.permission.INTERNAL_SYSTEM_WINDOW, callingPid, callingUid,
1002 "DisplayPolicy");
1003 break;
Heemin Seog2cf45dd2020-02-24 15:43:29 -08001004 case TYPE_STATUS_BAR_PANEL:
1005 return WindowManagerGlobal.ADD_INVALID_TYPE;
Tiger Huang5f6cbca2019-07-18 19:00:01 +08001006 }
Yuncheol Heo13a6eb62020-03-04 23:50:37 -08001007
1008 if (attrs.providesInsetsTypes != null) {
1009 mContext.enforcePermission(
1010 android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
1011 "DisplayPolicy");
1012 enforceSingleInsetsTypeCorrespondingToWindowType(attrs.providesInsetsTypes);
1013 }
Tiger Huang5f6cbca2019-07-18 19:00:01 +08001014 return ADD_OKAY;
1015 }
1016
1017 /**
1018 * Called when a window is being added to the system. Must not throw an exception.
1019 *
1020 * @param win The window being added.
1021 * @param attrs Information about the window to be added.
1022 */
1023 void addWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
1024 if ((attrs.privateFlags & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0) {
1025 mScreenDecorWindows.add(win);
1026 }
1027
1028 switch (attrs.type) {
wilsonshihe8321942019-10-18 18:39:46 +08001029 case TYPE_NOTIFICATION_SHADE:
1030 mNotificationShade = win;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001031 if (mDisplayContent.isDefaultDisplay) {
1032 mService.mPolicy.setKeyguardCandidateLw(win);
1033 }
wilsonshihe8321942019-10-18 18:39:46 +08001034 break;
1035 case TYPE_STATUS_BAR:
1036 mStatusBar = win;
1037 mStatusBarController.setWindow(win);
Adrian Roos11dfd272019-03-25 19:21:26 +01001038 final TriConsumer<DisplayFrames, WindowState, Rect> frameProvider =
Jorim Jaggif96c90a2018-09-26 16:55:15 +02001039 (displayFrames, windowState, rect) -> {
1040 rect.top = 0;
1041 rect.bottom = getStatusBarHeight(displayFrames);
Adrian Roos11dfd272019-03-25 19:21:26 +01001042 };
Tiger Huang332793b2019-10-29 23:21:27 +08001043 mDisplayContent.setInsetProvider(ITYPE_STATUS_BAR, win, frameProvider);
1044 mDisplayContent.setInsetProvider(ITYPE_TOP_GESTURES, win, frameProvider);
1045 mDisplayContent.setInsetProvider(ITYPE_TOP_TAPPABLE_ELEMENT, win, frameProvider);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001046 break;
1047 case TYPE_NAVIGATION_BAR:
Tiger Huang7c610aa2018-10-27 00:01:01 +08001048 mNavigationBar = win;
1049 mNavigationBarController.setWindow(win);
1050 mNavigationBarController.setOnBarVisibilityChangedListener(
1051 mNavBarVisibilityListener, true);
Jorim Jaggidd3d5102020-01-28 12:09:03 +01001052 mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, win,
1053 (displayFrames, windowState, inOutFrame) -> {
1054
1055 // In Gesture Nav, navigation bar frame is larger than frame to
1056 // calculate inset.
Riddle Hsu55d7c402020-02-26 22:49:29 +08001057 if (navigationBarPosition(displayFrames.mDisplayWidth,
1058 displayFrames.mDisplayHeight,
Sunny Goyal38412952020-04-17 11:35:37 -07001059 displayFrames.mRotation) == NAV_BAR_BOTTOM
1060 && !mNavButtonForcedVisible) {
1061
Jorim Jaggidd3d5102020-01-28 12:09:03 +01001062 sTmpRect.set(displayFrames.mUnrestricted);
1063 sTmpRect.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
1064 inOutFrame.top = sTmpRect.bottom
1065 - getNavigationBarHeight(displayFrames.mRotation,
Sunny Goyal38412952020-04-17 11:35:37 -07001066 mDisplayContent.getConfiguration().uiMode);
Jorim Jaggidd3d5102020-01-28 12:09:03 +01001067 }
Jorim Jaggi9b4f4202020-01-28 17:05:06 +01001068 },
1069
1070 // For IME we use regular frame.
1071 (displayFrames, windowState, inOutFrame) ->
1072 inOutFrame.set(windowState.getFrameLw()));
1073
Tiger Huang332793b2019-10-29 23:21:27 +08001074 mDisplayContent.setInsetProvider(ITYPE_BOTTOM_GESTURES, win,
Adrian Roos11dfd272019-03-25 19:21:26 +01001075 (displayFrames, windowState, inOutFrame) -> {
1076 inOutFrame.top -= mBottomGestureAdditionalInset;
1077 });
Tiger Huang332793b2019-10-29 23:21:27 +08001078 mDisplayContent.setInsetProvider(ITYPE_LEFT_GESTURES, win,
Adrian Roos11dfd272019-03-25 19:21:26 +01001079 (displayFrames, windowState, inOutFrame) -> {
1080 inOutFrame.left = 0;
1081 inOutFrame.top = 0;
1082 inOutFrame.bottom = displayFrames.mDisplayHeight;
Mehdi Alizadehf2b28e92019-12-05 20:13:49 -08001083 inOutFrame.right = displayFrames.mUnrestricted.left + mLeftGestureInset;
Adrian Roos11dfd272019-03-25 19:21:26 +01001084 });
Tiger Huang332793b2019-10-29 23:21:27 +08001085 mDisplayContent.setInsetProvider(ITYPE_RIGHT_GESTURES, win,
Adrian Roos11dfd272019-03-25 19:21:26 +01001086 (displayFrames, windowState, inOutFrame) -> {
Mehdi Alizadehf2b28e92019-12-05 20:13:49 -08001087 inOutFrame.left = displayFrames.mUnrestricted.right
1088 - mRightGestureInset;
Adrian Roos11dfd272019-03-25 19:21:26 +01001089 inOutFrame.top = 0;
1090 inOutFrame.bottom = displayFrames.mDisplayHeight;
1091 inOutFrame.right = displayFrames.mDisplayWidth;
1092 });
Tiger Huang332793b2019-10-29 23:21:27 +08001093 mDisplayContent.setInsetProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT, win,
Adrian Roos11dfd272019-03-25 19:21:26 +01001094 (displayFrames, windowState, inOutFrame) -> {
1095 if ((windowState.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0
1096 || mNavigationBarLetsThroughTaps) {
1097 inOutFrame.setEmpty();
1098 }
1099 });
Tiger Huang7c610aa2018-10-27 00:01:01 +08001100 if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
1101 break;
Yuncheol Heo13a6eb62020-03-04 23:50:37 -08001102 default:
1103 if (attrs.providesInsetsTypes != null) {
1104 for (int insetsType : attrs.providesInsetsTypes) {
1105 mDisplayContent.setInsetProvider(insetsType, win, null);
1106 }
1107 }
1108 break;
1109 }
1110 }
1111
Tiger Huang77414fa2020-05-15 18:22:00 +08001112 TriConsumer<DisplayFrames, WindowState, Rect> getImeSourceFrameProvider() {
1113 return (displayFrames, windowState, inOutFrame) -> {
1114 if (mNavigationBar != null && navigationBarPosition(displayFrames.mDisplayWidth,
1115 displayFrames.mDisplayHeight,
1116 displayFrames.mRotation) == NAV_BAR_BOTTOM) {
1117 // In gesture navigation, nav bar frame is larger than frame to calculate insets.
1118 // IME should not provide frame which is smaller than the nav bar frame. Otherwise,
1119 // nav bar might be overlapped with the content of the client when IME is shown.
1120 sTmpRect.set(inOutFrame);
1121 sTmpRect.intersectUnchecked(mNavigationBar.getFrameLw());
1122 inOutFrame.inset(windowState.getGivenContentInsetsLw());
1123 inOutFrame.union(sTmpRect);
1124 } else {
1125 inOutFrame.inset(windowState.getGivenContentInsetsLw());
1126 }
1127 };
1128 }
1129
Yuncheol Heo13a6eb62020-03-04 23:50:37 -08001130 private static void enforceSingleInsetsTypeCorrespondingToWindowType(int[] insetsTypes) {
1131 int count = 0;
1132 for (int insetsType : insetsTypes) {
1133 switch (insetsType) {
1134 case ITYPE_NAVIGATION_BAR:
1135 case ITYPE_STATUS_BAR:
1136 case ITYPE_CAPTION_BAR:
1137 if (++count > 1) {
1138 throw new IllegalArgumentException(
1139 "Multiple InsetsTypes corresponding to Window type");
1140 }
1141 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001142 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001143 }
1144
1145 /**
1146 * Called when a window is being removed from a window manager. Must not
1147 * throw an exception -- clean up as much as possible.
1148 *
1149 * @param win The window being removed.
1150 */
Tiger Huang5f6cbca2019-07-18 19:00:01 +08001151 void removeWindowLw(WindowState win) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001152 if (mStatusBar == win) {
1153 mStatusBar = null;
1154 mStatusBarController.setWindow(null);
Tiger Huang332793b2019-10-29 23:21:27 +08001155 mDisplayContent.setInsetProvider(ITYPE_STATUS_BAR, null, null);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001156 } else if (mNavigationBar == win) {
1157 mNavigationBar = null;
1158 mNavigationBarController.setWindow(null);
Tiger Huang332793b2019-10-29 23:21:27 +08001159 mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, null, null);
wilsonshihe8321942019-10-18 18:39:46 +08001160 } else if (mNotificationShade == win) {
1161 mNotificationShade = null;
1162 if (mDisplayContent.isDefaultDisplay) {
1163 mService.mPolicy.setKeyguardCandidateLw(null);
1164 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001165 }
1166 if (mLastFocusedWindow == win) {
1167 mLastFocusedWindow = null;
1168 }
1169 mScreenDecorWindows.remove(win);
1170 }
1171
Jorim Jaggif96c90a2018-09-26 16:55:15 +02001172 private int getStatusBarHeight(DisplayFrames displayFrames) {
1173 return Math.max(mStatusBarHeightForRotation[displayFrames.mRotation],
1174 displayFrames.mDisplayCutoutSafe.top);
1175 }
1176
Riddle Hsu80f4f7c2020-05-05 23:07:59 +08001177 @VisibleForTesting
1178 StatusBarController getStatusBarController() {
1179 return mStatusBarController;
1180 }
1181
Jorim Jaggi28620472019-01-02 23:21:49 +01001182 WindowState getStatusBar() {
1183 return mStatusBar;
1184 }
1185
wilsonshihe8321942019-10-18 18:39:46 +08001186 WindowState getNotificationShade() {
1187 return mNotificationShade;
1188 }
1189
Jorim Jaggi28620472019-01-02 23:21:49 +01001190 WindowState getNavigationBar() {
1191 return mNavigationBar;
1192 }
1193
Tiger Huang7c610aa2018-10-27 00:01:01 +08001194 /**
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001195 * Control the animation to run when a window's state changes. Return a positive number to
1196 * force the animation to a specific resource ID, {@link #ANIMATION_STYLEABLE} to use the
1197 * style resource defining the animation, or {@link #ANIMATION_NONE} for no animation.
Tiger Huang7c610aa2018-10-27 00:01:01 +08001198 *
1199 * @param win The window that is changing.
1200 * @param transit What is happening to the window:
1201 * {@link com.android.server.policy.WindowManagerPolicy#TRANSIT_ENTER},
1202 * {@link com.android.server.policy.WindowManagerPolicy#TRANSIT_EXIT},
1203 * {@link com.android.server.policy.WindowManagerPolicy#TRANSIT_SHOW}, or
1204 * {@link com.android.server.policy.WindowManagerPolicy#TRANSIT_HIDE}.
1205 *
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001206 * @return Resource ID of the actual animation to use, or {@link #ANIMATION_NONE} for none.
Tiger Huang7c610aa2018-10-27 00:01:01 +08001207 */
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001208 int selectAnimation(WindowState win, int transit) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001209 if (DEBUG_ANIM) Slog.i(TAG, "selectAnimation in " + win
1210 + ": transit=" + transit);
1211 if (win == mStatusBar) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001212 if (transit == TRANSIT_EXIT
1213 || transit == TRANSIT_HIDE) {
1214 return R.anim.dock_top_exit;
1215 } else if (transit == TRANSIT_ENTER
1216 || transit == TRANSIT_SHOW) {
1217 return R.anim.dock_top_enter;
1218 }
1219 } else if (win == mNavigationBar) {
1220 if (win.getAttrs().windowAnimations != 0) {
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001221 return ANIMATION_STYLEABLE;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001222 }
1223 // This can be on either the bottom or the right or the left.
1224 if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
1225 if (transit == TRANSIT_EXIT
1226 || transit == TRANSIT_HIDE) {
1227 if (mService.mPolicy.isKeyguardShowingAndNotOccluded()) {
1228 return R.anim.dock_bottom_exit_keyguard;
1229 } else {
1230 return R.anim.dock_bottom_exit;
1231 }
1232 } else if (transit == TRANSIT_ENTER
1233 || transit == TRANSIT_SHOW) {
1234 return R.anim.dock_bottom_enter;
1235 }
1236 } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
1237 if (transit == TRANSIT_EXIT
1238 || transit == TRANSIT_HIDE) {
1239 return R.anim.dock_right_exit;
1240 } else if (transit == TRANSIT_ENTER
1241 || transit == TRANSIT_SHOW) {
1242 return R.anim.dock_right_enter;
1243 }
1244 } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
1245 if (transit == TRANSIT_EXIT
1246 || transit == TRANSIT_HIDE) {
1247 return R.anim.dock_left_exit;
1248 } else if (transit == TRANSIT_ENTER
1249 || transit == TRANSIT_SHOW) {
1250 return R.anim.dock_left_enter;
1251 }
1252 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001253 }
1254
1255 if (transit == TRANSIT_PREVIEW_DONE) {
1256 if (win.hasAppShownWindows()) {
Riddle Hsu3b9ac732020-02-18 16:10:29 +08001257 if (win.isActivityTypeHome()) {
1258 // Dismiss the starting window as soon as possible to avoid the crossfade out
1259 // with old content because home is easier to have different UI states.
1260 return ANIMATION_NONE;
1261 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001262 if (DEBUG_ANIM) Slog.i(TAG, "**** STARTING EXIT");
1263 return R.anim.app_starting_exit;
1264 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001265 }
1266
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001267 return ANIMATION_STYLEABLE;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001268 }
1269
Tiger Huang7c610aa2018-10-27 00:01:01 +08001270 /**
Tiger Huang7c610aa2018-10-27 00:01:01 +08001271 * Called when a new system UI visibility is being reported, allowing
1272 * the policy to adjust what is actually reported.
1273 * @param visibility The raw visibility reported by the status bar.
1274 * @return The new desired visibility.
1275 */
1276 public int adjustSystemUiVisibilityLw(int visibility) {
1277 mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
1278 mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
1279
1280 // Reset any bits in mForceClearingStatusBarVisibility that
1281 // are now clear.
1282 mResettingSystemUiFlags &= visibility;
1283 // Clear any bits in the new visibility that are currently being
1284 // force cleared, before reporting it.
1285 return visibility & ~mResettingSystemUiFlags
1286 & ~mForceClearedSystemUiFlags;
1287 }
1288
1289 /**
Brad Stenninge0573692019-03-11 13:52:46 -07001290 * @return true if the system bars are forced to stay visible
Tiger Huang7c610aa2018-10-27 00:01:01 +08001291 */
Brad Stenninge0573692019-03-11 13:52:46 -07001292 public boolean areSystemBarsForcedShownLw(WindowState windowState) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001293 return mForceShowSystemBars;
1294 }
1295
1296 // TODO: Should probably be moved into DisplayFrames.
1297 /**
1298 * Return the layout hints for a newly added window. These values are computed on the
1299 * most recent layout, so they are not guaranteed to be correct.
1300 *
1301 * @param attrs The LayoutParams of the window.
Riddle Hsu55d7c402020-02-26 22:49:29 +08001302 * @param windowToken The token of the window.
Tiger Huang7c610aa2018-10-27 00:01:01 +08001303 * @param outFrame The frame of the window.
1304 * @param outContentInsets The areas covered by system windows, expressed as positive insets.
1305 * @param outStableInsets The areas covered by stable system windows irrespective of their
1306 * current visibility. Expressed as positive insets.
Tiger Huang7c610aa2018-10-27 00:01:01 +08001307 * @param outDisplayCutout The area that has been cut away from the display.
Brad Stenninge0573692019-03-11 13:52:46 -07001308 * @return Whether to always consume the system bars.
1309 * See {@link #areSystemBarsForcedShownLw(WindowState)}.
Tiger Huang7c610aa2018-10-27 00:01:01 +08001310 */
Riddle Hsu55d7c402020-02-26 22:49:29 +08001311 boolean getLayoutHint(LayoutParams attrs, WindowToken windowToken, Rect outFrame,
Tiger Huang7c610aa2018-10-27 00:01:01 +08001312 Rect outContentInsets, Rect outStableInsets,
Jorim Jaggif081f062019-10-24 16:24:54 +02001313 DisplayCutout.ParcelableWrapper outDisplayCutout) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001314 final int fl = PolicyControl.getWindowFlags(null, attrs);
1315 final int pfl = attrs.privateFlags;
1316 final int requestedSysUiVis = PolicyControl.getSystemUiVisibility(null, attrs);
1317 final int sysUiVis = requestedSysUiVis | getImpliedSysUiFlagsForLayout(attrs);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001318
1319 final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) != 0;
1320 final boolean layoutInScreenAndInsetDecor = layoutInScreen
1321 && (fl & FLAG_LAYOUT_INSET_DECOR) != 0;
1322 final boolean screenDecor = (pfl & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0;
1323
Riddle Hsu55d7c402020-02-26 22:49:29 +08001324 final boolean isFixedRotationTransforming =
1325 windowToken != null && windowToken.isFixedRotationTransforming();
1326 final ActivityRecord activity = windowToken != null ? windowToken.asActivityRecord() : null;
1327 final Task task = activity != null ? activity.getTask() : null;
1328 final Rect taskBounds = isFixedRotationTransforming
1329 // Use token (activity) bounds if it is rotated because its task is not rotated.
1330 ? windowToken.getBounds()
1331 : (task != null ? task.getBounds() : null);
1332 final DisplayFrames displayFrames = isFixedRotationTransforming
1333 ? windowToken.getFixedRotationTransformDisplayFrames()
1334 : mDisplayContent.mDisplayFrames;
1335
Tiger Huang7c610aa2018-10-27 00:01:01 +08001336 if (layoutInScreenAndInsetDecor && !screenDecor) {
Tiger Huang4a7835f2019-11-06 00:07:56 +08001337 if ((sysUiVis & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
Tiger Huang52724442020-01-20 21:38:42 +08001338 || (attrs.getFitInsetsTypes() & Type.navigationBars()) == 0) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001339 outFrame.set(displayFrames.mUnrestricted);
1340 } else {
1341 outFrame.set(displayFrames.mRestricted);
1342 }
1343
Riddle Hsu55d7c402020-02-26 22:49:29 +08001344 final boolean isFloatingTask = task != null && task.isFloating();
1345 final Rect sf = isFloatingTask ? null : displayFrames.mStable;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001346 final Rect cf;
Riddle Hsu55d7c402020-02-26 22:49:29 +08001347 if (isFloatingTask) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001348 cf = null;
1349 } else if ((sysUiVis & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
1350 if ((fl & FLAG_FULLSCREEN) != 0) {
1351 cf = displayFrames.mStableFullscreen;
1352 } else {
1353 cf = displayFrames.mStable;
1354 }
Jorim Jaggif081f062019-10-24 16:24:54 +02001355 } else if ((fl & FLAG_FULLSCREEN) != 0) {
1356 cf = displayFrames.mUnrestricted;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001357 } else {
1358 cf = displayFrames.mCurrent;
1359 }
1360
1361 if (taskBounds != null) {
1362 outFrame.intersect(taskBounds);
1363 }
1364 InsetUtils.insetsBetweenFrames(outFrame, cf, outContentInsets);
1365 InsetUtils.insetsBetweenFrames(outFrame, sf, outStableInsets);
1366 outDisplayCutout.set(displayFrames.mDisplayCutout.calculateRelativeTo(outFrame)
1367 .getDisplayCutout());
1368 return mForceShowSystemBars;
1369 } else {
1370 if (layoutInScreen) {
1371 outFrame.set(displayFrames.mUnrestricted);
1372 } else {
1373 outFrame.set(displayFrames.mStable);
1374 }
1375 if (taskBounds != null) {
1376 outFrame.intersect(taskBounds);
1377 }
1378
1379 outContentInsets.setEmpty();
1380 outStableInsets.setEmpty();
1381 outDisplayCutout.set(DisplayCutout.NO_CUTOUT);
1382 return mForceShowSystemBars;
1383 }
1384 }
1385
Tiger Huang4a7835f2019-11-06 00:07:56 +08001386 // TODO(b/118118435): remove after migration
Tiger Huang7c610aa2018-10-27 00:01:01 +08001387 private static int getImpliedSysUiFlagsForLayout(LayoutParams attrs) {
1388 int impliedFlags = 0;
Jorim Jaggia6aabac2019-03-11 14:23:16 -07001389 final boolean forceWindowDrawsBarBackgrounds =
1390 (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0
Tiger Huang4a7835f2019-11-06 00:07:56 +08001391 && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001392 if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
Jorim Jaggia6aabac2019-03-11 14:23:16 -07001393 || forceWindowDrawsBarBackgrounds) {
Jorim Jaggid6490572019-04-16 14:57:56 +02001394 impliedFlags |= SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001395 impliedFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
1396 }
1397 return impliedFlags;
1398 }
1399
Tiger Huang7c610aa2018-10-27 00:01:01 +08001400 private final Runnable mClearHideNavigationFlag = new Runnable() {
1401 @Override
1402 public void run() {
1403 synchronized (mLock) {
1404 mForceClearedSystemUiFlags &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
1405 mDisplayContent.reevaluateStatusBarVisibility();
1406 }
1407 }
1408 };
1409
1410 /**
1411 * Input handler used while nav bar is hidden. Captures any touch on the screen,
1412 * to determine when the nav bar should be shown and prevent applications from
1413 * receiving those touches.
1414 */
1415 private final class HideNavInputEventReceiver extends InputEventReceiver {
1416 HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
1417 super(inputChannel, looper);
1418 }
1419
1420 @Override
1421 public void onInputEvent(InputEvent event) {
1422 try {
1423 if (event instanceof MotionEvent
1424 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
1425 final MotionEvent motionEvent = (MotionEvent) event;
1426 if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
1427 // When the user taps down, we re-show the nav bar.
1428 boolean changed = false;
1429 synchronized (mLock) {
1430 if (mInputConsumer == null) {
1431 return;
1432 }
Tiger Huang9ff42bd2020-05-01 03:27:33 +08001433 showNavigationBar();
Tiger Huang7c610aa2018-10-27 00:01:01 +08001434 // Any user activity always causes us to show the
1435 // navigation controls, if they had been hidden.
1436 // We also clear the low profile and only content
1437 // flags so that tapping on the screen will atomically
1438 // restore all currently hidden screen decorations.
1439 int newVal = mResettingSystemUiFlags
1440 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
1441 | View.SYSTEM_UI_FLAG_LOW_PROFILE
1442 | View.SYSTEM_UI_FLAG_FULLSCREEN;
1443 if (mResettingSystemUiFlags != newVal) {
1444 mResettingSystemUiFlags = newVal;
1445 changed = true;
1446 }
1447 // We don't allow the system's nav bar to be hidden
1448 // again for 1 second, to prevent applications from
1449 // spamming us and keeping it from being shown.
1450 newVal = mForceClearedSystemUiFlags
1451 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
1452 if (mForceClearedSystemUiFlags != newVal) {
1453 mForceClearedSystemUiFlags = newVal;
1454 changed = true;
1455 mHandler.postDelayed(mClearHideNavigationFlag, 1000);
1456 }
1457 if (changed) {
1458 mDisplayContent.reevaluateStatusBarVisibility();
1459 }
1460 }
1461 }
1462 }
1463 } finally {
1464 finishInputEvent(event, false /* handled */);
1465 }
1466 }
Tiger Huang9ff42bd2020-05-01 03:27:33 +08001467
1468 private void showNavigationBar() {
1469 final InsetsSourceProvider provider = mDisplayContent.getInsetsStateController()
1470 .peekSourceProvider(ITYPE_NAVIGATION_BAR);
1471 final InsetsControlTarget target =
1472 provider != null ? provider.getControlTarget() : null;
1473 if (target != null) {
1474 target.showInsets(Type.navigationBars(), false /* fromIme */);
1475 }
1476 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001477 }
1478
Riddle Hsu6f548e92020-01-13 13:34:09 +08001479 private void simulateLayoutDecorWindow(WindowState win, DisplayFrames displayFrames,
Riddle Hsu80f4f7c2020-05-05 23:07:59 +08001480 InsetsState insetsState, WindowFrames simulatedWindowFrames,
1481 SparseArray<Rect> contentFrames, Consumer<Rect> layout) {
Riddle Hsuc7175762020-01-10 21:03:48 +08001482 win.setSimulatedWindowFrames(simulatedWindowFrames);
Riddle Hsu80f4f7c2020-05-05 23:07:59 +08001483 final Rect contentFrame = new Rect();
Riddle Hsuc7175762020-01-10 21:03:48 +08001484 try {
Riddle Hsu80f4f7c2020-05-05 23:07:59 +08001485 layout.accept(contentFrame);
Riddle Hsuc7175762020-01-10 21:03:48 +08001486 } finally {
1487 win.setSimulatedWindowFrames(null);
1488 }
Riddle Hsu80f4f7c2020-05-05 23:07:59 +08001489 contentFrames.put(win.mAttrs.type, contentFrame);
Riddle Hsuc7175762020-01-10 21:03:48 +08001490 mDisplayContent.getInsetsStateController().computeSimulatedState(insetsState, win,
1491 displayFrames, simulatedWindowFrames);
1492 }
1493
1494 /**
1495 * Computes the frames of display (its logical size, rotation and cutout should already be set)
1496 * used to layout window. The result of display frames and insets state should be the same as
1497 * using {@link #beginLayoutLw}, but this method only changes the given display frames, insets
1498 * state and some temporal states. In other words, it doesn't change the window frames used to
1499 * show on screen.
1500 */
Riddle Hsu80f4f7c2020-05-05 23:07:59 +08001501 void simulateLayoutDisplay(DisplayFrames displayFrames, InsetsState insetsState,
1502 SparseArray<Rect> barContentFrames) {
Riddle Hsuc7175762020-01-10 21:03:48 +08001503 displayFrames.onBeginLayout();
Tiger Huange16645a2020-02-25 22:24:39 +08001504 updateInsetsStateForDisplayCutout(displayFrames, insetsState);
Riddle Hsu55d7c402020-02-26 22:49:29 +08001505 insetsState.setDisplayFrame(displayFrames.mUnrestricted);
Riddle Hsuc7175762020-01-10 21:03:48 +08001506 final WindowFrames simulatedWindowFrames = new WindowFrames();
1507 if (mNavigationBar != null) {
Riddle Hsu80f4f7c2020-05-05 23:07:59 +08001508 simulateLayoutDecorWindow(mNavigationBar, displayFrames, insetsState,
1509 simulatedWindowFrames, barContentFrames,
1510 contentFrame -> layoutNavigationBar(displayFrames,
1511 mDisplayContent.getConfiguration().uiMode, mLastNavVisible,
Riddle Hsuc7175762020-01-10 21:03:48 +08001512 mLastNavTranslucent, mLastNavAllowedHidden,
Riddle Hsu80f4f7c2020-05-05 23:07:59 +08001513 mLastNotificationShadeForcesShowingNavigation, contentFrame));
Riddle Hsuc7175762020-01-10 21:03:48 +08001514 }
1515 if (mStatusBar != null) {
Riddle Hsu80f4f7c2020-05-05 23:07:59 +08001516 simulateLayoutDecorWindow(mStatusBar, displayFrames, insetsState,
1517 simulatedWindowFrames, barContentFrames,
1518 contentFrame -> layoutStatusBar(displayFrames, mLastSystemUiFlags,
1519 contentFrame));
Riddle Hsuc7175762020-01-10 21:03:48 +08001520 }
1521 layoutScreenDecorWindows(displayFrames, simulatedWindowFrames);
1522 postAdjustDisplayFrames(displayFrames);
1523 }
1524
Tiger Huang7c610aa2018-10-27 00:01:01 +08001525 /**
1526 * Called when layout of the windows is about to start.
1527 *
1528 * @param displayFrames frames of the display we are doing layout on.
1529 * @param uiMode The current uiMode in configuration.
1530 */
1531 public void beginLayoutLw(DisplayFrames displayFrames, int uiMode) {
1532 displayFrames.onBeginLayout();
Tiger Huang57e2e1c2020-03-13 22:54:36 +08001533 updateInsetsStateForDisplayCutout(displayFrames,
1534 mDisplayContent.getInsetsStateController().getRawInsetsState());
Tiger Huang7c610aa2018-10-27 00:01:01 +08001535 mSystemGestures.screenWidth = displayFrames.mUnrestricted.width();
1536 mSystemGestures.screenHeight = displayFrames.mUnrestricted.height();
1537
1538 // For purposes of putting out fake window up to steal focus, we will
1539 // drive nav being hidden only by whether it is requested.
1540 final int sysui = mLastSystemUiFlags;
Tiger Huang4a7835f2019-11-06 00:07:56 +08001541 final int behavior = mLastBehavior;
Tiger Huang9ff42bd2020-05-01 03:27:33 +08001542 final InsetsSourceProvider provider =
1543 mDisplayContent.getInsetsStateController().peekSourceProvider(ITYPE_NAVIGATION_BAR);
Tiger Huang4a7835f2019-11-06 00:07:56 +08001544 boolean navVisible = ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL
1545 ? (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
Tiger Huang9ff42bd2020-05-01 03:27:33 +08001546 : provider != null
1547 ? provider.isClientVisible()
1548 : InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001549 boolean navTranslucent = (sysui
1550 & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
Tiger Huang4a7835f2019-11-06 00:07:56 +08001551 boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0
1552 || (behavior & BEHAVIOR_SHOW_BARS_BY_SWIPE) != 0;
1553 boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0
1554 || (behavior & BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE) != 0;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001555 boolean navAllowedHidden = immersive || immersiveSticky;
1556 navTranslucent &= !immersiveSticky; // transient trumps translucent
wilsonshihe8321942019-10-18 18:39:46 +08001557 boolean isKeyguardShowing = isKeyguardShowing() && !isKeyguardOccluded();
1558 boolean notificationShadeForcesShowingNavigation =
1559 !isKeyguardShowing && mNotificationShade != null
1560 && (mNotificationShade.getAttrs().privateFlags
Tiger Huang7c610aa2018-10-27 00:01:01 +08001561 & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0;
1562
Tiger Huang9ff42bd2020-05-01 03:27:33 +08001563 updateHideNavInputEventReceiver();
Tiger Huang7c610aa2018-10-27 00:01:01 +08001564
1565 // For purposes of positioning and showing the nav bar, if we have decided that it can't
1566 // be hidden (because of the screen aspect ratio), then take that into account.
1567 navVisible |= !canHideNavigationBar();
1568
1569 boolean updateSysUiVisibility = layoutNavigationBar(displayFrames, uiMode, navVisible,
Riddle Hsuc7175762020-01-10 21:03:48 +08001570 navTranslucent, navAllowedHidden, notificationShadeForcesShowingNavigation,
Riddle Hsu80f4f7c2020-05-05 23:07:59 +08001571 null /* simulatedContentFrame */);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001572 if (DEBUG_LAYOUT) Slog.i(TAG, "mDock rect:" + displayFrames.mDock);
Riddle Hsu80f4f7c2020-05-05 23:07:59 +08001573 updateSysUiVisibility |= layoutStatusBar(displayFrames, sysui,
1574 null /* simulatedContentFrame */);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001575 if (updateSysUiVisibility) {
1576 updateSystemUiVisibilityLw();
1577 }
Riddle Hsu6f548e92020-01-13 13:34:09 +08001578 layoutScreenDecorWindows(displayFrames, null /* simulatedFrames */);
Riddle Hsuc7175762020-01-10 21:03:48 +08001579 postAdjustDisplayFrames(displayFrames);
1580 mLastNavVisible = navVisible;
1581 mLastNavTranslucent = navTranslucent;
1582 mLastNavAllowedHidden = navAllowedHidden;
1583 mLastNotificationShadeForcesShowingNavigation = notificationShadeForcesShowingNavigation;
1584 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001585
Tiger Huang9ff42bd2020-05-01 03:27:33 +08001586 void updateHideNavInputEventReceiver() {
1587 final InsetsSourceProvider provider = mDisplayContent.getInsetsStateController()
1588 .peekSourceProvider(ITYPE_NAVIGATION_BAR);
1589 final InsetsControlTarget navControlTarget =
1590 provider != null ? provider.getControlTarget() : null;
1591 final WindowState navControllingWin =
1592 navControlTarget instanceof WindowState ? (WindowState) navControlTarget : null;
1593 final InsetsState requestedState = navControllingWin != null
1594 ? navControllingWin.getRequestedInsetsState() : null;
Tiger Huang017d51d2020-05-27 17:58:17 +08001595 final boolean navVisible = requestedState != null
1596 ? requestedState.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR)
1597 : InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR);
Tiger Huang9ff42bd2020-05-01 03:27:33 +08001598 final boolean showBarsByTouch = navControllingWin != null
1599 && navControllingWin.mAttrs.insetsFlags.behavior == BEHAVIOR_SHOW_BARS_BY_TOUCH;
Tiger Huangd611a9b2020-03-25 17:52:17 +08001600 // When the navigation bar isn't visible, we put up a fake input window to catch all
1601 // touch events. This way we can detect when the user presses anywhere to bring back the
1602 // nav bar and ensure the application doesn't see the event.
Tiger Huang9ff42bd2020-05-01 03:27:33 +08001603 if (navVisible || !showBarsByTouch) {
Tiger Huangd611a9b2020-03-25 17:52:17 +08001604 if (mInputConsumer != null) {
1605 mInputConsumer.dismiss();
1606 mHandler.sendMessage(
1607 mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
1608 mInputConsumer = null;
Tiger Huang9ff42bd2020-05-01 03:27:33 +08001609 Slog.v(TAG, INPUT_CONSUMER_NAVIGATION + " dismissed.");
Tiger Huangd611a9b2020-03-25 17:52:17 +08001610 }
1611 } else if (mInputConsumer == null && mStatusBar != null && canHideNavigationBar()) {
1612 mInputConsumer = mDisplayContent.getInputMonitor().createInputConsumer(
1613 mHandler.getLooper(),
1614 INPUT_CONSUMER_NAVIGATION,
1615 HideNavInputEventReceiver::new);
Tiger Huang9ff42bd2020-05-01 03:27:33 +08001616 Slog.v(TAG, INPUT_CONSUMER_NAVIGATION + " created.");
Tiger Huangd611a9b2020-03-25 17:52:17 +08001617 // As long as mInputConsumer is active, hover events are not dispatched to the app
1618 // and the pointer icon is likely to become stale. Hide it to avoid confusion.
1619 InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL);
1620 }
1621 }
1622
Tiger Huange16645a2020-02-25 22:24:39 +08001623 private static void updateInsetsStateForDisplayCutout(DisplayFrames displayFrames,
1624 InsetsState state) {
1625 if (displayFrames.mDisplayCutout.getDisplayCutout().isEmpty()) {
1626 state.removeSource(ITYPE_LEFT_DISPLAY_CUTOUT);
1627 state.removeSource(ITYPE_TOP_DISPLAY_CUTOUT);
1628 state.removeSource(ITYPE_RIGHT_DISPLAY_CUTOUT);
1629 state.removeSource(ITYPE_BOTTOM_DISPLAY_CUTOUT);
1630 return;
1631 }
1632 final Rect u = displayFrames.mUnrestricted;
1633 final Rect s = displayFrames.mDisplayCutoutSafe;
1634 state.getSource(ITYPE_LEFT_DISPLAY_CUTOUT).setFrame(u.left, u.top, s.left, u.bottom);
1635 state.getSource(ITYPE_TOP_DISPLAY_CUTOUT).setFrame(u.left, u.top, u.right, s.top);
1636 state.getSource(ITYPE_RIGHT_DISPLAY_CUTOUT).setFrame(s.right, u.top, u.right, u.bottom);
1637 state.getSource(ITYPE_BOTTOM_DISPLAY_CUTOUT).setFrame(u.left, s.bottom, u.right, u.bottom);
1638 }
1639
Riddle Hsuc7175762020-01-10 21:03:48 +08001640 /** Enforces the last layout policy for display frames. */
1641 private void postAdjustDisplayFrames(DisplayFrames displayFrames) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001642 if (displayFrames.mDisplayCutoutSafe.top > displayFrames.mUnrestricted.top) {
1643 // Make sure that the zone we're avoiding for the cutout is at least as tall as the
1644 // status bar; otherwise fullscreen apps will end up cutting halfway into the status
1645 // bar.
1646 displayFrames.mDisplayCutoutSafe.top = Math.max(displayFrames.mDisplayCutoutSafe.top,
1647 displayFrames.mStable.top);
1648 }
Issei Suzukia5dbf522019-02-01 17:58:15 +01001649
1650 // In case this is a virtual display, and the host display has insets that overlap this
1651 // virtual display, apply the insets of the overlapped area onto the current and content
1652 // frame of this virtual display. This let us layout windows in the virtual display as
1653 // expected when the window needs to avoid overlap with the system windows.
1654 // TODO: Generalize the forwarded insets, so that we can handle system windows other than
1655 // IME.
1656 displayFrames.mCurrent.inset(mForwardedInsets);
1657 displayFrames.mContent.inset(mForwardedInsets);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001658 }
1659
Riddle Hsuc7175762020-01-10 21:03:48 +08001660 /**
1661 * Layout the decor windows with {@link #PRIVATE_FLAG_IS_SCREEN_DECOR}.
1662 *
1663 * @param displayFrames The display frames to be layouted.
1664 * @param simulatedFrames Non-null if the caller only needs the result of display frames (see
1665 * {@link WindowState#mSimulatedWindowFrames}).
1666 */
1667 private void layoutScreenDecorWindows(DisplayFrames displayFrames,
1668 WindowFrames simulatedFrames) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001669 if (mScreenDecorWindows.isEmpty()) {
1670 return;
1671 }
1672
1673 sTmpRect.setEmpty();
Tiger Huang7c610aa2018-10-27 00:01:01 +08001674 final int displayId = displayFrames.mDisplayId;
1675 final Rect dockFrame = displayFrames.mDock;
1676 final int displayHeight = displayFrames.mDisplayHeight;
1677 final int displayWidth = displayFrames.mDisplayWidth;
1678
1679 for (int i = mScreenDecorWindows.size() - 1; i >= 0; --i) {
1680 final WindowState w = mScreenDecorWindows.valueAt(i);
1681 if (w.getDisplayId() != displayId || !w.isVisibleLw()) {
1682 // Skip if not on the same display or not visible.
1683 continue;
1684 }
1685
Riddle Hsuc7175762020-01-10 21:03:48 +08001686 final boolean isSimulatedLayout = simulatedFrames != null;
1687 if (isSimulatedLayout) {
1688 w.setSimulatedWindowFrames(simulatedFrames);
1689 }
1690 final WindowFrames windowFrames = w.getLayoutingWindowFrames();
1691 windowFrames.setFrames(displayFrames.mUnrestricted /* parentFrame */,
chaviw0d833762019-06-20 17:09:53 -07001692 displayFrames.mUnrestricted /* displayFrame */,
chaviw0d833762019-06-20 17:09:53 -07001693 displayFrames.mUnrestricted /* contentFrame */,
1694 displayFrames.mUnrestricted /* visibleFrame */, sTmpRect /* decorFrame */,
Jorim Jaggif081f062019-10-24 16:24:54 +02001695 displayFrames.mUnrestricted /* stableFrame */);
Riddle Hsuc7175762020-01-10 21:03:48 +08001696 try {
1697 w.computeFrame(displayFrames);
1698 } finally {
1699 if (isSimulatedLayout) {
1700 w.setSimulatedWindowFrames(null);
1701 }
Tiger Huang4a7835f2019-11-06 00:07:56 +08001702 }
Riddle Hsuc7175762020-01-10 21:03:48 +08001703 final Rect frame = windowFrames.mFrame;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001704
1705 if (frame.left <= 0 && frame.top <= 0) {
1706 // Docked at left or top.
1707 if (frame.bottom >= displayHeight) {
1708 // Docked left.
1709 dockFrame.left = Math.max(frame.right, dockFrame.left);
1710 } else if (frame.right >= displayWidth) {
1711 // Docked top.
1712 dockFrame.top = Math.max(frame.bottom, dockFrame.top);
1713 } else {
1714 Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w
1715 + " not docked on left or top of display. frame=" + frame
1716 + " displayWidth=" + displayWidth + " displayHeight=" + displayHeight);
1717 }
1718 } else if (frame.right >= displayWidth && frame.bottom >= displayHeight) {
1719 // Docked at right or bottom.
1720 if (frame.top <= 0) {
1721 // Docked right.
1722 dockFrame.right = Math.min(frame.left, dockFrame.right);
1723 } else if (frame.left <= 0) {
1724 // Docked bottom.
1725 dockFrame.bottom = Math.min(frame.top, dockFrame.bottom);
1726 } else {
1727 Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w
1728 + " not docked on right or bottom" + " of display. frame=" + frame
1729 + " displayWidth=" + displayWidth + " displayHeight=" + displayHeight);
1730 }
1731 } else {
1732 // Screen decor windows are required to be docked on one of the sides of the screen.
1733 Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w
1734 + " not docked on one of the sides of the display. frame=" + frame
1735 + " displayWidth=" + displayWidth + " displayHeight=" + displayHeight);
1736 }
1737 }
1738
1739 displayFrames.mRestricted.set(dockFrame);
1740 displayFrames.mCurrent.set(dockFrame);
1741 displayFrames.mVoiceContent.set(dockFrame);
1742 displayFrames.mSystem.set(dockFrame);
1743 displayFrames.mContent.set(dockFrame);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001744 }
1745
Riddle Hsu80f4f7c2020-05-05 23:07:59 +08001746 private boolean layoutStatusBar(DisplayFrames displayFrames, int sysui,
1747 Rect simulatedContentFrame) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001748 // decide where the status bar goes ahead of time
1749 if (mStatusBar == null) {
1750 return false;
1751 }
1752 // apply any navigation bar insets
1753 sTmpRect.setEmpty();
Riddle Hsuc7175762020-01-10 21:03:48 +08001754 final WindowFrames windowFrames = mStatusBar.getLayoutingWindowFrames();
Jorim Jaggi4981f152019-03-26 18:58:45 +01001755 windowFrames.setFrames(displayFrames.mUnrestricted /* parentFrame */,
Tiger Huang7c610aa2018-10-27 00:01:01 +08001756 displayFrames.mUnrestricted /* displayFrame */,
Jorim Jaggif081f062019-10-24 16:24:54 +02001757 displayFrames.mStable /* contentFrame */,
Tiger Huang7c610aa2018-10-27 00:01:01 +08001758 displayFrames.mStable /* visibleFrame */, sTmpRect /* decorFrame */,
Jorim Jaggif081f062019-10-24 16:24:54 +02001759 displayFrames.mStable /* stableFrame */);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001760 // Let the status bar determine its size.
Riddle Hsuc7175762020-01-10 21:03:48 +08001761 mStatusBar.computeFrame(displayFrames);
Tiger Huang4a7835f2019-11-06 00:07:56 +08001762
Tiger Huang7c610aa2018-10-27 00:01:01 +08001763 // For layout, the status bar is always at the top with our fixed height.
1764 displayFrames.mStable.top = displayFrames.mUnrestricted.top
1765 + mStatusBarHeightForRotation[displayFrames.mRotation];
1766 // Make sure the status bar covers the entire cutout height
1767 displayFrames.mStable.top = Math.max(displayFrames.mStable.top,
1768 displayFrames.mDisplayCutoutSafe.top);
1769
Riddle Hsu80f4f7c2020-05-05 23:07:59 +08001770 // Tell the bar controller where the collapsed status bar content is.
1771 sTmpRect.set(windowFrames.mContentFrame);
1772 sTmpRect.intersect(displayFrames.mDisplayCutoutSafe);
1773 sTmpRect.top = windowFrames.mContentFrame.top; // Ignore top display cutout inset
1774 sTmpRect.bottom = displayFrames.mStable.top; // Use collapsed status bar size
1775 if (simulatedContentFrame != null) {
1776 simulatedContentFrame.set(sTmpRect);
1777 } else {
Riddle Hsuc7175762020-01-10 21:03:48 +08001778 mStatusBarController.setContentFrame(sTmpRect);
1779 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001780
Tiger Huang4a7835f2019-11-06 00:07:56 +08001781 boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0
1782 || mDisplayContent.getInsetsPolicy().isTransient(ITYPE_STATUS_BAR);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001783 boolean statusBarTranslucent = (sysui
1784 & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001785
1786 // If the status bar is hidden, we don't want to cause windows behind it to scroll.
1787 if (mStatusBar.isVisibleLw() && !statusBarTransient) {
1788 // Status bar may go away, so the screen area it occupies is available to apps but just
1789 // covering them when the status bar is visible.
1790 final Rect dockFrame = displayFrames.mDock;
1791 dockFrame.top = displayFrames.mStable.top;
1792 displayFrames.mContent.set(dockFrame);
1793 displayFrames.mVoiceContent.set(dockFrame);
1794 displayFrames.mCurrent.set(dockFrame);
1795
1796 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " + String.format(
1797 "dock=%s content=%s cur=%s", dockFrame.toString(),
1798 displayFrames.mContent.toString(), displayFrames.mCurrent.toString()));
1799
Jorim Jaggi4981f152019-03-26 18:58:45 +01001800 if (!statusBarTranslucent && !mStatusBarController.wasRecentlyTranslucent()
1801 && !mStatusBar.isAnimatingLw()) {
1802
Tiger Huang7c610aa2018-10-27 00:01:01 +08001803 // If the opaque status bar is currently requested to be visible, and not in the
1804 // process of animating on or off, then we can tell the app that it is covered by
1805 // it.
1806 displayFrames.mSystem.top = displayFrames.mStable.top;
1807 }
1808 }
1809 return mStatusBarController.checkHiddenLw();
1810 }
1811
1812 private boolean layoutNavigationBar(DisplayFrames displayFrames, int uiMode, boolean navVisible,
1813 boolean navTranslucent, boolean navAllowedHidden,
Riddle Hsu80f4f7c2020-05-05 23:07:59 +08001814 boolean statusBarForcesShowingNavigation, Rect simulatedContentFrame) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001815 if (mNavigationBar == null) {
1816 return false;
1817 }
1818
1819 final Rect navigationFrame = sTmpNavFrame;
1820 boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
1821 // Force the navigation bar to its appropriate place and size. We need to do this directly,
1822 // instead of relying on it to bubble up from the nav bar, because this needs to change
1823 // atomically with screen rotations.
1824 final int rotation = displayFrames.mRotation;
1825 final int displayHeight = displayFrames.mDisplayHeight;
1826 final int displayWidth = displayFrames.mDisplayWidth;
1827 final Rect dockFrame = displayFrames.mDock;
Riddle Hsuc7175762020-01-10 21:03:48 +08001828 final int navBarPosition = navigationBarPosition(displayWidth, displayHeight, rotation);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001829
1830 final Rect cutoutSafeUnrestricted = sTmpRect;
1831 cutoutSafeUnrestricted.set(displayFrames.mUnrestricted);
1832 cutoutSafeUnrestricted.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
1833
Riddle Hsuc7175762020-01-10 21:03:48 +08001834 if (navBarPosition == NAV_BAR_BOTTOM) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001835 // It's a system nav bar or a portrait screen; nav bar goes on bottom.
Tiger Huang7c610aa2018-10-27 00:01:01 +08001836 final int topNavBar = cutoutSafeUnrestricted.bottom
Matthew Nga7f24bc2019-04-09 17:06:41 -07001837 - getNavigationBarFrameHeight(rotation, uiMode);
Sunny Goyal6f17adc2020-06-17 13:36:56 -07001838 final int top = mNavButtonForcedVisible
1839 ? topNavBar
1840 : cutoutSafeUnrestricted.bottom - getNavigationBarHeight(rotation, uiMode);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001841 navigationFrame.set(0, topNavBar, displayWidth, displayFrames.mUnrestricted.bottom);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001842 displayFrames.mStable.bottom = displayFrames.mStableFullscreen.bottom = top;
1843 if (transientNavBarShowing) {
1844 mNavigationBarController.setBarShowingLw(true);
1845 } else if (navVisible) {
1846 mNavigationBarController.setBarShowingLw(true);
Jorim Jaggif081f062019-10-24 16:24:54 +02001847 dockFrame.bottom = displayFrames.mRestricted.bottom = top;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001848 } else {
1849 // We currently want to hide the navigation UI - unless we expanded the status bar.
1850 mNavigationBarController.setBarShowingLw(statusBarForcesShowingNavigation);
1851 }
1852 if (navVisible && !navTranslucent && !navAllowedHidden
1853 && !mNavigationBar.isAnimatingLw()
1854 && !mNavigationBarController.wasRecentlyTranslucent()) {
1855 // If the opaque nav bar is currently requested to be visible and not in the process
1856 // of animating on or off, then we can tell the app that it is covered by it.
1857 displayFrames.mSystem.bottom = top;
1858 }
Riddle Hsuc7175762020-01-10 21:03:48 +08001859 } else if (navBarPosition == NAV_BAR_RIGHT) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001860 // Landscape screen; nav bar goes to the right.
1861 final int left = cutoutSafeUnrestricted.right
1862 - getNavigationBarWidth(rotation, uiMode);
Matthew Nga7f24bc2019-04-09 17:06:41 -07001863 navigationFrame.set(left, 0, displayFrames.mUnrestricted.right, displayHeight);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001864 displayFrames.mStable.right = displayFrames.mStableFullscreen.right = left;
1865 if (transientNavBarShowing) {
1866 mNavigationBarController.setBarShowingLw(true);
1867 } else if (navVisible) {
1868 mNavigationBarController.setBarShowingLw(true);
Jorim Jaggif081f062019-10-24 16:24:54 +02001869 dockFrame.right = displayFrames.mRestricted.right = left;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001870 } else {
1871 // We currently want to hide the navigation UI - unless we expanded the status bar.
1872 mNavigationBarController.setBarShowingLw(statusBarForcesShowingNavigation);
1873 }
1874 if (navVisible && !navTranslucent && !navAllowedHidden
1875 && !mNavigationBar.isAnimatingLw()
1876 && !mNavigationBarController.wasRecentlyTranslucent()) {
1877 // If the nav bar is currently requested to be visible, and not in the process of
1878 // animating on or off, then we can tell the app that it is covered by it.
1879 displayFrames.mSystem.right = left;
1880 }
Riddle Hsuc7175762020-01-10 21:03:48 +08001881 } else if (navBarPosition == NAV_BAR_LEFT) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001882 // Seascape screen; nav bar goes to the left.
1883 final int right = cutoutSafeUnrestricted.left
1884 + getNavigationBarWidth(rotation, uiMode);
Matthew Nga7f24bc2019-04-09 17:06:41 -07001885 navigationFrame.set(displayFrames.mUnrestricted.left, 0, right, displayHeight);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001886 displayFrames.mStable.left = displayFrames.mStableFullscreen.left = right;
1887 if (transientNavBarShowing) {
1888 mNavigationBarController.setBarShowingLw(true);
1889 } else if (navVisible) {
1890 mNavigationBarController.setBarShowingLw(true);
Jorim Jaggif081f062019-10-24 16:24:54 +02001891 dockFrame.left = displayFrames.mRestricted.left = right;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001892 } else {
1893 // We currently want to hide the navigation UI - unless we expanded the status bar.
1894 mNavigationBarController.setBarShowingLw(statusBarForcesShowingNavigation);
1895 }
1896 if (navVisible && !navTranslucent && !navAllowedHidden
1897 && !mNavigationBar.isAnimatingLw()
1898 && !mNavigationBarController.wasRecentlyTranslucent()) {
1899 // If the nav bar is currently requested to be visible, and not in the process of
1900 // animating on or off, then we can tell the app that it is covered by it.
1901 displayFrames.mSystem.left = right;
1902 }
1903 }
1904
1905 // Make sure the content and current rectangles are updated to account for the restrictions
1906 // from the navigation bar.
1907 displayFrames.mCurrent.set(dockFrame);
1908 displayFrames.mVoiceContent.set(dockFrame);
1909 displayFrames.mContent.set(dockFrame);
1910 // And compute the final frame.
1911 sTmpRect.setEmpty();
Riddle Hsuc7175762020-01-10 21:03:48 +08001912 final WindowFrames windowFrames = mNavigationBar.getLayoutingWindowFrames();
1913 windowFrames.setFrames(navigationFrame /* parentFrame */,
Jorim Jaggif081f062019-10-24 16:24:54 +02001914 navigationFrame /* displayFrame */,
Tiger Huang7c610aa2018-10-27 00:01:01 +08001915 displayFrames.mDisplayCutoutSafe /* contentFrame */,
1916 navigationFrame /* visibleFrame */, sTmpRect /* decorFrame */,
Jorim Jaggif081f062019-10-24 16:24:54 +02001917 navigationFrame /* stableFrame */);
Riddle Hsuc7175762020-01-10 21:03:48 +08001918 mNavigationBar.computeFrame(displayFrames);
Riddle Hsu80f4f7c2020-05-05 23:07:59 +08001919 if (simulatedContentFrame != null) {
1920 simulatedContentFrame.set(windowFrames.mContentFrame);
1921 } else {
Riddle Hsuc7175762020-01-10 21:03:48 +08001922 mNavigationBarPosition = navBarPosition;
1923 mNavigationBarController.setContentFrame(windowFrames.mContentFrame);
Tiger Huang4a7835f2019-11-06 00:07:56 +08001924 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001925
1926 if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + navigationFrame);
1927 return mNavigationBarController.checkHiddenLw();
1928 }
1929
1930 private void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
Jorim Jaggif081f062019-10-24 16:24:54 +02001931 boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf,
Tiger Huang7c610aa2018-10-27 00:01:01 +08001932 DisplayFrames displayFrames) {
1933 if (!win.isInputMethodTarget() && attached.isInputMethodTarget()) {
1934 // Here's a special case: if the child window is not the 'dock window'
1935 // or input method target, and the window it is attached to is below
1936 // the dock window, then the frames we computed for the window it is
1937 // attached to can not be used because the dock is effectively part
1938 // of the underlying window and the attached window is floating on top
1939 // of the whole thing. So, we ignore the attached window and explicitly
1940 // compute the frames that would be appropriate without the dock.
1941 vf.set(displayFrames.mDock);
1942 cf.set(displayFrames.mDock);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001943 df.set(displayFrames.mDock);
1944 } else {
Jorim Jaggid6490572019-04-16 14:57:56 +02001945
Jorim Jaggif081f062019-10-24 16:24:54 +02001946 // In case we forced the window to draw behind the navigation bar, restrict df to
1947 // DF.Restricted to simulate old compat behavior.
Jorim Jaggia72b4cc2019-04-16 15:38:49 +02001948 Rect parentDisplayFrame = attached.getDisplayFrameLw();
Jorim Jaggid6490572019-04-16 14:57:56 +02001949 final WindowManager.LayoutParams attachedAttrs = attached.mAttrs;
1950 if ((attachedAttrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0
1951 && (attachedAttrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
1952 && (attachedAttrs.systemUiVisibility
1953 & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0) {
Jorim Jaggia72b4cc2019-04-16 15:38:49 +02001954 parentDisplayFrame = new Rect(parentDisplayFrame);
Jorim Jaggif081f062019-10-24 16:24:54 +02001955 parentDisplayFrame.intersect(displayFrames.mRestricted);
Jorim Jaggid6490572019-04-16 14:57:56 +02001956 }
1957
Tiger Huang7c610aa2018-10-27 00:01:01 +08001958 // The effective display frame of the attached window depends on whether it is taking
1959 // care of insetting its content. If not, we need to use the parent's content frame so
1960 // that the entire window is positioned within that content. Otherwise we can use the
Jorim Jaggif081f062019-10-24 16:24:54 +02001961 // parent display frame and let the attached window take care of positioning its content
Tiger Huang7c610aa2018-10-27 00:01:01 +08001962 // appropriately.
1963 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
1964 // Set the content frame of the attached window to the parent's decor frame
1965 // (same as content frame when IME isn't present) if specifically requested by
1966 // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
1967 // Otherwise, use the overscan frame.
1968 cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
Jorim Jaggif081f062019-10-24 16:24:54 +02001969 ? attached.getContentFrameLw() : parentDisplayFrame);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001970 } else {
1971 // If the window is resizing, then we want to base the content frame on our attached
1972 // content frame to resize...however, things can be tricky if the attached window is
1973 // NOT in resize mode, in which case its content frame will be larger.
1974 // Ungh. So to deal with that, make sure the content frame we end up using is not
1975 // covering the IM dock.
1976 cf.set(attached.getContentFrameLw());
1977 if (attached.isVoiceInteraction()) {
1978 cf.intersectUnchecked(displayFrames.mVoiceContent);
1979 } else if (win.isInputMethodTarget() || attached.isInputMethodTarget()) {
1980 cf.intersectUnchecked(displayFrames.mContent);
1981 }
1982 }
Jorim Jaggid6490572019-04-16 14:57:56 +02001983 df.set(insetDecors ? parentDisplayFrame : cf);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001984 vf.set(attached.getVisibleFrameLw());
1985 }
1986 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached window should be
1987 // positioned relative to its parent or the entire screen.
1988 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 ? attached.getFrameLw() : df);
1989 }
1990
1991 private void applyStableConstraints(int sysui, int fl, Rect r, DisplayFrames displayFrames) {
1992 if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) == 0) {
1993 return;
1994 }
1995 // If app is requesting a stable layout, don't let the content insets go below the stable
1996 // values.
1997 if ((fl & FLAG_FULLSCREEN) != 0) {
1998 r.intersectUnchecked(displayFrames.mStableFullscreen);
1999 } else {
2000 r.intersectUnchecked(displayFrames.mStable);
2001 }
2002 }
2003
2004 private boolean canReceiveInput(WindowState win) {
2005 boolean notFocusable =
2006 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
2007 boolean altFocusableIm =
2008 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
2009 boolean notFocusableForIm = notFocusable ^ altFocusableIm;
2010 return !notFocusableForIm;
2011 }
2012
2013 /**
2014 * Called for each window attached to the window manager as layout is proceeding. The
2015 * implementation of this function must take care of setting the window's frame, either here or
2016 * in finishLayout().
2017 *
2018 * @param win The window being positioned.
2019 * @param attached For sub-windows, the window it is attached to; this
2020 * window will already have had layoutWindow() called on it
2021 * so you can use its Rect. Otherwise null.
2022 * @param displayFrames The display frames.
2023 */
2024 public void layoutWindowLw(WindowState win, WindowState attached, DisplayFrames displayFrames) {
2025 // We've already done the navigation bar, status bar, and all screen decor windows. If the
2026 // status bar can receive input, we need to layout it again to accommodate for the IME
2027 // window.
2028 if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar
2029 || mScreenDecorWindows.contains(win)) {
2030 return;
2031 }
2032 final WindowManager.LayoutParams attrs = win.getAttrs();
Tiger Huang7c610aa2018-10-27 00:01:01 +08002033
2034 final int type = attrs.type;
2035 final int fl = PolicyControl.getWindowFlags(win, attrs);
2036 final int pfl = attrs.privateFlags;
2037 final int sim = attrs.softInputMode;
2038 final int requestedSysUiFl = PolicyControl.getSystemUiVisibility(null, attrs);
2039 final int sysUiFl = requestedSysUiFl | getImpliedSysUiFlagsForLayout(attrs);
2040
Riddle Hsu6f548e92020-01-13 13:34:09 +08002041 displayFrames = win.getDisplayFrames(displayFrames);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002042 final WindowFrames windowFrames = win.getWindowFrames();
2043
Tiger Huang7c610aa2018-10-27 00:01:01 +08002044 sTmpLastParentFrame.set(windowFrames.mParentFrame);
2045 final Rect pf = windowFrames.mParentFrame;
2046 final Rect df = windowFrames.mDisplayFrame;
Tiger Huang7c610aa2018-10-27 00:01:01 +08002047 final Rect cf = windowFrames.mContentFrame;
2048 final Rect vf = windowFrames.mVisibleFrame;
2049 final Rect dcf = windowFrames.mDecorFrame;
2050 final Rect sf = windowFrames.mStableFrame;
2051 dcf.setEmpty();
2052 windowFrames.setParentFrameWasClippedByDisplayCutout(false);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002053
2054 final boolean hasNavBar = hasNavigationBar() && mNavigationBar != null
2055 && mNavigationBar.isVisibleLw();
2056
2057 final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
2058
Tiger Huang7c610aa2018-10-27 00:01:01 +08002059 final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) == FLAG_LAYOUT_IN_SCREEN;
2060 final boolean layoutInsetDecor = (fl & FLAG_LAYOUT_INSET_DECOR) == FLAG_LAYOUT_INSET_DECOR;
2061
2062 sf.set(displayFrames.mStable);
2063
Tiger Huang4a7835f2019-11-06 00:07:56 +08002064 if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
Tiger Huang52724442020-01-20 21:38:42 +08002065 final @InsetsType int typesToFit = attrs.getFitInsetsTypes();
2066 final @InsetsSide int sidesToFit = attrs.getFitInsetsSides();
Tiger Huang4a7835f2019-11-06 00:07:56 +08002067 final ArraySet<Integer> types = InsetsState.toInternalType(typesToFit);
2068 final Rect dfu = displayFrames.mUnrestricted;
2069 Insets insets = Insets.of(0, 0, 0, 0);
2070 for (int i = types.size() - 1; i >= 0; i--) {
Tiger Huangeb5a5922020-05-06 22:54:28 +08002071 final InsetsSource source = mDisplayContent.getInsetsPolicy()
2072 .getInsetsForDispatch(win).peekSource(types.valueAt(i));
2073 if (source == null) {
2074 continue;
2075 }
2076 insets = Insets.max(insets, source.calculateInsets(
2077 dfu, attrs.isFitInsetsIgnoringVisibility()));
Tiger Huang4a7835f2019-11-06 00:07:56 +08002078 }
2079 final int left = (sidesToFit & Side.LEFT) != 0 ? insets.left : 0;
2080 final int top = (sidesToFit & Side.TOP) != 0 ? insets.top : 0;
2081 final int right = (sidesToFit & Side.RIGHT) != 0 ? insets.right : 0;
2082 final int bottom = (sidesToFit & Side.BOTTOM) != 0 ? insets.bottom : 0;
2083 df.set(left, top, dfu.right - right, dfu.bottom - bottom);
2084 if (attached == null) {
2085 pf.set(df);
2086 vf.set(adjust != SOFT_INPUT_ADJUST_NOTHING
2087 ? displayFrames.mCurrent : displayFrames.mDock);
2088 } else {
2089 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 ? attached.getFrameLw() : df);
2090 vf.set(attached.getVisibleFrameLw());
2091 }
2092 cf.set(adjust != SOFT_INPUT_ADJUST_RESIZE
2093 ? displayFrames.mDock : displayFrames.mContent);
2094 dcf.set(displayFrames.mSystem);
2095 } else if (type == TYPE_INPUT_METHOD) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002096 vf.set(displayFrames.mDock);
2097 cf.set(displayFrames.mDock);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002098 df.set(displayFrames.mDock);
Tiger Huang4a7835f2019-11-06 00:07:56 +08002099 pf.set(displayFrames.mDock);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002100 // IM dock windows layout below the nav bar...
Jorim Jaggif081f062019-10-24 16:24:54 +02002101 pf.bottom = df.bottom = displayFrames.mUnrestricted.bottom;
Tiger Huang7c610aa2018-10-27 00:01:01 +08002102 // ...with content insets above the nav bar
2103 cf.bottom = vf.bottom = displayFrames.mStable.bottom;
2104 if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
2105 // The status bar forces the navigation bar while it's visible. Make sure the IME
2106 // avoids the navigation bar in that case.
2107 if (mNavigationBarPosition == NAV_BAR_RIGHT) {
Jorim Jaggif081f062019-10-24 16:24:54 +02002108 pf.right = df.right = cf.right = vf.right =
Tiger Huang7c610aa2018-10-27 00:01:01 +08002109 displayFrames.mStable.right;
2110 } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
Jorim Jaggif081f062019-10-24 16:24:54 +02002111 pf.left = df.left = cf.left = vf.left = displayFrames.mStable.left;
Tiger Huang7c610aa2018-10-27 00:01:01 +08002112 }
2113 }
2114
Matthew Nga7f24bc2019-04-09 17:06:41 -07002115 // In case the navigation bar is on the bottom, we use the frame height instead of the
2116 // regular height for the insets we send to the IME as we need some space to show
2117 // additional buttons in SystemUI when the IME is up.
2118 if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
2119 final int rotation = displayFrames.mRotation;
2120 final int uimode = mService.mPolicy.getUiMode();
2121 final int navHeightOffset = getNavigationBarFrameHeight(rotation, uimode)
2122 - getNavigationBarHeight(rotation, uimode);
2123 if (navHeightOffset > 0) {
2124 cf.bottom -= navHeightOffset;
2125 sf.bottom -= navHeightOffset;
2126 vf.bottom -= navHeightOffset;
2127 dcf.bottom -= navHeightOffset;
2128 }
2129 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002130
2131 // IM dock windows always go to the bottom of the screen.
2132 attrs.gravity = Gravity.BOTTOM;
2133 } else if (type == TYPE_VOICE_INTERACTION) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002134 df.set(displayFrames.mUnrestricted);
2135 pf.set(displayFrames.mUnrestricted);
2136 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
2137 cf.set(displayFrames.mDock);
2138 } else {
2139 cf.set(displayFrames.mContent);
2140 }
2141 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
2142 vf.set(displayFrames.mCurrent);
2143 } else {
2144 vf.set(cf);
2145 }
2146 } else if (type == TYPE_WALLPAPER) {
Jorim Jaggif081f062019-10-24 16:24:54 +02002147 layoutWallpaper(displayFrames, pf, df, cf);
Jorim Jaggif2ce4fa2020-01-21 22:32:37 +01002148 } else if (win == mStatusBar || type == TYPE_NOTIFICATION_SHADE) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002149 df.set(displayFrames.mUnrestricted);
2150 pf.set(displayFrames.mUnrestricted);
2151 cf.set(displayFrames.mStable);
2152 vf.set(displayFrames.mStable);
2153
2154 if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
Tiger Huang7fe7f682019-10-26 01:11:23 +08002155 // cf.bottom should not be below the stable bottom, or the content might be obscured
2156 // by the navigation bar.
2157 if (cf.bottom > displayFrames.mContent.bottom) {
2158 cf.bottom = displayFrames.mContent.bottom;
2159 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002160 } else {
Tiger Huang7fe7f682019-10-26 01:11:23 +08002161 if (cf.bottom > displayFrames.mDock.bottom) {
2162 cf.bottom = displayFrames.mDock.bottom;
2163 }
2164 if (vf.bottom > displayFrames.mContent.bottom) {
2165 vf.bottom = displayFrames.mContent.bottom;
2166 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002167 }
2168 } else {
2169 dcf.set(displayFrames.mSystem);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002170 final boolean isAppWindow =
2171 type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW;
2172 final boolean topAtRest =
2173 win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
Jorim Jaggia2e648e2019-10-25 15:06:53 +02002174 if (isAppWindow && !topAtRest) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002175 if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
2176 && (fl & FLAG_FULLSCREEN) == 0
2177 && (fl & FLAG_TRANSLUCENT_STATUS) == 0
2178 && (fl & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
Jorim Jaggia6aabac2019-03-11 14:23:16 -07002179 && (pfl & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) == 0) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002180 // Ensure policy decor includes status bar
2181 dcf.top = displayFrames.mStable.top;
2182 }
2183 if ((fl & FLAG_TRANSLUCENT_NAVIGATION) == 0
2184 && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
Jorim Jaggia6aabac2019-03-11 14:23:16 -07002185 && (fl & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
2186 && (pfl & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) == 0) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002187 // Ensure policy decor includes navigation bar
2188 dcf.bottom = displayFrames.mStable.bottom;
2189 dcf.right = displayFrames.mStable.right;
2190 }
2191 }
2192
2193 if (layoutInScreen && layoutInsetDecor) {
2194 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
2195 + "): IN_SCREEN, INSET_DECOR");
2196 // This is the case for a normal activity window: we want it to cover all of the
2197 // screen space, and it can take care of moving its contents to account for screen
2198 // decorations that intrude into that space.
2199 if (attached != null) {
2200 // If this window is attached to another, our display
2201 // frame is the same as the one we are attached to.
Jorim Jaggif081f062019-10-24 16:24:54 +02002202 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, cf, vf,
Tiger Huang7c610aa2018-10-27 00:01:01 +08002203 displayFrames);
2204 } else {
Heemin Seog2cf45dd2020-02-24 15:43:29 -08002205 if (type == TYPE_STATUS_BAR_ADDITIONAL || type == TYPE_STATUS_BAR_SUB_PANEL) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002206 // Status bar panels are the only windows who can go on top of the status
2207 // bar. They are protected by the STATUS_BAR_SERVICE permission, so they
2208 // have the same privileges as the status bar itself.
2209 //
2210 // However, they should still dodge the navigation bar if it exists.
2211
Jorim Jaggif081f062019-10-24 16:24:54 +02002212 pf.left = df.left = hasNavBar
Tiger Huang7c610aa2018-10-27 00:01:01 +08002213 ? displayFrames.mDock.left : displayFrames.mUnrestricted.left;
Jorim Jaggif081f062019-10-24 16:24:54 +02002214 pf.top = df.top = displayFrames.mUnrestricted.top;
2215 pf.right = df.right = hasNavBar
Tiger Huang7c610aa2018-10-27 00:01:01 +08002216 ? displayFrames.mRestricted.right
2217 : displayFrames.mUnrestricted.right;
Jorim Jaggif081f062019-10-24 16:24:54 +02002218 pf.bottom = df.bottom = hasNavBar
Tiger Huang7c610aa2018-10-27 00:01:01 +08002219 ? displayFrames.mRestricted.bottom
2220 : displayFrames.mUnrestricted.bottom;
2221
2222 if (DEBUG_LAYOUT) Slog.v(TAG, "Laying out status bar window: " + pf);
Jorim Jaggid6490572019-04-16 14:57:56 +02002223 } else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
Tiger Huang7c610aa2018-10-27 00:01:01 +08002224 && (type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW
Charles Chen64172bb2019-04-22 17:30:29 +08002225 || type == TYPE_VOLUME_OVERLAY
2226 || type == TYPE_KEYGUARD_DIALOG)) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002227 // Asking for layout as if the nav bar is hidden, lets the application
2228 // extend into the unrestricted overscan screen area. We only do this for
2229 // application windows and certain system windows to ensure no window that
2230 // can be above the nav bar can do this.
Jorim Jaggif081f062019-10-24 16:24:54 +02002231 df.set(displayFrames.mUnrestricted);
2232 pf.set(displayFrames.mUnrestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002233 } else {
Jorim Jaggif081f062019-10-24 16:24:54 +02002234 df.set(displayFrames.mRestricted);
2235 pf.set(displayFrames.mRestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002236 }
2237
2238 if ((fl & FLAG_FULLSCREEN) == 0) {
2239 if (win.isVoiceInteraction()) {
2240 cf.set(displayFrames.mVoiceContent);
2241 } else {
Jorim Jaggi648e5882019-01-24 13:24:02 +01002242 // IME Insets are handled on the client for ADJUST_RESIZE in the new
2243 // insets world
2244 if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_NONE
2245 || adjust != SOFT_INPUT_ADJUST_RESIZE) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002246 cf.set(displayFrames.mDock);
2247 } else {
2248 cf.set(displayFrames.mContent);
2249 }
2250 }
2251 } else {
2252 // Full screen windows are always given a layout that is as if the status
2253 // bar and other transient decors are gone. This is to avoid bad states when
2254 // moving from a window that is not hiding the status bar to one that is.
2255 cf.set(displayFrames.mRestricted);
2256 }
2257 applyStableConstraints(sysUiFl, fl, cf, displayFrames);
Jorim Jaggi4e04eb22020-01-09 16:42:14 +01002258 if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE
2259 && adjust != SOFT_INPUT_ADJUST_NOTHING) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002260 vf.set(displayFrames.mCurrent);
2261 } else {
2262 vf.set(cf);
2263 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002264 }
2265 } else if (layoutInScreen || (sysUiFl
Tiger Huang4a7835f2019-11-06 00:07:56 +08002266 & (SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
Jorim Jaggid6490572019-04-16 14:57:56 +02002267 | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002268 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
2269 + "): IN_SCREEN");
2270 // A window that has requested to fill the entire screen just
2271 // gets everything, period.
Heemin Seog2cf45dd2020-02-24 15:43:29 -08002272 if (type == TYPE_STATUS_BAR_ADDITIONAL || type == TYPE_STATUS_BAR_SUB_PANEL) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002273 cf.set(displayFrames.mUnrestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002274 df.set(displayFrames.mUnrestricted);
2275 pf.set(displayFrames.mUnrestricted);
2276 if (hasNavBar) {
Jorim Jaggif081f062019-10-24 16:24:54 +02002277 pf.left = df.left = cf.left = displayFrames.mDock.left;
2278 pf.right = df.right = cf.right = displayFrames.mRestricted.right;
2279 pf.bottom = df.bottom = cf.bottom =
Tiger Huang7c610aa2018-10-27 00:01:01 +08002280 displayFrames.mRestricted.bottom;
2281 }
2282 if (DEBUG_LAYOUT) Slog.v(TAG, "Laying out IN_SCREEN status bar window: " + pf);
2283 } else if (type == TYPE_NAVIGATION_BAR || type == TYPE_NAVIGATION_BAR_PANEL) {
2284 // The navigation bar has Real Ultimate Power.
Tiger Huang7c610aa2018-10-27 00:01:01 +08002285 df.set(displayFrames.mUnrestricted);
2286 pf.set(displayFrames.mUnrestricted);
2287 if (DEBUG_LAYOUT) Slog.v(TAG, "Laying out navigation bar window: " + pf);
2288 } else if ((type == TYPE_SECURE_SYSTEM_OVERLAY || type == TYPE_SCREENSHOT)
2289 && ((fl & FLAG_FULLSCREEN) != 0)) {
2290 // Fullscreen secure system overlays get what they ask for. Screenshot region
2291 // selection overlay should also expand to full screen.
Jorim Jaggif081f062019-10-24 16:24:54 +02002292 cf.set(displayFrames.mUnrestricted);
2293 df.set(displayFrames.mUnrestricted);
2294 pf.set(displayFrames.mUnrestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002295 } else if (type == TYPE_BOOT_PROGRESS) {
2296 // Boot progress screen always covers entire display.
Jorim Jaggif081f062019-10-24 16:24:54 +02002297 cf.set(displayFrames.mUnrestricted);
2298 df.set(displayFrames.mUnrestricted);
2299 pf.set(displayFrames.mUnrestricted);
Jorim Jaggid6490572019-04-16 14:57:56 +02002300 } else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
wilsonshihe8321942019-10-18 18:39:46 +08002301 && (type == TYPE_NOTIFICATION_SHADE
Tiger Huang7c610aa2018-10-27 00:01:01 +08002302 || type == TYPE_TOAST
2303 || type == TYPE_DOCK_DIVIDER
2304 || type == TYPE_VOICE_INTERACTION_STARTING
2305 || (type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW))) {
2306 // Asking for layout as if the nav bar is hidden, lets the
2307 // application extend into the unrestricted screen area. We
2308 // only do this for application windows (or toasts) to ensure no window that
2309 // can be above the nav bar can do this.
2310 // XXX This assumes that an app asking for this will also
2311 // ask for layout in only content. We can't currently figure out
2312 // what the screen would be if only laying out to hide the nav bar.
2313 cf.set(displayFrames.mUnrestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002314 df.set(displayFrames.mUnrestricted);
2315 pf.set(displayFrames.mUnrestricted);
Tiger Huang4a7835f2019-11-06 00:07:56 +08002316 } else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002317 df.set(displayFrames.mRestricted);
2318 pf.set(displayFrames.mRestricted);
Jorim Jaggi648e5882019-01-24 13:24:02 +01002319
2320 // IME Insets are handled on the client for ADJUST_RESIZE in the new insets
2321 // world
2322 if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_NONE
2323 || adjust != SOFT_INPUT_ADJUST_RESIZE) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002324 cf.set(displayFrames.mDock);
2325 } else {
2326 cf.set(displayFrames.mContent);
2327 }
2328 } else {
2329 cf.set(displayFrames.mRestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002330 df.set(displayFrames.mRestricted);
2331 pf.set(displayFrames.mRestricted);
2332 }
2333
2334 applyStableConstraints(sysUiFl, fl, cf, displayFrames);
2335
Jorim Jaggi4e04eb22020-01-09 16:42:14 +01002336 if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE
2337 && adjust != SOFT_INPUT_ADJUST_NOTHING) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002338 vf.set(displayFrames.mCurrent);
2339 } else {
2340 vf.set(cf);
2341 }
2342 } else if (attached != null) {
2343 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
2344 + "): attached to " + attached);
2345 // A child window should be placed inside of the same visible
2346 // frame that its parent had.
Jorim Jaggif081f062019-10-24 16:24:54 +02002347 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, cf, vf,
Tiger Huang7c610aa2018-10-27 00:01:01 +08002348 displayFrames);
2349 } else {
2350 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
2351 + "): normal window");
2352 // Otherwise, a normal window must be placed inside the content
2353 // of all screen decorations.
Heemin Seog2cf45dd2020-02-24 15:43:29 -08002354 if (type == TYPE_STATUS_BAR_ADDITIONAL) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002355 // Status bar panels can go on
2356 // top of the status bar. They are protected by the STATUS_BAR_SERVICE
2357 // permission, so they have the same privileges as the status bar itself.
2358 cf.set(displayFrames.mRestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002359 df.set(displayFrames.mRestricted);
2360 pf.set(displayFrames.mRestricted);
Vishnu Nair9ccb1d22019-03-20 16:32:44 +00002361 } else if (type == TYPE_TOAST || type == TYPE_SYSTEM_ALERT) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002362 // These dialogs are stable to interim decor changes.
2363 cf.set(displayFrames.mStable);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002364 df.set(displayFrames.mStable);
2365 pf.set(displayFrames.mStable);
2366 } else {
2367 pf.set(displayFrames.mContent);
2368 if (win.isVoiceInteraction()) {
2369 cf.set(displayFrames.mVoiceContent);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002370 df.set(displayFrames.mVoiceContent);
2371 } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
2372 cf.set(displayFrames.mDock);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002373 df.set(displayFrames.mDock);
2374 } else {
2375 cf.set(displayFrames.mContent);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002376 df.set(displayFrames.mContent);
2377 }
Jorim Jaggi4e04eb22020-01-09 16:42:14 +01002378 if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE
2379 && adjust != SOFT_INPUT_ADJUST_NOTHING) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002380 vf.set(displayFrames.mCurrent);
2381 } else {
2382 vf.set(cf);
2383 }
2384 }
2385 }
2386 }
2387
2388 final int cutoutMode = attrs.layoutInDisplayCutoutMode;
2389 final boolean attachedInParent = attached != null && !layoutInScreen;
Tiger Huang4a7835f2019-11-06 00:07:56 +08002390 final boolean requestedFullscreen = (fl & FLAG_FULLSCREEN) != 0
2391 || (requestedSysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0
Jorim Jaggi0dd0cf92019-12-27 15:17:44 +01002392 || (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL
Tiger Huang017d51d2020-05-27 17:58:17 +08002393 && !win.getRequestedInsetsState().getSourceOrDefaultVisibility(
2394 ITYPE_STATUS_BAR));
Tiger Huang7c610aa2018-10-27 00:01:01 +08002395 final boolean requestedHideNavigation =
Tiger Huang4a7835f2019-11-06 00:07:56 +08002396 (requestedSysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
Jorim Jaggi0dd0cf92019-12-27 15:17:44 +01002397 || (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL
Tiger Huang017d51d2020-05-27 17:58:17 +08002398 && !win.getRequestedInsetsState().getSourceOrDefaultVisibility(
2399 ITYPE_NAVIGATION_BAR));
Tiger Huang7c610aa2018-10-27 00:01:01 +08002400
2401 // TYPE_BASE_APPLICATION windows are never considered floating here because they don't get
2402 // cropped / shifted to the displayFrame in WindowState.
2403 final boolean floatingInScreenWindow = !attrs.isFullscreen() && layoutInScreen
2404 && type != TYPE_BASE_APPLICATION;
Tiger Huang7c610aa2018-10-27 00:01:01 +08002405 // Ensure that windows with a DEFAULT or NEVER display cutout mode are laid out in
2406 // the cutout safe zone.
shawnlin465b7de2020-02-11 20:45:35 +08002407 if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002408 final Rect displayCutoutSafeExceptMaybeBars = sTmpDisplayCutoutSafeExceptMaybeBarsRect;
2409 displayCutoutSafeExceptMaybeBars.set(displayFrames.mDisplayCutoutSafe);
shawnlin465b7de2020-02-11 20:45:35 +08002410 if (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES) {
2411 if (displayFrames.mDisplayWidth < displayFrames.mDisplayHeight) {
2412 displayCutoutSafeExceptMaybeBars.top = Integer.MIN_VALUE;
2413 displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
2414 } else {
2415 displayCutoutSafeExceptMaybeBars.left = Integer.MIN_VALUE;
2416 displayCutoutSafeExceptMaybeBars.right = Integer.MAX_VALUE;
2417 }
2418 }
2419
Tiger Huang7c610aa2018-10-27 00:01:01 +08002420 if (layoutInScreen && layoutInsetDecor && !requestedFullscreen
shawnlin465b7de2020-02-11 20:45:35 +08002421 && (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
2422 || cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES)) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002423 // At the top we have the status bar, so apps that are
2424 // LAYOUT_IN_SCREEN | LAYOUT_INSET_DECOR but not FULLSCREEN
2425 // already expect that there's an inset there and we don't need to exclude
2426 // the window from that area.
2427 displayCutoutSafeExceptMaybeBars.top = Integer.MIN_VALUE;
2428 }
2429 if (layoutInScreen && layoutInsetDecor && !requestedHideNavigation
shawnlin465b7de2020-02-11 20:45:35 +08002430 && (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
2431 || cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES)) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002432 // Same for the navigation bar.
2433 switch (mNavigationBarPosition) {
2434 case NAV_BAR_BOTTOM:
2435 displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
2436 break;
2437 case NAV_BAR_RIGHT:
2438 displayCutoutSafeExceptMaybeBars.right = Integer.MAX_VALUE;
2439 break;
2440 case NAV_BAR_LEFT:
2441 displayCutoutSafeExceptMaybeBars.left = Integer.MIN_VALUE;
2442 break;
2443 }
2444 }
2445 if (type == TYPE_INPUT_METHOD && mNavigationBarPosition == NAV_BAR_BOTTOM) {
2446 // The IME can always extend under the bottom cutout if the navbar is there.
2447 displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
2448 }
2449 // Windows that are attached to a parent and laid out in said parent already avoid
2450 // the cutout according to that parent and don't need to be further constrained.
2451 // Floating IN_SCREEN windows get what they ask for and lay out in the full screen.
2452 // They will later be cropped or shifted using the displayFrame in WindowState,
2453 // which prevents overlap with the DisplayCutout.
2454 if (!attachedInParent && !floatingInScreenWindow) {
2455 sTmpRect.set(pf);
2456 pf.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
2457 windowFrames.setParentFrameWasClippedByDisplayCutout(!sTmpRect.equals(pf));
2458 }
2459 // Make sure that NO_LIMITS windows clipped to the display don't extend under the
2460 // cutout.
2461 df.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
2462 }
2463
2464 // Content should never appear in the cutout.
2465 cf.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
2466
2467 // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
2468 // Also, we don't allow windows in multi-window mode to extend out of the screen.
2469 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && type != TYPE_SYSTEM_ERROR
Evan Rosky4fb1e912019-03-06 13:54:43 -08002470 && !win.inMultiWindowMode()) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002471 df.left = df.top = -10000;
2472 df.right = df.bottom = 10000;
2473 if (type != TYPE_WALLPAPER) {
Jorim Jaggif081f062019-10-24 16:24:54 +02002474 cf.left = cf.top = vf.left = vf.top = -10000;
2475 cf.right = cf.bottom = vf.right = vf.bottom = 10000;
Tiger Huang7c610aa2018-10-27 00:01:01 +08002476 }
2477 }
2478
2479 if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
2480 + ": sim=#" + Integer.toHexString(sim)
2481 + " attach=" + attached + " type=" + type
2482 + String.format(" flags=0x%08x", fl)
2483 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
Tiger Huang7c610aa2018-10-27 00:01:01 +08002484 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
2485 + " dcf=" + dcf.toShortString()
Jorim Jaggif081f062019-10-24 16:24:54 +02002486 + " sf=" + sf.toShortString());
Tiger Huang7c610aa2018-10-27 00:01:01 +08002487
2488 if (!sTmpLastParentFrame.equals(pf)) {
2489 windowFrames.setContentChanged(true);
2490 }
2491
Riddle Hsuc7175762020-01-10 21:03:48 +08002492 win.computeFrame(displayFrames);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002493 // Dock windows carve out the bottom of the screen, so normal windows
2494 // can't appear underneath them.
2495 if (type == TYPE_INPUT_METHOD && win.isVisibleLw()
2496 && !win.getGivenInsetsPendingLw()) {
2497 offsetInputMethodWindowLw(win, displayFrames);
2498 }
2499 if (type == TYPE_VOICE_INTERACTION && win.isVisibleLw()
2500 && !win.getGivenInsetsPendingLw()) {
2501 offsetVoiceInputWindowLw(win, displayFrames);
2502 }
2503 }
2504
Jorim Jaggif081f062019-10-24 16:24:54 +02002505 private void layoutWallpaper(DisplayFrames displayFrames, Rect pf, Rect df, Rect cf) {
2506 // The wallpaper has Real Ultimate Power
2507 df.set(displayFrames.mUnrestricted);
2508 pf.set(displayFrames.mUnrestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002509 cf.set(displayFrames.mUnrestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002510 }
2511
2512 private void offsetInputMethodWindowLw(WindowState win, DisplayFrames displayFrames) {
Winson Chung913690d2019-11-14 16:06:01 -08002513 final int rotation = displayFrames.mRotation;
2514 final int navBarPosition = navigationBarPosition(displayFrames.mDisplayWidth,
2515 displayFrames.mDisplayHeight, rotation);
2516
Tiger Huang7c610aa2018-10-27 00:01:01 +08002517 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
2518 top += win.getGivenContentInsetsLw().top;
2519 displayFrames.mContent.bottom = Math.min(displayFrames.mContent.bottom, top);
Winson Chung913690d2019-11-14 16:06:01 -08002520 if (navBarPosition == NAV_BAR_BOTTOM) {
2521 // Always account for the nav bar frame height on the bottom since in all navigation
2522 // modes we make room to show the dismiss-ime button, even if the IME does not report
2523 // insets (ie. when floating)
2524 final int uimode = mService.mPolicy.getUiMode();
2525 final int navFrameHeight = getNavigationBarFrameHeight(rotation, uimode);
2526 displayFrames.mContent.bottom = Math.min(displayFrames.mContent.bottom,
2527 displayFrames.mUnrestricted.bottom - navFrameHeight);
2528 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002529 displayFrames.mVoiceContent.bottom = Math.min(displayFrames.mVoiceContent.bottom, top);
2530 top = win.getVisibleFrameLw().top;
2531 top += win.getGivenVisibleInsetsLw().top;
2532 displayFrames.mCurrent.bottom = Math.min(displayFrames.mCurrent.bottom, top);
2533 if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
2534 + displayFrames.mDock.bottom + " mContentBottom="
2535 + displayFrames.mContent.bottom + " mCurBottom=" + displayFrames.mCurrent.bottom);
2536 }
2537
2538 private void offsetVoiceInputWindowLw(WindowState win, DisplayFrames displayFrames) {
2539 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
2540 top += win.getGivenContentInsetsLw().top;
2541 displayFrames.mVoiceContent.bottom = Math.min(displayFrames.mVoiceContent.bottom, top);
2542 }
2543
Riddle Hsuccf09402019-08-13 00:33:06 +08002544 WindowState getTopFullscreenOpaqueWindow() {
2545 return mTopFullscreenOpaqueWindowState;
2546 }
2547
2548 boolean isTopLayoutFullscreen() {
2549 return mTopIsFullscreen;
2550 }
2551
Tiger Huang7c610aa2018-10-27 00:01:01 +08002552 /**
2553 * Called following layout of all windows before each window has policy applied.
2554 */
2555 public void beginPostLayoutPolicyLw() {
2556 mTopFullscreenOpaqueWindowState = null;
2557 mTopFullscreenOpaqueOrDimmingWindowState = null;
2558 mTopDockedOpaqueWindowState = null;
2559 mTopDockedOpaqueOrDimmingWindowState = null;
2560 mForceStatusBar = false;
Tiger Huang7c610aa2018-10-27 00:01:01 +08002561 mForcingShowNavBar = false;
2562 mForcingShowNavBarLayer = -1;
2563
2564 mAllowLockscreenWhenOn = false;
2565 mShowingDream = false;
HEO SEUNG22d3ec22019-05-30 20:28:53 +09002566 mIsFreeformWindowOverlappingWithNavBar = false;
Tiger Huang7c610aa2018-10-27 00:01:01 +08002567 }
2568
2569 /**
2570 * Called following layout of all window to apply policy to each window.
2571 *
2572 * @param win The window being positioned.
2573 * @param attrs The LayoutParams of the window.
2574 * @param attached For sub-windows, the window it is attached to. Otherwise null.
2575 */
2576 public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
2577 WindowState attached, WindowState imeTarget) {
2578 final boolean affectsSystemUi = win.canAffectSystemUiFlags();
2579 if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": affectsSystemUi=" + affectsSystemUi);
2580 mService.mPolicy.applyKeyguardPolicyLw(win, imeTarget);
2581 final int fl = PolicyControl.getWindowFlags(win, attrs);
2582 if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi
2583 && attrs.type == TYPE_INPUT_METHOD) {
2584 mForcingShowNavBar = true;
2585 mForcingShowNavBarLayer = win.getSurfaceLayer();
2586 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002587
2588 boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
2589 && attrs.type < FIRST_SYSTEM_WINDOW;
2590 final int windowingMode = win.getWindowingMode();
2591 final boolean inFullScreenOrSplitScreenSecondaryWindowingMode =
2592 windowingMode == WINDOWING_MODE_FULLSCREEN
2593 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
2594 if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi) {
2595 if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
2596 mForceStatusBar = true;
2597 }
Galia Peycheva70b55712020-03-16 18:31:34 +01002598 if (win.isDreamWindow()) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002599 // If the lockscreen was showing when the dream started then wait
2600 // for the dream to draw before hiding the lockscreen.
2601 if (!mDreamingLockscreen
2602 || (win.isVisibleLw() && win.hasDrawnLw())) {
2603 mShowingDream = true;
2604 appWindow = true;
2605 }
2606 }
2607
2608 // For app windows that are not attached, we decide if all windows in the app they
2609 // represent should be hidden or if we should hide the lockscreen. For attached app
2610 // windows we defer the decision to the window it is attached to.
2611 if (appWindow && attached == null) {
2612 if (attrs.isFullscreen() && inFullScreenOrSplitScreenSecondaryWindowingMode) {
2613 if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
2614 mTopFullscreenOpaqueWindowState = win;
2615 if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
2616 mTopFullscreenOpaqueOrDimmingWindowState = win;
2617 }
2618 if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
2619 mAllowLockscreenWhenOn = true;
2620 }
2621 }
2622 }
2623 }
2624
2625 // Voice interaction overrides both top fullscreen and top docked.
Jorim Jaggi50150152019-03-27 23:08:58 +01002626 if (affectsSystemUi && attrs.type == TYPE_VOICE_INTERACTION) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002627 if (mTopFullscreenOpaqueWindowState == null) {
2628 mTopFullscreenOpaqueWindowState = win;
2629 if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
2630 mTopFullscreenOpaqueOrDimmingWindowState = win;
2631 }
2632 }
2633 if (mTopDockedOpaqueWindowState == null) {
2634 mTopDockedOpaqueWindowState = win;
2635 if (mTopDockedOpaqueOrDimmingWindowState == null) {
2636 mTopDockedOpaqueOrDimmingWindowState = win;
2637 }
2638 }
2639 }
2640
2641 // Keep track of the window if it's dimming but not necessarily fullscreen.
2642 if (mTopFullscreenOpaqueOrDimmingWindowState == null && affectsSystemUi
2643 && win.isDimming() && inFullScreenOrSplitScreenSecondaryWindowingMode) {
2644 mTopFullscreenOpaqueOrDimmingWindowState = win;
2645 }
2646
2647 // We need to keep track of the top "fullscreen" opaque window for the docked stack
2648 // separately, because both the "real fullscreen" opaque window and the one for the docked
2649 // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
2650 if (mTopDockedOpaqueWindowState == null && affectsSystemUi && appWindow && attached == null
2651 && attrs.isFullscreen() && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
2652 mTopDockedOpaqueWindowState = win;
2653 if (mTopDockedOpaqueOrDimmingWindowState == null) {
2654 mTopDockedOpaqueOrDimmingWindowState = win;
2655 }
2656 }
2657
HEO SEUNG22d3ec22019-05-30 20:28:53 +09002658 // Check if the freeform window overlaps with the navigation bar area.
2659 final WindowState navBarWin = hasNavigationBar() ? mNavigationBar : null;
2660 if (!mIsFreeformWindowOverlappingWithNavBar && win.inFreeformWindowingMode()
2661 && isOverlappingWithNavBar(win, navBarWin)) {
2662 mIsFreeformWindowOverlappingWithNavBar = true;
2663 }
2664
Tiger Huang7c610aa2018-10-27 00:01:01 +08002665 // Also keep track of any windows that are dimming but not necessarily fullscreen in the
2666 // docked stack.
2667 if (mTopDockedOpaqueOrDimmingWindowState == null && affectsSystemUi && win.isDimming()
2668 && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
2669 mTopDockedOpaqueOrDimmingWindowState = win;
2670 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002671 }
2672
2673 /**
2674 * Called following layout of all windows and after policy has been applied
2675 * to each window. If in this function you do
2676 * something that may have modified the animation state of another window,
2677 * be sure to return non-zero in order to perform another pass through layout.
2678 *
2679 * @return Return any bit set of
2680 * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_LAYOUT},
2681 * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_CONFIG},
2682 * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_WALLPAPER}, or
2683 * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_ANIM}.
2684 */
2685 public int finishPostLayoutPolicyLw() {
2686 int changes = 0;
2687 boolean topIsFullscreen = false;
2688
2689 // If we are not currently showing a dream then remember the current
2690 // lockscreen state. We will use this to determine whether the dream
2691 // started while the lockscreen was showing and remember this state
2692 // while the dream is showing.
2693 if (!mShowingDream) {
2694 mDreamingLockscreen = mService.mPolicy.isKeyguardShowingAndNotOccluded();
Tiger Huang7c610aa2018-10-27 00:01:01 +08002695 }
2696
2697 if (mStatusBar != null) {
2698 if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
Tiger Huang7c610aa2018-10-27 00:01:01 +08002699 + " top=" + mTopFullscreenOpaqueWindowState);
wilsonshihe8321942019-10-18 18:39:46 +08002700 final boolean forceShowStatusBar = (mStatusBar.getAttrs().privateFlags
2701 & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0;
2702 final boolean notificationShadeForcesShowingNavigation =
2703 mNotificationShade != null
2704 && (mNotificationShade.getAttrs().privateFlags
Tiger Huang7c610aa2018-10-27 00:01:01 +08002705 & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0;
wilsonshihe8321942019-10-18 18:39:46 +08002706
Tiger Huang7c610aa2018-10-27 00:01:01 +08002707 boolean topAppHidesStatusBar = topAppHidesStatusBar();
wilsonshihe8321942019-10-18 18:39:46 +08002708 if (mForceStatusBar || forceShowStatusBar) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002709 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
2710 if (mStatusBarController.setBarShowingLw(true)) {
2711 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2712 }
2713 // Maintain fullscreen layout until incoming animation is complete.
2714 topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
wilsonshihe8321942019-10-18 18:39:46 +08002715 // Transient status bar is not allowed if notification shade is expecting the
2716 // navigation keys from the user.
2717 if (notificationShadeForcesShowingNavigation
Tiger Huang7c610aa2018-10-27 00:01:01 +08002718 && mStatusBarController.isTransientShowing()) {
2719 mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
2720 mLastSystemUiFlags, mLastSystemUiFlags);
2721 }
2722 } else if (mTopFullscreenOpaqueWindowState != null) {
2723 topIsFullscreen = topAppHidesStatusBar;
2724 // The subtle difference between the window for mTopFullscreenOpaqueWindowState
2725 // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
2726 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the
2727 // case though.
2728 if (mStatusBarController.isTransientShowing()) {
2729 if (mStatusBarController.setBarShowingLw(true)) {
2730 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2731 }
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07002732 } else if (topIsFullscreen && !mDisplayContent.getDefaultTaskDisplayArea()
2733 .isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002734 if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
2735 if (mStatusBarController.setBarShowingLw(false)) {
2736 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2737 } else {
2738 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
2739 }
2740 } else {
2741 if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
2742 if (mStatusBarController.setBarShowingLw(true)) {
2743 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2744 }
2745 topAppHidesStatusBar = false;
2746 }
2747 }
2748 mStatusBarController.setTopAppHidesStatusBar(topAppHidesStatusBar);
2749 }
2750
2751 if (mTopIsFullscreen != topIsFullscreen) {
2752 if (!topIsFullscreen) {
2753 // Force another layout when status bar becomes fully shown.
2754 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2755 }
2756 mTopIsFullscreen = topIsFullscreen;
2757 }
2758
2759 if ((updateSystemUiVisibilityLw() & SYSTEM_UI_CHANGING_LAYOUT) != 0) {
2760 // If the navigation bar has been hidden or shown, we need to do another
2761 // layout pass to update that window.
2762 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2763 }
2764
2765 if (mShowingDream != mLastShowingDream) {
2766 mLastShowingDream = mShowingDream;
2767 mService.notifyShowingDreamChanged();
2768 }
2769
Tiger Huang7c610aa2018-10-27 00:01:01 +08002770 mService.mPolicy.setAllowLockscreenWhenOn(getDisplayId(), mAllowLockscreenWhenOn);
2771 return changes;
2772 }
2773
Tiger Huang7c610aa2018-10-27 00:01:01 +08002774 /**
2775 * @return Whether the top app should hide the statusbar based on the top fullscreen opaque
2776 * window.
2777 */
Tiger Huang8949be42020-05-18 19:42:09 +08002778 boolean topAppHidesStatusBar() {
hyok.kim332ccfc2019-07-02 15:39:43 +09002779 if (mTopFullscreenOpaqueWindowState == null || mForceShowSystemBars) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002780 return false;
2781 }
Tiger Huang8949be42020-05-18 19:42:09 +08002782 final LayoutParams attrs = mTopFullscreenOpaqueWindowState.getAttrs();
2783 final int fl = PolicyControl.getWindowFlags(null, attrs);
2784 final int sysui = PolicyControl.getSystemUiVisibility(null, attrs);
2785 final InsetsSource request = mTopFullscreenOpaqueWindowState.getRequestedInsetsState()
2786 .peekSource(ITYPE_STATUS_BAR);
Adam Pardyl8c2d19c2019-09-16 17:15:38 +02002787 if (WindowManagerDebugConfig.DEBUG) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002788 Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw());
Tiger Huang8949be42020-05-18 19:42:09 +08002789 Slog.d(TAG, "attr: " + attrs + " request: " + request);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002790 }
2791 return (fl & LayoutParams.FLAG_FULLSCREEN) != 0
Tiger Huang8949be42020-05-18 19:42:09 +08002792 || (sysui & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0
2793 || (request != null && !request.isVisible());
Tiger Huang7c610aa2018-10-27 00:01:01 +08002794 }
2795
2796 /**
Winson Chungda20fec2019-04-10 12:19:59 -07002797 * Called when the user is switched.
2798 */
2799 public void switchUser() {
2800 updateCurrentUserResources();
2801 }
2802
2803 /**
Tiger Huang7c610aa2018-10-27 00:01:01 +08002804 * Called when the resource overlays change.
2805 */
2806 public void onOverlayChangedLw() {
Winson Chungda20fec2019-04-10 12:19:59 -07002807 updateCurrentUserResources();
Tiger Huang7c610aa2018-10-27 00:01:01 +08002808 onConfigurationChanged();
Jeff Changb0a061e2019-03-11 11:39:54 +08002809 mSystemGestures.onConfigurationChanged();
Tiger Huang7c610aa2018-10-27 00:01:01 +08002810 }
2811
2812 /**
2813 * Called when the configuration has changed, and it's safe to load new values from resources.
2814 */
2815 public void onConfigurationChanged() {
2816 final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation();
2817
Winson Chungda20fec2019-04-10 12:19:59 -07002818 final Resources res = getCurrentUserResources();
Tiger Huang7c610aa2018-10-27 00:01:01 +08002819 final int portraitRotation = displayRotation.getPortraitRotation();
2820 final int upsideDownRotation = displayRotation.getUpsideDownRotation();
2821 final int landscapeRotation = displayRotation.getLandscapeRotation();
2822 final int seascapeRotation = displayRotation.getSeascapeRotation();
Matthew Nga7f24bc2019-04-09 17:06:41 -07002823 final int uiMode = mService.mPolicy.getUiMode();
Tiger Huang7c610aa2018-10-27 00:01:01 +08002824
Louis Changfc64c832018-12-04 11:38:26 +08002825 if (hasStatusBar()) {
2826 mStatusBarHeightForRotation[portraitRotation] =
2827 mStatusBarHeightForRotation[upsideDownRotation] =
2828 res.getDimensionPixelSize(R.dimen.status_bar_height_portrait);
2829 mStatusBarHeightForRotation[landscapeRotation] =
2830 mStatusBarHeightForRotation[seascapeRotation] =
2831 res.getDimensionPixelSize(R.dimen.status_bar_height_landscape);
2832 } else {
2833 mStatusBarHeightForRotation[portraitRotation] =
2834 mStatusBarHeightForRotation[upsideDownRotation] =
2835 mStatusBarHeightForRotation[landscapeRotation] =
2836 mStatusBarHeightForRotation[seascapeRotation] = 0;
2837 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002838
2839 // Height of the navigation bar when presented horizontally at bottom
2840 mNavigationBarHeightForRotationDefault[portraitRotation] =
2841 mNavigationBarHeightForRotationDefault[upsideDownRotation] =
2842 res.getDimensionPixelSize(R.dimen.navigation_bar_height);
2843 mNavigationBarHeightForRotationDefault[landscapeRotation] =
2844 mNavigationBarHeightForRotationDefault[seascapeRotation] =
2845 res.getDimensionPixelSize(R.dimen.navigation_bar_height_landscape);
2846
Matthew Nga7f24bc2019-04-09 17:06:41 -07002847 // Height of the navigation bar frame when presented horizontally at bottom
2848 mNavigationBarFrameHeightForRotationDefault[portraitRotation] =
2849 mNavigationBarFrameHeightForRotationDefault[upsideDownRotation] =
2850 res.getDimensionPixelSize(R.dimen.navigation_bar_frame_height);
2851 mNavigationBarFrameHeightForRotationDefault[landscapeRotation] =
2852 mNavigationBarFrameHeightForRotationDefault[seascapeRotation] =
2853 res.getDimensionPixelSize(R.dimen.navigation_bar_frame_height_landscape);
2854
Tiger Huang7c610aa2018-10-27 00:01:01 +08002855 // Width of the navigation bar when presented vertically along one side
2856 mNavigationBarWidthForRotationDefault[portraitRotation] =
2857 mNavigationBarWidthForRotationDefault[upsideDownRotation] =
2858 mNavigationBarWidthForRotationDefault[landscapeRotation] =
2859 mNavigationBarWidthForRotationDefault[seascapeRotation] =
2860 res.getDimensionPixelSize(R.dimen.navigation_bar_width);
2861
2862 if (ALTERNATE_CAR_MODE_NAV_SIZE) {
2863 // Height of the navigation bar when presented horizontally at bottom
2864 mNavigationBarHeightForRotationInCarMode[portraitRotation] =
2865 mNavigationBarHeightForRotationInCarMode[upsideDownRotation] =
2866 res.getDimensionPixelSize(R.dimen.navigation_bar_height_car_mode);
2867 mNavigationBarHeightForRotationInCarMode[landscapeRotation] =
2868 mNavigationBarHeightForRotationInCarMode[seascapeRotation] =
2869 res.getDimensionPixelSize(R.dimen.navigation_bar_height_landscape_car_mode);
2870
2871 // Width of the navigation bar when presented vertically along one side
2872 mNavigationBarWidthForRotationInCarMode[portraitRotation] =
2873 mNavigationBarWidthForRotationInCarMode[upsideDownRotation] =
2874 mNavigationBarWidthForRotationInCarMode[landscapeRotation] =
2875 mNavigationBarWidthForRotationInCarMode[seascapeRotation] =
2876 res.getDimensionPixelSize(R.dimen.navigation_bar_width_car_mode);
2877 }
2878
Winson Chung4723b4e2019-03-25 16:49:36 -07002879 mNavBarOpacityMode = res.getInteger(R.integer.config_navBarOpacityMode);
Mehdi Alizadehf2b28e92019-12-05 20:13:49 -08002880 mLeftGestureInset = mGestureNavigationSettingsObserver.getLeftSensitivity(res);
2881 mRightGestureInset = mGestureNavigationSettingsObserver.getRightSensitivity(res);
Sunny Goyal38412952020-04-17 11:35:37 -07002882 mNavButtonForcedVisible =
2883 mGestureNavigationSettingsObserver.areNavigationButtonForcedVisible();
Adrian Roos11dfd272019-03-25 19:21:26 +01002884 mNavigationBarLetsThroughTaps = res.getBoolean(R.bool.config_navBarTapThrough);
Winson Chung36941632019-04-19 15:21:38 -07002885 mNavigationBarAlwaysShowOnSideGesture =
2886 res.getBoolean(R.bool.config_navBarAlwaysShowOnSideEdgeGesture);
Winson Chung4723b4e2019-03-25 16:49:36 -07002887
Matthew Nga7f24bc2019-04-09 17:06:41 -07002888 // This should calculate how much above the frame we accept gestures.
Sunny Goyalb5e5bcb2019-05-22 14:28:44 -07002889 mBottomGestureAdditionalInset =
Matthew Nga7f24bc2019-04-09 17:06:41 -07002890 res.getDimensionPixelSize(R.dimen.navigation_bar_gesture_height)
Sunny Goyalb5e5bcb2019-05-22 14:28:44 -07002891 - getNavigationBarFrameHeight(portraitRotation, uiMode);
Adrian Roos11dfd272019-03-25 19:21:26 +01002892
Winson Chung4723b4e2019-03-25 16:49:36 -07002893 updateConfigurationAndScreenSizeDependentBehaviors();
2894 }
2895
2896 void updateConfigurationAndScreenSizeDependentBehaviors() {
Winson Chungda20fec2019-04-10 12:19:59 -07002897 final Resources res = getCurrentUserResources();
Winson Chung4723b4e2019-03-25 16:49:36 -07002898 mNavigationBarCanMove =
2899 mDisplayContent.mBaseDisplayWidth != mDisplayContent.mBaseDisplayHeight
2900 && res.getBoolean(R.bool.config_navBarCanMove);
Riddle Hsuccf09402019-08-13 00:33:06 +08002901 mDisplayContent.getDisplayRotation().updateUserDependentConfiguration(res);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002902 }
2903
Winson Chungda20fec2019-04-10 12:19:59 -07002904 /**
2905 * Updates the current user's resources to pick up any changes for the current user (including
2906 * overlay paths)
2907 */
2908 private void updateCurrentUserResources() {
2909 final int userId = mService.mAmInternal.getCurrentUserId();
2910 final Context uiContext = getSystemUiContext();
Winson Chung203e1522019-05-02 15:42:22 -07002911
2912 if (userId == UserHandle.USER_SYSTEM) {
2913 // Skip the (expensive) recreation of resources for the system user below and just
2914 // use the resources from the system ui context
2915 mCurrentUserResources = uiContext.getResources();
2916 return;
2917 }
2918
2919 // For non-system users, ensure that the resources are loaded from the current
2920 // user's package info (see ContextImpl.createDisplayContext)
Winson Chungda20fec2019-04-10 12:19:59 -07002921 final LoadedApk pi = ActivityThread.currentActivityThread().getPackageInfo(
2922 uiContext.getPackageName(), null, 0, userId);
Winson Chungda20fec2019-04-10 12:19:59 -07002923 mCurrentUserResources = ResourcesManager.getInstance().getResources(null,
2924 pi.getResDir(),
2925 null /* splitResDirs */,
2926 pi.getOverlayDirs(),
2927 pi.getApplicationInfo().sharedLibraryFiles,
2928 mDisplayContent.getDisplayId(),
2929 null /* overrideConfig */,
2930 uiContext.getResources().getCompatibilityInfo(),
Ryan Mitchell4579c0a2020-01-08 16:29:11 -08002931 null /* classLoader */,
2932 null /* loaders */);
Winson Chungda20fec2019-04-10 12:19:59 -07002933 }
2934
Tiger Huang7c610aa2018-10-27 00:01:01 +08002935 @VisibleForTesting
Winson Chungda20fec2019-04-10 12:19:59 -07002936 Resources getCurrentUserResources() {
2937 if (mCurrentUserResources == null) {
2938 updateCurrentUserResources();
2939 }
2940 return mCurrentUserResources;
2941 }
2942
2943 @VisibleForTesting
2944 Context getContext() {
2945 return mContext;
2946 }
2947
Charles Chen173ae782019-11-11 20:39:02 +08002948 Context getSystemUiContext() {
2949 return mUiContext;
Tiger Huang7c610aa2018-10-27 00:01:01 +08002950 }
2951
2952 private int getNavigationBarWidth(int rotation, int uiMode) {
2953 if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2954 return mNavigationBarWidthForRotationInCarMode[rotation];
2955 } else {
2956 return mNavigationBarWidthForRotationDefault[rotation];
2957 }
2958 }
2959
Charles Chen3dedec32019-01-24 22:19:37 +08002960 void notifyDisplayReady() {
wilsonshih643bf132019-02-27 12:49:19 +08002961 mHandler.post(() -> {
2962 final int displayId = getDisplayId();
2963 getStatusBarManagerInternal().onDisplayReady(displayId);
Felipe Leme34a861a2019-08-05 16:00:12 -07002964 final WallpaperManagerInternal wpMgr = LocalServices
2965 .getService(WallpaperManagerInternal.class);
2966 if (wpMgr != null) {
2967 wpMgr.onDisplayReady(displayId);
2968 }
wilsonshih643bf132019-02-27 12:49:19 +08002969 });
Charles Chen3dedec32019-01-24 22:19:37 +08002970 }
2971
Tiger Huang7c610aa2018-10-27 00:01:01 +08002972 /**
2973 * Return the display width available after excluding any screen
2974 * decorations that could never be removed in Honeycomb. That is, system bar or
2975 * button bar.
2976 */
2977 public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
2978 DisplayCutout displayCutout) {
2979 int width = fullWidth;
2980 if (hasNavigationBar()) {
Tiger Huang3d2b8982019-01-29 22:56:48 +08002981 final int navBarPosition = navigationBarPosition(fullWidth, fullHeight, rotation);
2982 if (navBarPosition == NAV_BAR_LEFT || navBarPosition == NAV_BAR_RIGHT) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002983 width -= getNavigationBarWidth(rotation, uiMode);
2984 }
2985 }
2986 if (displayCutout != null) {
2987 width -= displayCutout.getSafeInsetLeft() + displayCutout.getSafeInsetRight();
2988 }
2989 return width;
2990 }
2991
2992 private int getNavigationBarHeight(int rotation, int uiMode) {
2993 if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2994 return mNavigationBarHeightForRotationInCarMode[rotation];
2995 } else {
2996 return mNavigationBarHeightForRotationDefault[rotation];
2997 }
2998 }
2999
3000 /**
Matthew Nga7f24bc2019-04-09 17:06:41 -07003001 * Get the Navigation Bar Frame height. This dimension is the height of the navigation bar that
3002 * is used for spacing to show additional buttons on the navigation bar (such as the ime
3003 * switcher when ime is visible) while {@link #getNavigationBarHeight} is used for the visible
3004 * height that we send to the app as content insets that can be smaller.
3005 * <p>
3006 * In car mode it will return the same height as {@link #getNavigationBarHeight}
3007 *
3008 * @param rotation specifies rotation to return dimension from
3009 * @param uiMode to determine if in car mode
3010 * @return navigation bar frame height
3011 */
3012 private int getNavigationBarFrameHeight(int rotation, int uiMode) {
3013 if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
3014 return mNavigationBarHeightForRotationInCarMode[rotation];
3015 } else {
3016 return mNavigationBarFrameHeightForRotationDefault[rotation];
3017 }
3018 }
3019
3020 /**
Tiger Huang7c610aa2018-10-27 00:01:01 +08003021 * Return the display height available after excluding any screen
3022 * decorations that could never be removed in Honeycomb. That is, system bar or
3023 * button bar.
3024 */
3025 public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
3026 DisplayCutout displayCutout) {
3027 int height = fullHeight;
3028 if (hasNavigationBar()) {
Tiger Huang3d2b8982019-01-29 22:56:48 +08003029 final int navBarPosition = navigationBarPosition(fullWidth, fullHeight, rotation);
3030 if (navBarPosition == NAV_BAR_BOTTOM) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08003031 height -= getNavigationBarHeight(rotation, uiMode);
3032 }
3033 }
3034 if (displayCutout != null) {
3035 height -= displayCutout.getSafeInsetTop() + displayCutout.getSafeInsetBottom();
3036 }
3037 return height;
3038 }
3039
3040 /**
3041 * Return the available screen width that we should report for the
3042 * configuration. This must be no larger than
3043 * {@link #getNonDecorDisplayWidth(int, int, int, int, DisplayCutout)}; it may be smaller
3044 * than that to account for more transient decoration like a status bar.
3045 */
3046 public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
3047 DisplayCutout displayCutout) {
3048 return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode, displayCutout);
3049 }
3050
3051 /**
3052 * Return the available screen height that we should report for the
3053 * configuration. This must be no larger than
3054 * {@link #getNonDecorDisplayHeight(int, int, int, int, DisplayCutout)}; it may be smaller
3055 * than that to account for more transient decoration like a status bar.
3056 */
3057 public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
3058 DisplayCutout displayCutout) {
3059 // There is a separate status bar at the top of the display. We don't count that as part
3060 // of the fixed decor, since it can hide; however, for purposes of configurations,
3061 // we do want to exclude it since applications can't generally use that part
3062 // of the screen.
3063 int statusBarHeight = mStatusBarHeightForRotation[rotation];
3064 if (displayCutout != null) {
3065 // If there is a cutout, it may already have accounted for some part of the status
3066 // bar height.
3067 statusBarHeight = Math.max(0, statusBarHeight - displayCutout.getSafeInsetTop());
3068 }
3069 return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayCutout)
3070 - statusBarHeight;
3071 }
3072
Tiger Huang43b8fc22019-04-26 11:49:29 +08003073 /**
3074 * Return corner radius in pixels that should be used on windows in order to cover the display.
Dominik Laskowski26290bb2020-01-15 16:09:55 -08003075 *
3076 * The radius is only valid for internal displays, since the corner radius of external displays
3077 * is not known at build time when window corners are configured.
Tiger Huang43b8fc22019-04-26 11:49:29 +08003078 */
3079 float getWindowCornerRadius() {
Dominik Laskowski26290bb2020-01-15 16:09:55 -08003080 return mDisplayContent.getDisplay().getType() == TYPE_INTERNAL
Tiger Huang43b8fc22019-04-26 11:49:29 +08003081 ? ScreenDecorationsUtils.getWindowCornerRadius(mContext.getResources()) : 0f;
3082 }
3083
Tiger Huang7c610aa2018-10-27 00:01:01 +08003084 boolean isShowingDreamLw() {
3085 return mShowingDream;
3086 }
3087
3088 /**
Riddle Hsu61987bc2019-04-03 13:08:47 +08003089 * Calculates the stable insets if we already have the non-decor insets.
3090 *
3091 * @param inOutInsets The known non-decor insets. It will be modified to stable insets.
3092 * @param rotation The current display rotation.
3093 */
3094 void convertNonDecorInsetsToStableInsets(Rect inOutInsets, int rotation) {
3095 inOutInsets.top = Math.max(inOutInsets.top, mStatusBarHeightForRotation[rotation]);
3096 }
3097
3098 /**
Tiger Huang7c610aa2018-10-27 00:01:01 +08003099 * Calculates the stable insets without running a layout.
3100 *
3101 * @param displayRotation the current display rotation
3102 * @param displayWidth the current display width
3103 * @param displayHeight the current display height
3104 * @param displayCutout the current display cutout
3105 * @param outInsets the insets to return
3106 */
3107 public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
3108 DisplayCutout displayCutout, Rect outInsets) {
3109 outInsets.setEmpty();
3110
3111 // Navigation bar and status bar.
3112 getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, displayCutout, outInsets);
Riddle Hsu61987bc2019-04-03 13:08:47 +08003113 convertNonDecorInsetsToStableInsets(outInsets, displayRotation);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003114 }
3115
3116 /**
3117 * Calculates the insets for the areas that could never be removed in Honeycomb, i.e. system
3118 * bar or button bar. See {@link #getNonDecorDisplayWidth}.
3119 *
3120 * @param displayRotation the current display rotation
3121 * @param displayWidth the current display width
3122 * @param displayHeight the current display height
3123 * @param displayCutout the current display cutout
3124 * @param outInsets the insets to return
3125 */
3126 public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
3127 DisplayCutout displayCutout, Rect outInsets) {
3128 outInsets.setEmpty();
3129
3130 // Only navigation bar
3131 if (hasNavigationBar()) {
3132 final int uiMode = mService.mPolicy.getUiMode();
3133 int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
3134 if (position == NAV_BAR_BOTTOM) {
3135 outInsets.bottom = getNavigationBarHeight(displayRotation, uiMode);
3136 } else if (position == NAV_BAR_RIGHT) {
3137 outInsets.right = getNavigationBarWidth(displayRotation, uiMode);
3138 } else if (position == NAV_BAR_LEFT) {
3139 outInsets.left = getNavigationBarWidth(displayRotation, uiMode);
3140 }
3141 }
3142
3143 if (displayCutout != null) {
3144 outInsets.left += displayCutout.getSafeInsetLeft();
3145 outInsets.top += displayCutout.getSafeInsetTop();
3146 outInsets.right += displayCutout.getSafeInsetRight();
3147 outInsets.bottom += displayCutout.getSafeInsetBottom();
3148 }
3149 }
3150
Issei Suzukia5dbf522019-02-01 17:58:15 +01003151 /**
3152 * @see IWindowManager#setForwardedInsets
3153 */
3154 public void setForwardedInsets(@NonNull Insets forwardedInsets) {
3155 mForwardedInsets = forwardedInsets;
3156 }
3157
3158 @NonNull
3159 public Insets getForwardedInsets() {
3160 return mForwardedInsets;
3161 }
3162
Tiger Huang7c610aa2018-10-27 00:01:01 +08003163 @NavigationBarPosition
3164 int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
3165 if (navigationBarCanMove() && displayWidth > displayHeight) {
3166 if (displayRotation == Surface.ROTATION_270) {
3167 return NAV_BAR_LEFT;
3168 } else if (displayRotation == Surface.ROTATION_90) {
3169 return NAV_BAR_RIGHT;
3170 }
3171 }
3172 return NAV_BAR_BOTTOM;
3173 }
3174
3175 /**
3176 * @return The side of the screen where navigation bar is positioned.
3177 * @see WindowManagerPolicyConstants#NAV_BAR_LEFT
3178 * @see WindowManagerPolicyConstants#NAV_BAR_RIGHT
3179 * @see WindowManagerPolicyConstants#NAV_BAR_BOTTOM
3180 */
3181 @NavigationBarPosition
3182 public int getNavBarPosition() {
3183 return mNavigationBarPosition;
3184 }
3185
3186 /**
3187 * A new window has been focused.
3188 */
3189 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
3190 mFocusedWindow = newFocus;
3191 mLastFocusedWindow = lastFocus;
Issei Suzuki9f840c72018-12-07 15:09:30 -08003192 if (mDisplayContent.isDefaultDisplay) {
3193 mService.mPolicy.onDefaultDisplayFocusChangedLw(newFocus);
3194 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08003195 if ((updateSystemUiVisibilityLw() & SYSTEM_UI_CHANGING_LAYOUT) != 0) {
3196 // If the navigation bar has been hidden or shown, we need to do another
3197 // layout pass to update that window.
3198 return FINISH_LAYOUT_REDO_LAYOUT;
3199 }
3200 return 0;
3201 }
3202
Tiger Huang7c610aa2018-10-27 00:01:01 +08003203 private void requestTransientBars(WindowState swipeTarget) {
Tiger Huang82fd0ad2020-03-09 17:55:47 +08003204 if (!mService.mPolicy.isUserSetupComplete()) {
3205 // Swipe-up for navigation bar is disabled during setup
3206 return;
3207 }
3208 if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
Tiger Huang82fd0ad2020-03-09 17:55:47 +08003209 final InsetsSourceProvider provider = swipeTarget.getControllableInsetProvider();
3210 final InsetsControlTarget controlTarget = provider != null
3211 ? provider.getControlTarget() : null;
Jorim Jaggi026ed752020-01-29 00:30:24 +01003212
Tiger Huang82fd0ad2020-03-09 17:55:47 +08003213 if (controlTarget == null || controlTarget == getNotificationShade()) {
Tiger Huang017d51d2020-05-27 17:58:17 +08003214 // No transient mode on lockscreen (in notification shade window).
Tiger Huang82fd0ad2020-03-09 17:55:47 +08003215 return;
3216 }
Tiger Huang017d51d2020-05-27 17:58:17 +08003217
3218 if (swipeTarget == mNavigationBar
3219 && !getInsetsPolicy().isHidden(ITYPE_NAVIGATION_BAR)) {
3220 // Don't show status bar when swiping on already visible navigation bar.
3221 // But restore the position of navigation bar if it has been moved by the control
3222 // target.
3223 controlTarget.showInsets(Type.navigationBars(), false);
3224 return;
3225 }
3226
3227 int insetsTypesToShow = Type.systemBars();
3228
Tiger Huang82fd0ad2020-03-09 17:55:47 +08003229 if (controlTarget.canShowTransient()) {
Tiger Huang017d51d2020-05-27 17:58:17 +08003230 insetsTypesToShow &= ~mDisplayContent.getInsetsPolicy().showTransient(IntArray.wrap(
Tiger Huang82fd0ad2020-03-09 17:55:47 +08003231 new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
Tiger Huang017d51d2020-05-27 17:58:17 +08003232 }
3233 if (insetsTypesToShow != 0) {
3234 controlTarget.showInsets(insetsTypesToShow, false);
Tiger Huang82fd0ad2020-03-09 17:55:47 +08003235 }
3236 } else {
3237 boolean sb = mStatusBarController.checkShowTransientBarLw();
3238 boolean nb = mNavigationBarController.checkShowTransientBarLw()
3239 && !isNavBarEmpty(mLastSystemUiFlags);
3240 if (sb || nb) {
3241 // Don't show status bar when swiping on already visible navigation bar
3242 if (!nb && swipeTarget == mNavigationBar) {
3243 if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
Jorim Jaggi956ca412019-01-07 14:49:14 +01003244 return;
3245 }
Tiger Huang82fd0ad2020-03-09 17:55:47 +08003246 if (sb) mStatusBarController.showTransient();
3247 if (nb) mNavigationBarController.showTransient();
3248 updateSystemUiVisibilityLw();
Tiger Huang7c610aa2018-10-27 00:01:01 +08003249 }
3250 }
Tiger Huang82fd0ad2020-03-09 17:55:47 +08003251 mImmersiveModeConfirmation.confirmCurrentPrompt();
Tiger Huang7c610aa2018-10-27 00:01:01 +08003252 }
3253
3254 private void disposeInputConsumer(InputConsumer inputConsumer) {
3255 if (inputConsumer != null) {
Arthur Hungde767252020-02-03 19:22:16 +08003256 inputConsumer.dispose();
Tiger Huang7c610aa2018-10-27 00:01:01 +08003257 }
3258 }
3259
wilsonshihe8321942019-10-18 18:39:46 +08003260 boolean isKeyguardShowing() {
3261 return mService.mPolicy.isKeyguardShowing();
Tiger Huang7c610aa2018-10-27 00:01:01 +08003262 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08003263 private boolean isKeyguardOccluded() {
3264 // TODO (b/113840485): Handle per display keyguard.
3265 return mService.mPolicy.isKeyguardOccluded();
3266 }
3267
Jorim Jaggi956ca412019-01-07 14:49:14 +01003268 InsetsPolicy getInsetsPolicy() {
3269 return mDisplayContent.getInsetsPolicy();
3270 }
3271
Tiger Huang7c610aa2018-10-27 00:01:01 +08003272 void resetSystemUiVisibilityLw() {
3273 mLastSystemUiFlags = 0;
3274 updateSystemUiVisibilityLw();
3275 }
3276
Tiger Huangdd6db472020-02-13 21:38:46 +08003277 int updateSystemUiVisibilityLw() {
Tiger Huang7c610aa2018-10-27 00:01:01 +08003278 // If there is no window focused, there will be nobody to handle the events
3279 // anyway, so just hang on in whatever state we're in until things settle down.
3280 WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
3281 : mTopFullscreenOpaqueWindowState;
3282 if (winCandidate == null) {
3283 return 0;
3284 }
3285
3286 // The immersive mode confirmation should never affect the system bar visibility, otherwise
3287 // it will unhide the navigation bar and hide itself.
3288 if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
3289
3290 // The immersive mode confirmation took the focus from mLastFocusedWindow which was
3291 // controlling the system ui visibility. So if mLastFocusedWindow can still receive
3292 // keys, we let it keep controlling the visibility.
3293 final boolean lastFocusCanReceiveKeys =
3294 (mLastFocusedWindow != null && mLastFocusedWindow.canReceiveKeys());
wilsonshihe8321942019-10-18 18:39:46 +08003295 winCandidate = isKeyguardShowing() ? mNotificationShade
Tiger Huang7c610aa2018-10-27 00:01:01 +08003296 : lastFocusCanReceiveKeys ? mLastFocusedWindow
3297 : mTopFullscreenOpaqueWindowState;
3298 if (winCandidate == null) {
3299 return 0;
3300 }
3301 }
3302 final WindowState win = winCandidate;
wilsonshihe8321942019-10-18 18:39:46 +08003303 if (win.getAttrs().type == TYPE_NOTIFICATION_SHADE && isKeyguardShowing()
3304 && isKeyguardOccluded()) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08003305 // We are updating at a point where the keyguard has gotten
3306 // focus, but we were last in a state where the top window is
3307 // hiding it. This is probably because the keyguard as been
3308 // shown while the top window was displayed, so we want to ignore
3309 // it here because this is just a very transient change and it
3310 // will quickly lose focus once it correctly gets hidden.
3311 return 0;
3312 }
3313
Jorim Jaggi28620472019-01-02 23:21:49 +01003314 mDisplayContent.getInsetsPolicy().updateBarControlTarget(win);
Jorim Jaggib6030952018-10-23 18:31:52 +02003315
Tiger Huang7c610aa2018-10-27 00:01:01 +08003316 int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
3317 & ~mResettingSystemUiFlags
3318 & ~mForceClearedSystemUiFlags;
3319 if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
3320 tmpVisibility
3321 &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
3322 }
3323
Jorim Jaggi956ca412019-01-07 14:49:14 +01003324 final int fullscreenAppearance = updateLightStatusBarAppearanceLw(0 /* vis */,
3325 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
3326 final int dockedAppearance = updateLightStatusBarAppearanceLw(0 /* vis */,
3327 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
Evan Rosky40bf15c2020-04-02 20:23:36 -07003328 final boolean inSplitScreen =
Andrii Kulianf9df4a82020-03-31 12:09:27 -07003329 mService.mRoot.getDefaultTaskDisplayArea().isSplitScreenModeActivated();
Evan Rosky40bf15c2020-04-02 20:23:36 -07003330 if (inSplitScreen) {
3331 mService.getStackBounds(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD,
3332 mDockedStackBounds);
3333 } else {
3334 mDockedStackBounds.setEmpty();
3335 }
Jorim Jaggi956ca412019-01-07 14:49:14 +01003336 mService.getStackBounds(inSplitScreen ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
3337 : WINDOWING_MODE_FULLSCREEN,
Tiger Huangd5f0b9a2019-10-10 10:34:57 +02003338 ACTIVITY_TYPE_UNDEFINED, mNonDockedStackBounds);
Tiger Huange218e422020-03-06 21:36:12 +08003339 final Pair<Integer, WindowState> result =
Tarandeep Singhe439dec2019-04-22 12:28:43 -07003340 updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
3341 final int visibility = result.first;
Tiger Huange218e422020-03-06 21:36:12 +08003342 final WindowState navColorWin = result.second;
3343 final boolean isNavbarColorManagedByIme =
3344 navColorWin != null && navColorWin == mDisplayContent.mInputMethodWindow;
3345 final int opaqueAppearance = InsetsFlags.getAppearance(visibility)
3346 & (APPEARANCE_OPAQUE_STATUS_BARS | APPEARANCE_OPAQUE_NAVIGATION_BARS);
3347 final int appearance = ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL
3348 ? updateLightNavigationBarAppearanceLw(win.mAttrs.insetsFlags.appearance,
3349 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState,
3350 mDisplayContent.mInputMethodWindow, navColorWin) | opaqueAppearance
3351 : InsetsFlags.getAppearance(visibility);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003352 final int diff = visibility ^ mLastSystemUiFlags;
Jorim Jaggi956ca412019-01-07 14:49:14 +01003353 final InsetsPolicy insetsPolicy = getInsetsPolicy();
3354 final boolean isFullscreen = (visibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
3355 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)) != 0
3356 || (PolicyControl.getWindowFlags(win, win.mAttrs) & FLAG_FULLSCREEN) != 0
Tiger Huang332793b2019-10-29 23:21:27 +08003357 || (mStatusBar != null && insetsPolicy.isHidden(ITYPE_STATUS_BAR))
Jorim Jaggi956ca412019-01-07 14:49:14 +01003358 || (mNavigationBar != null && insetsPolicy.isHidden(
Tiger Huang332793b2019-10-29 23:21:27 +08003359 ITYPE_NAVIGATION_BAR));
Jorim Jaggi956ca412019-01-07 14:49:14 +01003360 final int behavior = win.mAttrs.insetsFlags.behavior;
3361 final boolean isImmersive = (visibility & (View.SYSTEM_UI_FLAG_IMMERSIVE
3362 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)) != 0
3363 || behavior == BEHAVIOR_SHOW_BARS_BY_SWIPE
3364 || behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
Tiger Huang0dbd5372019-10-26 00:24:22 +08003365 if (diff == 0
Jorim Jaggi956ca412019-01-07 14:49:14 +01003366 && mLastAppearance == appearance
3367 && mLastFullscreenAppearance == fullscreenAppearance
3368 && mLastDockedAppearance == dockedAppearance
Tiger Huang4a7835f2019-11-06 00:07:56 +08003369 && mLastBehavior == behavior
Jorim Jaggi956ca412019-01-07 14:49:14 +01003370 && mLastFocusIsFullscreen == isFullscreen
3371 && mLastFocusIsImmersive == isImmersive
Tiger Huang7c610aa2018-10-27 00:01:01 +08003372 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
3373 && mLastDockedStackBounds.equals(mDockedStackBounds)) {
3374 return 0;
3375 }
Tiger Huang0dbd5372019-10-26 00:24:22 +08003376
3377 // Obtains which types should show transient and which types should abort transient.
3378 // If there is no transient state change, this pair will contain two empty arrays.
3379 final Pair<int[], int[]> transientState = getTransientState(visibility, mLastSystemUiFlags);
3380
Tiger Huang7c610aa2018-10-27 00:01:01 +08003381 mLastSystemUiFlags = visibility;
Jorim Jaggi956ca412019-01-07 14:49:14 +01003382 mLastAppearance = appearance;
3383 mLastFullscreenAppearance = fullscreenAppearance;
3384 mLastDockedAppearance = dockedAppearance;
Tiger Huang4a7835f2019-11-06 00:07:56 +08003385 mLastBehavior = behavior;
Jorim Jaggi956ca412019-01-07 14:49:14 +01003386 mLastFocusIsFullscreen = isFullscreen;
3387 mLastFocusIsImmersive = isImmersive;
Riddle Hsu4d6a63f2019-03-29 19:14:43 +08003388 mLastNonDockedStackBounds.set(mNonDockedStackBounds);
3389 mLastDockedStackBounds.set(mDockedStackBounds);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003390 final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
3391 final Rect dockedStackBounds = new Rect(mDockedStackBounds);
Jorim Jaggi956ca412019-01-07 14:49:14 +01003392 final AppearanceRegion[] appearanceRegions = inSplitScreen
3393 ? new AppearanceRegion[]{
3394 new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds),
3395 new AppearanceRegion(dockedAppearance, dockedStackBounds)}
3396 : new AppearanceRegion[]{
3397 new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds)};
Vishnu Nair015d8cd2019-11-18 15:56:30 -08003398 String cause = win.toString();
Tiger Huang7c610aa2018-10-27 00:01:01 +08003399 mHandler.post(() -> {
3400 StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
3401 if (statusBar != null) {
3402 final int displayId = getDisplayId();
Tiger Huang0dbd5372019-10-26 00:24:22 +08003403 statusBar.setDisableFlags(displayId, visibility & StatusBarManager.DISABLE_MASK,
Vishnu Nair015d8cd2019-11-18 15:56:30 -08003404 cause);
Tiger Huang0dbd5372019-10-26 00:24:22 +08003405 if (transientState.first.length > 0) {
3406 statusBar.showTransient(displayId, transientState.first);
Jorim Jaggi956ca412019-01-07 14:49:14 +01003407 }
Tiger Huang0dbd5372019-10-26 00:24:22 +08003408 if (transientState.second.length > 0) {
3409 statusBar.abortTransient(displayId, transientState.second);
3410 }
3411 statusBar.onSystemBarAppearanceChanged(displayId, appearance,
3412 appearanceRegions, isNavbarColorManagedByIme);
Jorim Jaggi956ca412019-01-07 14:49:14 +01003413 statusBar.topAppWindowChanged(displayId, isFullscreen, isImmersive);
3414
3415 // TODO(b/118118435): Remove this after removing system UI visibilities.
Vishnu Nair015d8cd2019-11-18 15:56:30 -08003416 synchronized (mLock) {
3417 mDisplayContent.statusBarVisibilityChanged(
3418 visibility & ~(View.STATUS_BAR_UNHIDE | View.NAVIGATION_BAR_UNHIDE));
3419 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08003420 }
3421 });
3422 return diff;
3423 }
3424
Tiger Huang0dbd5372019-10-26 00:24:22 +08003425 private static Pair<int[], int[]> getTransientState(int vis, int oldVis) {
3426 final IntArray typesToShow = new IntArray(0);
3427 final IntArray typesToAbort = new IntArray(0);
Tiger Huang332793b2019-10-29 23:21:27 +08003428 updateTransientState(vis, oldVis, View.STATUS_BAR_TRANSIENT, ITYPE_STATUS_BAR, typesToShow,
Tiger Huang0dbd5372019-10-26 00:24:22 +08003429 typesToAbort);
3430 updateTransientState(vis, oldVis, View.NAVIGATION_BAR_TRANSIENT,
Tiger Huang332793b2019-10-29 23:21:27 +08003431 ITYPE_NAVIGATION_BAR, typesToShow, typesToAbort);
Tiger Huang0dbd5372019-10-26 00:24:22 +08003432 return Pair.create(typesToShow.toArray(), typesToAbort.toArray());
Tiger Huang7c610aa2018-10-27 00:01:01 +08003433 }
3434
Tiger Huang0dbd5372019-10-26 00:24:22 +08003435 private static void updateTransientState(int vis, int oldVis, int transientFlag,
Tiger Huang332793b2019-10-29 23:21:27 +08003436 @InternalInsetsType int type, IntArray typesToShow, IntArray typesToAbort) {
Tiger Huang0dbd5372019-10-26 00:24:22 +08003437 final boolean wasTransient = (oldVis & transientFlag) != 0;
3438 final boolean isTransient = (vis & transientFlag) != 0;
3439 if (!wasTransient && isTransient) {
3440 typesToShow.add(type);
3441 } else if (wasTransient && !isTransient) {
3442 typesToAbort.add(type);
3443 }
3444 }
3445
3446 private int updateLightStatusBarAppearanceLw(@Appearance int appearance, WindowState opaque,
Jorim Jaggi956ca412019-01-07 14:49:14 +01003447 WindowState opaqueOrDimming) {
wilsonshihe8321942019-10-18 18:39:46 +08003448 final boolean onKeyguard = isKeyguardShowing() && !isKeyguardOccluded();
3449 final WindowState statusColorWin = onKeyguard ? mNotificationShade : opaqueOrDimming;
Jorim Jaggi956ca412019-01-07 14:49:14 +01003450 if (statusColorWin != null && (statusColorWin == opaque || onKeyguard)) {
3451 // If the top fullscreen-or-dimming window is also the top fullscreen, respect
3452 // its light flag.
Tiger Huang332793b2019-10-29 23:21:27 +08003453 appearance &= ~APPEARANCE_LIGHT_STATUS_BARS;
Tiger Huang0dbd5372019-10-26 00:24:22 +08003454 final int legacyAppearance = InsetsFlags.getAppearance(
3455 PolicyControl.getSystemUiVisibility(statusColorWin, null));
3456 appearance |= (statusColorWin.mAttrs.insetsFlags.appearance | legacyAppearance)
Tiger Huang332793b2019-10-29 23:21:27 +08003457 & APPEARANCE_LIGHT_STATUS_BARS;
Jorim Jaggi956ca412019-01-07 14:49:14 +01003458 } else if (statusColorWin != null && statusColorWin.isDimming()) {
3459 // Otherwise if it's dimming, clear the light flag.
Tiger Huang332793b2019-10-29 23:21:27 +08003460 appearance &= ~APPEARANCE_LIGHT_STATUS_BARS;
Jorim Jaggi956ca412019-01-07 14:49:14 +01003461 }
3462 return appearance;
3463 }
3464
Tiger Huang7c610aa2018-10-27 00:01:01 +08003465 @VisibleForTesting
3466 @Nullable
3467 static WindowState chooseNavigationColorWindowLw(WindowState opaque,
3468 WindowState opaqueOrDimming, WindowState imeWindow,
3469 @NavigationBarPosition int navBarPosition) {
3470 // If the IME window is visible and FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS is set, then IME
3471 // window can be navigation color window.
3472 final boolean imeWindowCanNavColorWindow = imeWindow != null
3473 && imeWindow.isVisibleLw()
3474 && navBarPosition == NAV_BAR_BOTTOM
3475 && (PolicyControl.getWindowFlags(imeWindow, null)
3476 & WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
3477
3478 if (opaque != null && opaqueOrDimming == opaque) {
3479 // If the top fullscreen-or-dimming window is also the top fullscreen, respect it
3480 // unless IME window is also eligible, since currently the IME window is always show
3481 // above the opaque fullscreen app window, regardless of the IME target window.
3482 // TODO(b/31559891): Maybe we need to revisit this condition once b/31559891 is fixed.
3483 return imeWindowCanNavColorWindow ? imeWindow : opaque;
3484 }
3485
3486 if (opaqueOrDimming == null || !opaqueOrDimming.isDimming()) {
3487 // No dimming window is involved. Determine the result only with the IME window.
3488 return imeWindowCanNavColorWindow ? imeWindow : null;
3489 }
3490
3491 if (!imeWindowCanNavColorWindow) {
3492 // No IME window is involved. Determine the result only with opaqueOrDimming.
3493 return opaqueOrDimming;
3494 }
3495
3496 // The IME window and the dimming window are competing. Check if the dimming window can be
3497 // IME target or not.
3498 if (LayoutParams.mayUseInputMethod(PolicyControl.getWindowFlags(opaqueOrDimming, null))) {
3499 // The IME window is above the dimming window.
3500 return imeWindow;
3501 } else {
3502 // The dimming window is above the IME window.
3503 return opaqueOrDimming;
3504 }
3505 }
3506
3507 @VisibleForTesting
3508 static int updateLightNavigationBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming,
3509 WindowState imeWindow, WindowState navColorWin) {
3510
3511 if (navColorWin != null) {
3512 if (navColorWin == imeWindow || navColorWin == opaque) {
3513 // Respect the light flag.
3514 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
3515 vis |= PolicyControl.getSystemUiVisibility(navColorWin, null)
3516 & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
3517 } else if (navColorWin == opaqueOrDimming && navColorWin.isDimming()) {
3518 // Clear the light flag for dimming window.
3519 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
3520 }
3521 }
3522 return vis;
3523 }
3524
Tiger Huange218e422020-03-06 21:36:12 +08003525 @VisibleForTesting
3526 static int updateLightNavigationBarAppearanceLw(int appearance, WindowState opaque,
3527 WindowState opaqueOrDimming, WindowState imeWindow, WindowState navColorWin) {
3528
3529 if (navColorWin != null) {
3530 if (navColorWin == imeWindow || navColorWin == opaque) {
3531 // Respect the light flag.
3532 appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS;
3533 appearance |= navColorWin.mAttrs.insetsFlags.appearance
3534 & APPEARANCE_LIGHT_NAVIGATION_BARS;
3535 } else if (navColorWin == opaqueOrDimming && navColorWin.isDimming()) {
3536 // Clear the light flag for dimming window.
3537 appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS;
3538 }
3539 }
3540 return appearance;
3541 }
3542
3543 private Pair<Integer, WindowState> updateSystemBarsLw(WindowState win, int oldVis, int vis) {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07003544 final boolean dockedStackVisible = mDisplayContent.getDefaultTaskDisplayArea()
3545 .isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
3546 final boolean freeformStackVisible = mDisplayContent.getDefaultTaskDisplayArea()
3547 .isStackVisible(WINDOWING_MODE_FREEFORM);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003548 final boolean resizing = mDisplayContent.getDockedDividerController().isResizing();
3549
3550 // We need to force system bars when the docked stack is visible, when the freeform stack
hyok.kim332ccfc2019-07-02 15:39:43 +09003551 // is focused but also when we are resizing for the transitions when docked stack
Tiger Huang7c610aa2018-10-27 00:01:01 +08003552 // visibility changes.
hyok.kim332ccfc2019-07-02 15:39:43 +09003553 mForceShowSystemBars = dockedStackVisible || win.inFreeformWindowingMode() || resizing
Brad Stenninge0573692019-03-11 13:52:46 -07003554 || mForceShowSystemBarsFromExternal;
wilsonshihe8321942019-10-18 18:39:46 +08003555 final boolean forceOpaqueStatusBar = mForceShowSystemBars && !isKeyguardShowing();
Tiger Huang7c610aa2018-10-27 00:01:01 +08003556
3557 // apply translucent bar vis flags
wilsonshihe8321942019-10-18 18:39:46 +08003558 WindowState fullscreenTransWin = isKeyguardShowing() && !isKeyguardOccluded()
3559 ? mNotificationShade
Tiger Huang7c610aa2018-10-27 00:01:01 +08003560 : mTopFullscreenOpaqueWindowState;
3561 vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
3562 vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
Adrian Roosfaba4062019-05-14 15:27:17 +02003563 int dockedVis = mStatusBarController.applyTranslucentFlagLw(
Tiger Huang7c610aa2018-10-27 00:01:01 +08003564 mTopDockedOpaqueWindowState, 0, 0);
Adrian Roosfaba4062019-05-14 15:27:17 +02003565 dockedVis = mNavigationBarController.applyTranslucentFlagLw(
3566 mTopDockedOpaqueWindowState, dockedVis, 0);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003567
3568 final boolean fullscreenDrawsStatusBarBackground =
3569 drawsStatusBarBackground(vis, mTopFullscreenOpaqueWindowState);
3570 final boolean dockedDrawsStatusBarBackground =
3571 drawsStatusBarBackground(dockedVis, mTopDockedOpaqueWindowState);
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003572 final boolean fullscreenDrawsNavBarBackground =
3573 drawsNavigationBarBackground(vis, mTopFullscreenOpaqueWindowState);
Adrian Roosfaba4062019-05-14 15:27:17 +02003574 final boolean dockedDrawsNavigationBarBackground =
3575 drawsNavigationBarBackground(dockedVis, mTopDockedOpaqueWindowState);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003576
3577 // prevent status bar interaction from clearing certain flags
3578 int type = win.getAttrs().type;
wilsonshihe8321942019-10-18 18:39:46 +08003579 boolean notificationShadeHasFocus = type == TYPE_NOTIFICATION_SHADE;
3580 if (notificationShadeHasFocus && !isKeyguardShowing()) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08003581 int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
3582 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
3583 | View.SYSTEM_UI_FLAG_IMMERSIVE
3584 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
3585 | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
3586 if (isKeyguardOccluded()) {
3587 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
3588 }
3589 vis = (vis & ~flags) | (oldVis & flags);
3590 }
3591
3592 if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
3593 vis |= View.STATUS_BAR_TRANSPARENT;
3594 vis &= ~View.STATUS_BAR_TRANSLUCENT;
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003595 } else if (forceOpaqueStatusBar) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08003596 vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
3597 }
3598
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003599 vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing,
Adrian Roosfaba4062019-05-14 15:27:17 +02003600 fullscreenDrawsNavBarBackground, dockedDrawsNavigationBarBackground);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003601
3602 // update status bar
3603 boolean immersiveSticky =
3604 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
3605 final boolean hideStatusBarWM =
3606 mTopFullscreenOpaqueWindowState != null
3607 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
3608 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
3609 final boolean hideStatusBarSysui =
3610 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
3611 final boolean hideNavBarSysui =
3612 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
3613
3614 final boolean transientStatusBarAllowed = mStatusBar != null
wilsonshihe8321942019-10-18 18:39:46 +08003615 && (notificationShadeHasFocus || (!mForceShowSystemBars
Tiger Huang7c610aa2018-10-27 00:01:01 +08003616 && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
3617
3618 final boolean transientNavBarAllowed = mNavigationBar != null
3619 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
3620
3621 final long now = SystemClock.uptimeMillis();
3622 final boolean pendingPanic = mPendingPanicGestureUptime != 0
3623 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
3624 final DisplayPolicy defaultDisplayPolicy =
3625 mService.getDefaultDisplayContentLocked().getDisplayPolicy();
wilsonshihe8321942019-10-18 18:39:46 +08003626 if (pendingPanic && hideNavBarSysui && !isKeyguardShowing()
Tiger Huang7c610aa2018-10-27 00:01:01 +08003627 // TODO (b/111955725): Show keyguard presentation on all external displays
3628 && defaultDisplayPolicy.isKeyguardDrawComplete()) {
3629 // The user performed the panic gesture recently, we're about to hide the bars,
3630 // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
3631 mPendingPanicGestureUptime = 0;
3632 mStatusBarController.showTransient();
3633 if (!isNavBarEmpty(vis)) {
3634 mNavigationBarController.showTransient();
3635 }
3636 }
3637
3638 final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
3639 && !transientStatusBarAllowed && hideStatusBarSysui;
3640 final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
3641 && !transientNavBarAllowed;
3642 if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
3643 // clear the clearable flags instead
3644 clearClearableFlagsLw();
3645 vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
3646 }
3647
3648 final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
3649 immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
3650 final boolean navAllowedHidden = immersive || immersiveSticky;
3651
3652 if (hideNavBarSysui && !navAllowedHidden
3653 && mService.mPolicy.getWindowLayerLw(win)
3654 > mService.mPolicy.getWindowLayerFromTypeLw(TYPE_INPUT_CONSUMER)) {
3655 // We can't hide the navbar from this window otherwise the input consumer would not get
3656 // the input events.
3657 vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
3658 }
3659
3660 vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
3661
3662 // update navigation bar
Tiger Huangdd6db472020-02-13 21:38:46 +08003663 boolean newInsetsMode = ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL;
3664 boolean oldImmersiveMode = newInsetsMode ? mLastImmersiveMode : isImmersiveMode(oldVis);
3665 boolean newImmersiveMode = newInsetsMode ? isImmersiveMode(win) : isImmersiveMode(vis);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003666 if (oldImmersiveMode != newImmersiveMode) {
Tiger Huangdd6db472020-02-13 21:38:46 +08003667 mLastImmersiveMode = newImmersiveMode;
Tiger Huang7c610aa2018-10-27 00:01:01 +08003668 final String pkg = win.getOwningPackage();
3669 mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
3670 mService.mPolicy.isUserSetupComplete(),
3671 isNavBarEmpty(win.getSystemUiVisibility()));
3672 }
3673
3674 vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
3675
3676 final WindowState navColorWin = chooseNavigationColorWindowLw(
3677 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState,
3678 mDisplayContent.mInputMethodWindow, mNavigationBarPosition);
3679 vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState,
3680 mTopFullscreenOpaqueOrDimmingWindowState,
3681 mDisplayContent.mInputMethodWindow, navColorWin);
3682
Tiger Huange218e422020-03-06 21:36:12 +08003683 return Pair.create(vis, navColorWin);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003684 }
3685
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003686 private boolean drawsBarBackground(int vis, WindowState win, BarController controller,
3687 int translucentFlag) {
3688 if (!controller.isTransparentAllowed(win)) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08003689 return false;
3690 }
3691 if (win == null) {
3692 return true;
3693 }
3694
3695 final boolean drawsSystemBars =
3696 (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
3697 final boolean forceDrawsSystemBars =
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003698 (win.getAttrs().privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
Tiger Huang7c610aa2018-10-27 00:01:01 +08003699
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003700 return forceDrawsSystemBars || drawsSystemBars && (vis & translucentFlag) == 0;
3701 }
3702
3703 private boolean drawsStatusBarBackground(int vis, WindowState win) {
3704 return drawsBarBackground(vis, win, mStatusBarController, FLAG_TRANSLUCENT_STATUS);
3705 }
3706
3707 private boolean drawsNavigationBarBackground(int vis, WindowState win) {
3708 return drawsBarBackground(vis, win, mNavigationBarController, FLAG_TRANSLUCENT_NAVIGATION);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003709 }
3710
3711 /**
3712 * @return the current visibility flags with the nav-bar opacity related flags toggled based
3713 * on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
3714 */
3715 private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003716 boolean freeformStackVisible, boolean isDockedDividerResizing,
Adrian Roosfaba4062019-05-14 15:27:17 +02003717 boolean fullscreenDrawsBackground, boolean dockedDrawsNavigationBarBackground) {
3718 if (mNavBarOpacityMode == NAV_BAR_FORCE_TRANSPARENT) {
3719 if (fullscreenDrawsBackground && dockedDrawsNavigationBarBackground) {
3720 visibility = setNavBarTransparentFlag(visibility);
3721 } else if (dockedStackVisible) {
3722 visibility = setNavBarOpaqueFlag(visibility);
3723 }
3724 } else if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08003725 if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
HEO SEUNG22d3ec22019-05-30 20:28:53 +09003726 if (mIsFreeformWindowOverlappingWithNavBar) {
3727 visibility = setNavBarTranslucentFlag(visibility);
3728 } else {
3729 visibility = setNavBarOpaqueFlag(visibility);
3730 }
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003731 } else if (fullscreenDrawsBackground) {
3732 visibility = setNavBarTransparentFlag(visibility);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003733 }
3734 } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
3735 if (isDockedDividerResizing) {
3736 visibility = setNavBarOpaqueFlag(visibility);
3737 } else if (freeformStackVisible) {
3738 visibility = setNavBarTranslucentFlag(visibility);
3739 } else {
3740 visibility = setNavBarOpaqueFlag(visibility);
3741 }
3742 }
3743
Tiger Huang7c610aa2018-10-27 00:01:01 +08003744 return visibility;
3745 }
3746
3747 private int setNavBarOpaqueFlag(int visibility) {
3748 return visibility & ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
3749 }
3750
3751 private int setNavBarTranslucentFlag(int visibility) {
3752 visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
3753 return visibility | View.NAVIGATION_BAR_TRANSLUCENT;
3754 }
3755
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003756 private int setNavBarTransparentFlag(int visibility) {
3757 visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
3758 return visibility | View.NAVIGATION_BAR_TRANSPARENT;
3759 }
3760
Tiger Huang7c610aa2018-10-27 00:01:01 +08003761 private void clearClearableFlagsLw() {
3762 int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
3763 if (newVal != mResettingSystemUiFlags) {
3764 mResettingSystemUiFlags = newVal;
3765 mDisplayContent.reevaluateStatusBarVisibility();
3766 }
3767 }
3768
Tiger Huangdd6db472020-02-13 21:38:46 +08003769 // TODO(b/118118435): Remove this after migration
Tiger Huang7c610aa2018-10-27 00:01:01 +08003770 private boolean isImmersiveMode(int vis) {
3771 final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
3772 return mNavigationBar != null
3773 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
3774 && (vis & flags) != 0
3775 && canHideNavigationBar();
3776 }
3777
Tiger Huangdd6db472020-02-13 21:38:46 +08003778 private boolean isImmersiveMode(WindowState win) {
3779 final int behavior = win.mAttrs.insetsFlags.behavior;
3780 return mNavigationBar != null
3781 && canHideNavigationBar()
3782 && (behavior == BEHAVIOR_SHOW_BARS_BY_SWIPE
3783 || behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE)
3784 && getInsetsPolicy().isHidden(ITYPE_NAVIGATION_BAR)
Galia Peychevaada77ce2020-06-22 16:36:41 +02003785 && win != getNotificationShade()
3786 && !win.isActivityTypeDream();
Tiger Huangdd6db472020-02-13 21:38:46 +08003787 }
3788
Tiger Huang7c610aa2018-10-27 00:01:01 +08003789 /**
3790 * @return whether the navigation bar can be hidden, e.g. the device has a navigation bar
3791 */
3792 private boolean canHideNavigationBar() {
3793 return hasNavigationBar();
3794 }
3795
3796 private static boolean isNavBarEmpty(int systemUiFlags) {
3797 final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
3798 | View.STATUS_BAR_DISABLE_BACK
3799 | View.STATUS_BAR_DISABLE_RECENT);
3800
3801 return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
3802 }
3803
Tiger Huang7c610aa2018-10-27 00:01:01 +08003804 private final Runnable mHiddenNavPanic = new Runnable() {
3805 @Override
3806 public void run() {
3807 synchronized (mLock) {
3808 if (!mService.mPolicy.isUserSetupComplete()) {
3809 // Swipe-up for navigation bar is disabled during setup
3810 return;
3811 }
3812 mPendingPanicGestureUptime = SystemClock.uptimeMillis();
3813 if (!isNavBarEmpty(mLastSystemUiFlags)) {
3814 mNavigationBarController.showTransient();
Jorim Jaggi956ca412019-01-07 14:49:14 +01003815 mDisplayContent.getInsetsPolicy().showTransient(IntArray.wrap(
Tiger Huang332793b2019-10-29 23:21:27 +08003816 new int[] {ITYPE_NAVIGATION_BAR}));
Tiger Huang7c610aa2018-10-27 00:01:01 +08003817 }
3818 }
3819 }
3820 };
3821
3822 void onPowerKeyDown(boolean isScreenOn) {
3823 // Detect user pressing the power button in panic when an application has
3824 // taken over the whole screen.
3825 boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(isScreenOn,
3826 SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags),
3827 isNavBarEmpty(mLastSystemUiFlags));
3828 if (panic) {
3829 mHandler.post(mHiddenNavPanic);
3830 }
3831 }
3832
3833 void onVrStateChangedLw(boolean enabled) {
3834 mImmersiveModeConfirmation.onVrStateChangedLw(enabled);
3835 }
3836
3837 /**
3838 * Called when the state of lock task mode changes. This should be used to disable immersive
3839 * mode confirmation.
3840 *
3841 * @param lockTaskState the new lock task mode state. One of
3842 * {@link ActivityManager#LOCK_TASK_MODE_NONE},
3843 * {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
3844 * {@link ActivityManager#LOCK_TASK_MODE_PINNED}.
3845 */
3846 public void onLockTaskStateChangedLw(int lockTaskState) {
3847 mImmersiveModeConfirmation.onLockTaskModeChangedLw(lockTaskState);
3848 }
3849
3850 /**
3851 * Request a screenshot be taken.
3852 *
3853 * @param screenshotType The type of screenshot, for example either
3854 * {@link WindowManager#TAKE_SCREENSHOT_FULLSCREEN} or
3855 * {@link WindowManager#TAKE_SCREENSHOT_SELECTED_REGION}
Miranda Kephart7b2c3132020-03-27 09:54:14 -04003856 * @param source Where the screenshot originated from (see WindowManager.ScreenshotSource)
Tiger Huang7c610aa2018-10-27 00:01:01 +08003857 */
Miranda Kephart7b2c3132020-03-27 09:54:14 -04003858 public void takeScreenshot(int screenshotType, int source) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08003859 if (mScreenshotHelper != null) {
3860 mScreenshotHelper.takeScreenshot(screenshotType,
3861 mStatusBar != null && mStatusBar.isVisibleLw(),
James O'Learyfa5bb7a2019-09-05 13:43:29 -04003862 mNavigationBar != null && mNavigationBar.isVisibleLw(),
Miranda Kephart7b2c3132020-03-27 09:54:14 -04003863 source, mHandler, null /* completionConsumer */);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003864 }
3865 }
3866
Ady Abrahamf3e05312019-05-13 18:04:59 -07003867 RefreshRatePolicy getRefreshRatePolicy() {
3868 return mRefreshRatePolicy;
3869 }
3870
Riddle Hsu5ce4bb32018-07-18 16:11:30 +08003871 void dump(String prefix, PrintWriter pw) {
Riddle Hsuccf09402019-08-13 00:33:06 +08003872 pw.print(prefix); pw.println("DisplayPolicy");
Tiger Huang7c610aa2018-10-27 00:01:01 +08003873 prefix += " ";
3874 pw.print(prefix);
3875 pw.print("mCarDockEnablesAccelerometer="); pw.print(mCarDockEnablesAccelerometer);
3876 pw.print(" mDeskDockEnablesAccelerometer=");
3877 pw.println(mDeskDockEnablesAccelerometer);
3878 pw.print(prefix); pw.print("mDockMode="); pw.print(Intent.dockStateToString(mDockMode));
3879 pw.print(" mLidState="); pw.println(WindowManagerFuncs.lidStateToString(mLidState));
3880 pw.print(prefix); pw.print("mAwake="); pw.print(mAwake);
3881 pw.print(" mScreenOnEarly="); pw.print(mScreenOnEarly);
3882 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
3883 pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
3884 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
3885 pw.print(prefix); pw.print("mHdmiPlugged="); pw.println(mHdmiPlugged);
3886 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
3887 || mForceClearedSystemUiFlags != 0) {
3888 pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
3889 pw.print(Integer.toHexString(mLastSystemUiFlags));
3890 pw.print(" mResettingSystemUiFlags=0x");
3891 pw.print(Integer.toHexString(mResettingSystemUiFlags));
3892 pw.print(" mForceClearedSystemUiFlags=0x");
3893 pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
3894 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08003895 pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
3896 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003897 if (mStatusBar != null) {
3898 pw.print(prefix); pw.print("mStatusBar="); pw.print(mStatusBar);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003899 }
wilsonshihe8321942019-10-18 18:39:46 +08003900 if (mNotificationShade != null) {
3901 pw.print(prefix); pw.print("mExpandedPanel="); pw.print(mNotificationShade);
3902 }
3903 pw.print(" isKeyguardShowing="); pw.println(isKeyguardShowing());
Tiger Huang7c610aa2018-10-27 00:01:01 +08003904 if (mNavigationBar != null) {
3905 pw.print(prefix); pw.print("mNavigationBar="); pw.println(mNavigationBar);
Winson Chung4723b4e2019-03-25 16:49:36 -07003906 pw.print(prefix); pw.print("mNavBarOpacityMode="); pw.println(mNavBarOpacityMode);
3907 pw.print(prefix); pw.print("mNavigationBarCanMove="); pw.println(mNavigationBarCanMove);
3908 pw.print(prefix); pw.print("mNavigationBarPosition=");
3909 pw.println(mNavigationBarPosition);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003910 }
3911 if (mFocusedWindow != null) {
3912 pw.print(prefix); pw.print("mFocusedWindow="); pw.println(mFocusedWindow);
3913 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08003914 if (mTopFullscreenOpaqueWindowState != null) {
3915 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
3916 pw.println(mTopFullscreenOpaqueWindowState);
3917 }
3918 if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
3919 pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
3920 pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
3921 }
3922 if (mForcingShowNavBar) {
3923 pw.print(prefix); pw.print("mForcingShowNavBar="); pw.println(mForcingShowNavBar);
3924 pw.print(prefix); pw.print("mForcingShowNavBarLayer=");
3925 pw.println(mForcingShowNavBarLayer);
3926 }
Riddle Hsuccf09402019-08-13 00:33:06 +08003927 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.println(mTopIsFullscreen);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003928 pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
Riddle Hsuccf09402019-08-13 00:33:06 +08003929 pw.print(prefix); pw.print("mForceShowSystemBarsFromExternal=");
3930 pw.print(mForceShowSystemBarsFromExternal);
3931 pw.print(" mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003932 mStatusBarController.dump(pw, prefix);
3933 mNavigationBarController.dump(pw, prefix);
3934
3935 pw.print(prefix); pw.println("Looper state:");
3936 mHandler.getLooper().dump(new PrintWriterPrinter(pw), prefix + " ");
Riddle Hsu5ce4bb32018-07-18 16:11:30 +08003937 }
Arthur Hung20479922019-02-27 17:13:22 +08003938
3939 private boolean supportsPointerLocation() {
3940 return mDisplayContent.isDefaultDisplay || !mDisplayContent.isPrivate();
3941 }
3942
3943 void setPointerLocationEnabled(boolean pointerLocationEnabled) {
3944 if (!supportsPointerLocation()) {
3945 return;
3946 }
3947
3948 mHandler.sendEmptyMessage(pointerLocationEnabled
3949 ? MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
3950 }
3951
3952 private void enablePointerLocation() {
3953 if (mPointerLocationView != null) {
3954 return;
3955 }
3956
3957 mPointerLocationView = new PointerLocationView(mContext);
3958 mPointerLocationView.setPrintCoords(false);
3959 final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
3960 WindowManager.LayoutParams.MATCH_PARENT,
3961 WindowManager.LayoutParams.MATCH_PARENT);
3962 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
Arthur Hungaf7f6a92020-03-16 19:17:47 +08003963 lp.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
Arthur Hung20479922019-02-27 17:13:22 +08003964 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
3965 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
Arthur Hungaf7f6a92020-03-16 19:17:47 +08003966 lp.setFitInsetsTypes(0);
Arthur Hung20479922019-02-27 17:13:22 +08003967 lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
3968 if (ActivityManager.isHighEndGfx()) {
3969 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
3970 lp.privateFlags |=
3971 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
3972 }
3973 lp.format = PixelFormat.TRANSLUCENT;
3974 lp.setTitle("PointerLocation - display " + getDisplayId());
3975 lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
3976 final WindowManager wm = mContext.getSystemService(WindowManager.class);
3977 wm.addView(mPointerLocationView, lp);
3978 mDisplayContent.registerPointerEventListener(mPointerLocationView);
3979 }
3980
3981 private void disablePointerLocation() {
3982 if (mPointerLocationView == null) {
3983 return;
3984 }
3985
3986 mDisplayContent.unregisterPointerEventListener(mPointerLocationView);
3987 final WindowManager wm = mContext.getSystemService(WindowManager.class);
3988 wm.removeView(mPointerLocationView);
3989 mPointerLocationView = null;
3990 }
HEO SEUNG22d3ec22019-05-30 20:28:53 +09003991
Arthur Hungfbc8f412019-08-01 19:57:54 +08003992 /**
3993 * Check if the window could be excluded from checking if the display has content.
3994 *
3995 * @param w WindowState to check if should be excluded.
3996 * @return True if the window type is PointerLocation which is excluded.
3997 */
3998 boolean isWindowExcludedFromContent(WindowState w) {
3999 if (w != null && mPointerLocationView != null) {
4000 return w.mClient == mPointerLocationView.getWindowToken();
4001 }
4002
4003 return false;
4004 }
4005
Mehdi Alizadehf2b28e92019-12-05 20:13:49 -08004006 void release() {
4007 mHandler.post(mGestureNavigationSettingsObserver::unregister);
4008 }
4009
HEO SEUNG22d3ec22019-05-30 20:28:53 +09004010 @VisibleForTesting
4011 static boolean isOverlappingWithNavBar(WindowState targetWindow, WindowState navBarWindow) {
4012 if (navBarWindow == null || !navBarWindow.isVisibleLw()
Garfield Tane8d84ab2019-10-11 09:49:40 -07004013 || targetWindow.mActivityRecord == null || !targetWindow.isVisibleLw()) {
HEO SEUNG22d3ec22019-05-30 20:28:53 +09004014 return false;
4015 }
4016
4017 return Rect.intersects(targetWindow.getFrameLw(), navBarWindow.getFrameLw());
4018 }
Riddle Hsu5ce4bb32018-07-18 16:11:30 +08004019}