blob: eb5cff6d5ad856b8b4008bdec78cd2269a071bf1 [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;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800154import android.view.DisplayCutout;
155import android.view.Gravity;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800156import android.view.InputChannel;
157import android.view.InputDevice;
158import android.view.InputEvent;
159import android.view.InputEventReceiver;
Tiger Huang0dbd5372019-10-26 00:24:22 +0800160import android.view.InsetsFlags;
Tiger Huang9ff42bd2020-05-01 03:27:33 +0800161import android.view.InsetsSource;
Tiger Huang4a7835f2019-11-06 00:07:56 +0800162import android.view.InsetsState;
Tiger Huang332793b2019-10-29 23:21:27 +0800163import android.view.InsetsState.InternalInsetsType;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800164import android.view.MotionEvent;
165import android.view.PointerIcon;
166import android.view.Surface;
167import android.view.View;
Jorim Jaggi648e5882019-01-24 13:24:02 +0100168import android.view.ViewRootImpl;
Tiger Huang4a7835f2019-11-06 00:07:56 +0800169import android.view.WindowInsets.Side;
170import android.view.WindowInsets.Side.InsetsSide;
171import android.view.WindowInsets.Type;
172import android.view.WindowInsets.Type.InsetsType;
Tiger Huang0dbd5372019-10-26 00:24:22 +0800173import android.view.WindowInsetsController.Appearance;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800174import android.view.WindowManager;
175import android.view.WindowManager.LayoutParams;
176import android.view.WindowManagerGlobal;
177import android.view.WindowManagerPolicyConstants;
178import android.view.accessibility.AccessibilityManager;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800179
Tiger Huang7c610aa2018-10-27 00:01:01 +0800180import com.android.internal.R;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800181import com.android.internal.annotations.VisibleForTesting;
Mehdi Alizadehf2b28e92019-12-05 20:13:49 -0800182import com.android.internal.policy.GestureNavigationSettingsObserver;
Tiger Huang43b8fc22019-04-26 11:49:29 +0800183import com.android.internal.policy.ScreenDecorationsUtils;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800184import com.android.internal.util.ScreenshotHelper;
Adrian Roos11dfd272019-03-25 19:21:26 +0100185import com.android.internal.util.function.TriConsumer;
Jorim Jaggi956ca412019-01-07 14:49:14 +0100186import com.android.internal.view.AppearanceRegion;
Arthur Hung20479922019-02-27 17:13:22 +0800187import com.android.internal.widget.PointerLocationView;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800188import com.android.server.LocalServices;
189import com.android.server.UiThread;
190import com.android.server.policy.WindowManagerPolicy;
191import com.android.server.policy.WindowManagerPolicy.InputConsumer;
192import com.android.server.policy.WindowManagerPolicy.NavigationBarPosition;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800193import com.android.server.policy.WindowManagerPolicy.ScreenOnListener;
194import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800195import com.android.server.policy.WindowOrientationListener;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200196import com.android.server.protolog.common.ProtoLog;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800197import com.android.server.statusbar.StatusBarManagerInternal;
wilsonshih643bf132019-02-27 12:49:19 +0800198import com.android.server.wallpaper.WallpaperManagerInternal;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800199import com.android.server.wm.utils.InsetUtils;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800200
201import java.io.PrintWriter;
202
203/**
204 * The policy that provides the basic behaviors and states of a display to show UI.
205 */
206public class DisplayPolicy {
207 private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayPolicy" : TAG_WM;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800208 private static final boolean DEBUG = false;
209
210 private static final boolean ALTERNATE_CAR_MODE_NAV_SIZE = false;
211
212 // The panic gesture may become active only after the keyguard is dismissed and the immersive
213 // app shows again. If that doesn't happen for 30s we drop the gesture.
214 private static final long PANIC_GESTURE_EXPIRATION = 30000;
215
216 // Controls navigation bar opacity depending on which workspace stacks are currently
217 // visible.
218 // Nav bar is always opaque when either the freeform stack or docked stack is visible.
219 private static final int NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED = 0;
220 // Nav bar is always translucent when the freeform stack is visible, otherwise always opaque.
221 private static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1;
Adrian Roosfaba4062019-05-14 15:27:17 +0200222 // Nav bar is never forced opaque.
223 private static final int NAV_BAR_FORCE_TRANSPARENT = 2;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800224
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800225 /** Don't apply window animation (see {@link #selectAnimation}). */
226 static final int ANIMATION_NONE = -1;
227 /** Use the transit animation in style resource (see {@link #selectAnimation}). */
228 static final int ANIMATION_STYLEABLE = 0;
229
Tiger Huang7c610aa2018-10-27 00:01:01 +0800230 /**
231 * These are the system UI flags that, when changing, can cause the layout
232 * of the screen to change.
233 */
234 private static final int SYSTEM_UI_CHANGING_LAYOUT =
235 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
236 | View.SYSTEM_UI_FLAG_FULLSCREEN
237 | View.STATUS_BAR_TRANSLUCENT
238 | View.NAVIGATION_BAR_TRANSLUCENT
239 | View.STATUS_BAR_TRANSPARENT
240 | View.NAVIGATION_BAR_TRANSPARENT;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800241
242 private final WindowManagerService mService;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800243 private final Context mContext;
Charles Chen173ae782019-11-11 20:39:02 +0800244 private final Context mUiContext;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800245 private final DisplayContent mDisplayContent;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800246 private final Object mLock;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800247 private final Handler mHandler;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800248
Winson Chungda20fec2019-04-10 12:19:59 -0700249 private Resources mCurrentUserResources;
250
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800251 private final boolean mCarDockEnablesAccelerometer;
252 private final boolean mDeskDockEnablesAccelerometer;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800253 private final AccessibilityManager mAccessibilityManager;
254 private final ImmersiveModeConfirmation mImmersiveModeConfirmation;
255 private final ScreenshotHelper mScreenshotHelper;
256
257 private final Object mServiceAcquireLock = new Object();
258 private StatusBarManagerInternal mStatusBarManagerInternal;
259
Adrian Roos11dfd272019-03-25 19:21:26 +0100260 @Px
261 private int mBottomGestureAdditionalInset;
262 @Px
Mehdi Alizadehf2b28e92019-12-05 20:13:49 -0800263 private int mLeftGestureInset;
264 @Px
265 private int mRightGestureInset;
Adrian Roos11dfd272019-03-25 19:21:26 +0100266
Sunny Goyal38412952020-04-17 11:35:37 -0700267 private boolean mNavButtonForcedVisible;
268
Jorim Jaggi956ca412019-01-07 14:49:14 +0100269 StatusBarManagerInternal getStatusBarManagerInternal() {
Tiger Huang7c610aa2018-10-27 00:01:01 +0800270 synchronized (mServiceAcquireLock) {
271 if (mStatusBarManagerInternal == null) {
272 mStatusBarManagerInternal =
273 LocalServices.getService(StatusBarManagerInternal.class);
274 }
275 return mStatusBarManagerInternal;
276 }
277 }
278
Tiger Huang7c610aa2018-10-27 00:01:01 +0800279 private final SystemGesturesPointerEventListener mSystemGestures;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800280
281 private volatile int mLidState = LID_ABSENT;
282 private volatile int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
283 private volatile boolean mHdmiPlugged;
284
Louis Changfc64c832018-12-04 11:38:26 +0800285 private volatile boolean mHasStatusBar;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800286 private volatile boolean mHasNavigationBar;
287 // Can the navigation bar ever move to the side?
288 private volatile boolean mNavigationBarCanMove;
Winson Chung36941632019-04-19 15:21:38 -0700289 private volatile boolean mNavigationBarLetsThroughTaps;
290 private volatile boolean mNavigationBarAlwaysShowOnSideGesture;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800291
292 // Written by vr manager thread, only read in this class.
293 private volatile boolean mPersistentVrModeEnabled;
294
295 private volatile boolean mAwake;
296 private volatile boolean mScreenOnEarly;
297 private volatile boolean mScreenOnFully;
298 private volatile ScreenOnListener mScreenOnListener;
299
300 private volatile boolean mKeyguardDrawComplete;
301 private volatile boolean mWindowManagerDrawComplete;
302
Tiger Huang7c610aa2018-10-27 00:01:01 +0800303 private final ArraySet<WindowState> mScreenDecorWindows = new ArraySet<>();
304 private WindowState mStatusBar = null;
wilsonshihe8321942019-10-18 18:39:46 +0800305 private WindowState mNotificationShade = null;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800306 private final int[] mStatusBarHeightForRotation = new int[4];
307 private WindowState mNavigationBar = null;
308 @NavigationBarPosition
309 private int mNavigationBarPosition = NAV_BAR_BOTTOM;
310 private int[] mNavigationBarHeightForRotationDefault = new int[4];
311 private int[] mNavigationBarWidthForRotationDefault = new int[4];
312 private int[] mNavigationBarHeightForRotationInCarMode = new int[4];
313 private int[] mNavigationBarWidthForRotationInCarMode = new int[4];
314
Matthew Nga7f24bc2019-04-09 17:06:41 -0700315 /** See {@link #getNavigationBarFrameHeight} */
316 private int[] mNavigationBarFrameHeightForRotationDefault = new int[4];
317
HEO SEUNG22d3ec22019-05-30 20:28:53 +0900318 private boolean mIsFreeformWindowOverlappingWithNavBar;
319
Tiger Huangdd6db472020-02-13 21:38:46 +0800320 private boolean mLastImmersiveMode;
321
Riddle Hsud80ae9b2019-03-26 00:40:35 +0800322 private final StatusBarController mStatusBarController;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800323
Riddle Hsud80ae9b2019-03-26 00:40:35 +0800324 private final BarController mNavigationBarController;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800325
326 private final BarController.OnBarVisibilityChangedListener mNavBarVisibilityListener =
327 new BarController.OnBarVisibilityChangedListener() {
328 @Override
329 public void onBarVisibilityChanged(boolean visible) {
330 if (mAccessibilityManager == null) {
331 return;
332 }
333 mAccessibilityManager.notifyAccessibilityButtonVisibilityChanged(visible);
334 }
335 };
336
Tiger Huang7c610aa2018-10-27 00:01:01 +0800337 // The windows we were told about in focusChanged.
338 private WindowState mFocusedWindow;
339 private WindowState mLastFocusedWindow;
340
Riddle Hsuc7175762020-01-10 21:03:48 +0800341 // The states of decor windows from the last layout. These are used to generate another display
342 // layout in different bounds but with the same states.
343 private boolean mLastNavVisible;
344 private boolean mLastNavTranslucent;
345 private boolean mLastNavAllowedHidden;
346 private boolean mLastNotificationShadeForcesShowingNavigation;
347
Tiger Huang7c610aa2018-10-27 00:01:01 +0800348 int mLastSystemUiFlags;
349 // Bits that we are in the process of clearing, so we want to prevent
350 // them from being set by applications until everything has been updated
351 // to have them clear.
352 private int mResettingSystemUiFlags = 0;
353 // Bits that we are currently always keeping cleared.
354 private int mForceClearedSystemUiFlags = 0;
Jorim Jaggi956ca412019-01-07 14:49:14 +0100355 private int mLastAppearance;
356 private int mLastFullscreenAppearance;
357 private int mLastDockedAppearance;
Tiger Huang4a7835f2019-11-06 00:07:56 +0800358 private int mLastBehavior;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800359 private final Rect mNonDockedStackBounds = new Rect();
360 private final Rect mDockedStackBounds = new Rect();
361 private final Rect mLastNonDockedStackBounds = new Rect();
362 private final Rect mLastDockedStackBounds = new Rect();
363
Jorim Jaggi956ca412019-01-07 14:49:14 +0100364 // What we last reported to system UI about whether the focused window is fullscreen/immersive.
365 private boolean mLastFocusIsFullscreen = false;
366 private boolean mLastFocusIsImmersive = false;
367
Tiger Huang7c610aa2018-10-27 00:01:01 +0800368 // If nonzero, a panic gesture was performed at that time in uptime millis and is still pending.
369 private long mPendingPanicGestureUptime;
370
371 private static final Rect sTmpDisplayCutoutSafeExceptMaybeBarsRect = new Rect();
372 private static final Rect sTmpRect = new Rect();
Tiger Huang7c610aa2018-10-27 00:01:01 +0800373 private static final Rect sTmpNavFrame = new Rect();
374 private static final Rect sTmpLastParentFrame = new Rect();
375
376 private WindowState mTopFullscreenOpaqueWindowState;
377 private WindowState mTopFullscreenOpaqueOrDimmingWindowState;
378 private WindowState mTopDockedOpaqueWindowState;
379 private WindowState mTopDockedOpaqueOrDimmingWindowState;
380 private boolean mTopIsFullscreen;
381 private boolean mForceStatusBar;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800382 private int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
383 private boolean mForcingShowNavBar;
384 private int mForcingShowNavBarLayer;
385 private boolean mForceShowSystemBars;
386
Brad Stenninge0573692019-03-11 13:52:46 -0700387 /**
388 * Force the display of system bars regardless of other settings.
389 */
390 private boolean mForceShowSystemBarsFromExternal;
391
Tiger Huang7c610aa2018-10-27 00:01:01 +0800392 private boolean mShowingDream;
393 private boolean mLastShowingDream;
394 private boolean mDreamingLockscreen;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800395 private boolean mAllowLockscreenWhenOn;
396
Tiger Huang9ff42bd2020-05-01 03:27:33 +0800397 @VisibleForTesting
398 InputConsumer mInputConsumer = null;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800399
Arthur Hung20479922019-02-27 17:13:22 +0800400 private PointerLocationView mPointerLocationView;
401
Issei Suzukia5dbf522019-02-01 17:58:15 +0100402 /**
403 * The area covered by system windows which belong to another display. Forwarded insets is set
404 * in case this is a virtual display, this is displayed on another display that has insets, and
405 * the bounds of this display is overlapping with the insets of the host display (e.g. IME is
406 * displayed on the host display, and it covers a part of this virtual display.)
407 * The forwarded insets is used to compute display frames of this virtual display, which will
408 * be then used to layout windows in the virtual display.
409 */
410 @NonNull private Insets mForwardedInsets = Insets.NONE;
411
Ady Abrahamf3e05312019-05-13 18:04:59 -0700412 private RefreshRatePolicy mRefreshRatePolicy;
413
Tiger Huang7c610aa2018-10-27 00:01:01 +0800414 // -------- PolicyHandler --------
Tiger Huang7c610aa2018-10-27 00:01:01 +0800415 private static final int MSG_REQUEST_TRANSIENT_BARS = 2;
416 private static final int MSG_DISPOSE_INPUT_CONSUMER = 3;
Arthur Hung20479922019-02-27 17:13:22 +0800417 private static final int MSG_ENABLE_POINTER_LOCATION = 4;
418 private static final int MSG_DISABLE_POINTER_LOCATION = 5;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800419
420 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
421 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
422
Mehdi Alizadehf2b28e92019-12-05 20:13:49 -0800423 private final GestureNavigationSettingsObserver mGestureNavigationSettingsObserver;
424
Tiger Huang7c610aa2018-10-27 00:01:01 +0800425 private class PolicyHandler extends Handler {
426
427 PolicyHandler(Looper looper) {
428 super(looper);
429 }
430
431 @Override
432 public void handleMessage(Message msg) {
433 switch (msg.what) {
Tiger Huang7c610aa2018-10-27 00:01:01 +0800434 case MSG_REQUEST_TRANSIENT_BARS:
Tiger Huang82fd0ad2020-03-09 17:55:47 +0800435 synchronized (mLock) {
436 WindowState targetBar = (msg.arg1 == MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS)
437 ? mStatusBar : mNavigationBar;
438 if (targetBar != null) {
439 requestTransientBars(targetBar);
440 }
Tiger Huang7c610aa2018-10-27 00:01:01 +0800441 }
442 break;
443 case MSG_DISPOSE_INPUT_CONSUMER:
444 disposeInputConsumer((InputConsumer) msg.obj);
445 break;
Arthur Hung20479922019-02-27 17:13:22 +0800446 case MSG_ENABLE_POINTER_LOCATION:
447 enablePointerLocation();
448 break;
449 case MSG_DISABLE_POINTER_LOCATION:
450 disablePointerLocation();
451 break;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800452 }
453 }
454 }
455
456 DisplayPolicy(WindowManagerService service, DisplayContent displayContent) {
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800457 mService = service;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800458 mContext = displayContent.isDefaultDisplay ? service.mContext
459 : service.mContext.createDisplayContext(displayContent.getDisplay());
Charles Chen173ae782019-11-11 20:39:02 +0800460 mUiContext = displayContent.isDefaultDisplay ? service.mAtmService.mUiContext
461 : service.mAtmService.mSystemThread
462 .createSystemUiContext(displayContent.getDisplayId());
Tiger Huang7c610aa2018-10-27 00:01:01 +0800463 mDisplayContent = displayContent;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800464 mLock = service.getWindowManagerLock();
Tiger Huang7c610aa2018-10-27 00:01:01 +0800465
Riddle Hsud80ae9b2019-03-26 00:40:35 +0800466 final int displayId = displayContent.getDisplayId();
467 mStatusBarController = new StatusBarController(displayId);
468 mNavigationBarController = new BarController("NavigationBar",
469 displayId,
470 View.NAVIGATION_BAR_TRANSIENT,
471 View.NAVIGATION_BAR_UNHIDE,
472 View.NAVIGATION_BAR_TRANSLUCENT,
473 StatusBarManager.WINDOW_NAVIGATION_BAR,
474 FLAG_TRANSLUCENT_NAVIGATION,
475 View.NAVIGATION_BAR_TRANSPARENT);
476
Tiger Huang7c610aa2018-10-27 00:01:01 +0800477 final Resources r = mContext.getResources();
478 mCarDockEnablesAccelerometer = r.getBoolean(R.bool.config_carDockEnablesAccelerometer);
479 mDeskDockEnablesAccelerometer = r.getBoolean(R.bool.config_deskDockEnablesAccelerometer);
Brad Stenninge0573692019-03-11 13:52:46 -0700480 mForceShowSystemBarsFromExternal = r.getBoolean(R.bool.config_forceShowSystemBars);
Tiger Huang7c610aa2018-10-27 00:01:01 +0800481
482 mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(
483 Context.ACCESSIBILITY_SERVICE);
484 if (!displayContent.isDefaultDisplay) {
485 mAwake = true;
486 mScreenOnEarly = true;
487 mScreenOnFully = true;
488 }
489
490 final Looper looper = UiThread.getHandler().getLooper();
491 mHandler = new PolicyHandler(looper);
492 mSystemGestures = new SystemGesturesPointerEventListener(mContext, mHandler,
493 new SystemGesturesPointerEventListener.Callbacks() {
494 @Override
495 public void onSwipeFromTop() {
Tiger Huang82fd0ad2020-03-09 17:55:47 +0800496 synchronized (mLock) {
497 if (mStatusBar != null) {
498 requestTransientBars(mStatusBar);
499 }
Tiger Huang7c610aa2018-10-27 00:01:01 +0800500 }
501 }
502
503 @Override
504 public void onSwipeFromBottom() {
Tiger Huang82fd0ad2020-03-09 17:55:47 +0800505 synchronized (mLock) {
506 if (mNavigationBar != null
507 && mNavigationBarPosition == NAV_BAR_BOTTOM) {
508 requestTransientBars(mNavigationBar);
509 }
Tiger Huang7c610aa2018-10-27 00:01:01 +0800510 }
511 }
512
513 @Override
514 public void onSwipeFromRight() {
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200515 final Region excludedRegion = Region.obtain();
Jeff Chang3cf3e562019-06-18 11:51:25 +0800516 synchronized (mLock) {
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200517 mDisplayContent.calculateSystemGestureExclusion(
518 excludedRegion, null /* outUnrestricted */);
Tiger Huang82fd0ad2020-03-09 17:55:47 +0800519 final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
520 || mNavigationBarPosition == NAV_BAR_RIGHT;
521 if (mNavigationBar != null && sideAllowed
522 && !mSystemGestures.currentGestureStartedInRegion(
523 excludedRegion)) {
524 requestTransientBars(mNavigationBar);
525 }
Tiger Huang7c610aa2018-10-27 00:01:01 +0800526 }
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200527 excludedRegion.recycle();
Tiger Huang7c610aa2018-10-27 00:01:01 +0800528 }
529
530 @Override
531 public void onSwipeFromLeft() {
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200532 final Region excludedRegion = Region.obtain();
Jeff Chang3cf3e562019-06-18 11:51:25 +0800533 synchronized (mLock) {
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200534 mDisplayContent.calculateSystemGestureExclusion(
535 excludedRegion, null /* outUnrestricted */);
Tiger Huang82fd0ad2020-03-09 17:55:47 +0800536 final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
537 || mNavigationBarPosition == NAV_BAR_LEFT;
538 if (mNavigationBar != null && sideAllowed
539 && !mSystemGestures.currentGestureStartedInRegion(
540 excludedRegion)) {
541 requestTransientBars(mNavigationBar);
542 }
Tiger Huang7c610aa2018-10-27 00:01:01 +0800543 }
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200544 excludedRegion.recycle();
Tiger Huang7c610aa2018-10-27 00:01:01 +0800545 }
546
547 @Override
548 public void onFling(int duration) {
549 if (mService.mPowerManagerInternal != null) {
550 mService.mPowerManagerInternal.powerHint(
551 PowerHint.INTERACTION, duration);
552 }
553 }
554
555 @Override
556 public void onDebug() {
557 // no-op
558 }
559
560 private WindowOrientationListener getOrientationListener() {
561 final DisplayRotation rotation = mDisplayContent.getDisplayRotation();
562 return rotation != null ? rotation.getOrientationListener() : null;
563 }
564
565 @Override
566 public void onDown() {
567 final WindowOrientationListener listener = getOrientationListener();
568 if (listener != null) {
569 listener.onTouchStart();
570 }
571 }
572
573 @Override
574 public void onUpOrCancel() {
575 final WindowOrientationListener listener = getOrientationListener();
576 if (listener != null) {
577 listener.onTouchEnd();
578 }
579 }
580
581 @Override
582 public void onMouseHoverAtTop() {
583 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
584 Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
585 msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
586 mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
587 }
588
589 @Override
590 public void onMouseHoverAtBottom() {
591 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
592 Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
593 msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
594 mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
595 }
596
597 @Override
598 public void onMouseLeaveFromEdge() {
599 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
600 }
601 });
602 displayContent.registerPointerEventListener(mSystemGestures);
603 displayContent.mAppTransition.registerListenerLocked(
604 mStatusBarController.getAppTransitionListener());
605 mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext, looper,
606 mService.mVrModeEnabled);
Tiger Huang7c610aa2018-10-27 00:01:01 +0800607
608 // TODO: Make it can take screenshot on external display
609 mScreenshotHelper = displayContent.isDefaultDisplay
610 ? new ScreenshotHelper(mContext) : null;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800611
Tiger Huang7c610aa2018-10-27 00:01:01 +0800612 if (mDisplayContent.isDefaultDisplay) {
Louis Changfc64c832018-12-04 11:38:26 +0800613 mHasStatusBar = true;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800614 mHasNavigationBar = mContext.getResources().getBoolean(R.bool.config_showNavigationBar);
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800615
Tiger Huang7c610aa2018-10-27 00:01:01 +0800616 // Allow a system property to override this. Used by the emulator.
617 // See also hasNavigationBar().
618 String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
619 if ("1".equals(navBarOverride)) {
620 mHasNavigationBar = false;
621 } else if ("0".equals(navBarOverride)) {
622 mHasNavigationBar = true;
623 }
624 } else {
Louis Changfc64c832018-12-04 11:38:26 +0800625 mHasStatusBar = false;
Andrii Kuliandd989612019-02-21 12:13:28 -0800626 mHasNavigationBar = mDisplayContent.supportsSystemDecorations();
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800627 }
Ady Abrahamf3e05312019-05-13 18:04:59 -0700628
629 mRefreshRatePolicy = new RefreshRatePolicy(mService,
630 mDisplayContent.getDisplayInfo(),
631 mService.mHighRefreshRateBlacklist);
Mehdi Alizadehf2b28e92019-12-05 20:13:49 -0800632
633 mGestureNavigationSettingsObserver = new GestureNavigationSettingsObserver(mHandler,
634 mContext, () -> {
635 synchronized (mLock) {
636 onConfigurationChanged();
637 mSystemGestures.onConfigurationChanged();
638 mDisplayContent.updateSystemGestureExclusion();
639 }
640 });
641 mHandler.post(mGestureNavigationSettingsObserver::register);
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800642 }
643
Charles Chen5bdd3e22018-12-18 17:51:56 +0800644 void systemReady() {
645 mSystemGestures.systemReady();
Arthur Hung20479922019-02-27 17:13:22 +0800646 if (mService.mPointerLocationEnabled) {
647 setPointerLocationEnabled(true);
648 }
Charles Chen5bdd3e22018-12-18 17:51:56 +0800649 }
650
651 private int getDisplayId() {
652 return mDisplayContent.getDisplayId();
653 }
654
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800655 public void setHdmiPlugged(boolean plugged) {
656 setHdmiPlugged(plugged, false /* force */);
657 }
658
659 public void setHdmiPlugged(boolean plugged, boolean force) {
660 if (force || mHdmiPlugged != plugged) {
661 mHdmiPlugged = plugged;
662 mService.updateRotation(true /* alwaysSendConfiguration */, true /* forceRelayout */);
663 final Intent intent = new Intent(ACTION_HDMI_PLUGGED);
664 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
665 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
Tiger Huang7c610aa2018-10-27 00:01:01 +0800666 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800667 }
668 }
669
670 boolean isHdmiPlugged() {
671 return mHdmiPlugged;
672 }
673
674 boolean isCarDockEnablesAccelerometer() {
675 return mCarDockEnablesAccelerometer;
676 }
677
678 boolean isDeskDockEnablesAccelerometer() {
679 return mDeskDockEnablesAccelerometer;
680 }
681
682 public void setPersistentVrModeEnabled(boolean persistentVrModeEnabled) {
683 mPersistentVrModeEnabled = persistentVrModeEnabled;
684 }
685
686 public boolean isPersistentVrModeEnabled() {
687 return mPersistentVrModeEnabled;
688 }
689
690 public void setDockMode(int dockMode) {
691 mDockMode = dockMode;
692 }
693
694 public int getDockMode() {
695 return mDockMode;
696 }
697
Brad Stenninge0573692019-03-11 13:52:46 -0700698 /**
699 * @see WindowManagerService.setForceShowSystemBars
700 */
701 void setForceShowSystemBars(boolean forceShowSystemBars) {
702 mForceShowSystemBarsFromExternal = forceShowSystemBars;
703 }
704
JianYang Liuae86b3f2020-04-03 20:20:35 -0700705 boolean getForceShowSystemBars() {
706 return mForceShowSystemBarsFromExternal;
707 }
708
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800709 public boolean hasNavigationBar() {
710 return mHasNavigationBar;
711 }
712
Louis Changfc64c832018-12-04 11:38:26 +0800713 public boolean hasStatusBar() {
714 return mHasStatusBar;
715 }
716
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200717 boolean hasSideGestures() {
Mehdi Alizadehf2b28e92019-12-05 20:13:49 -0800718 return mHasNavigationBar && (mLeftGestureInset > 0 || mRightGestureInset > 0);
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200719 }
720
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800721 public boolean navigationBarCanMove() {
722 return mNavigationBarCanMove;
723 }
724
725 public void setLidState(int lidState) {
726 mLidState = lidState;
727 }
728
729 public int getLidState() {
730 return mLidState;
731 }
732
733 public void setAwake(boolean awake) {
734 mAwake = awake;
735 }
736
737 public boolean isAwake() {
738 return mAwake;
739 }
740
741 public boolean isScreenOnEarly() {
742 return mScreenOnEarly;
743 }
744
745 public boolean isScreenOnFully() {
746 return mScreenOnFully;
747 }
748
749 public boolean isKeyguardDrawComplete() {
750 return mKeyguardDrawComplete;
751 }
752
753 public boolean isWindowManagerDrawComplete() {
754 return mWindowManagerDrawComplete;
755 }
756
757 public ScreenOnListener getScreenOnListener() {
758 return mScreenOnListener;
759 }
760
761 public void screenTurnedOn(ScreenOnListener screenOnListener) {
762 synchronized (mLock) {
763 mScreenOnEarly = true;
764 mScreenOnFully = false;
765 mKeyguardDrawComplete = false;
766 mWindowManagerDrawComplete = false;
767 mScreenOnListener = screenOnListener;
768 }
769 }
770
771 public void screenTurnedOff() {
772 synchronized (mLock) {
773 mScreenOnEarly = false;
774 mScreenOnFully = false;
775 mKeyguardDrawComplete = false;
776 mWindowManagerDrawComplete = false;
777 mScreenOnListener = null;
778 }
779 }
780
781 /** Return false if we are not awake yet or we have already informed of this event. */
782 public boolean finishKeyguardDrawn() {
783 synchronized (mLock) {
784 if (!mScreenOnEarly || mKeyguardDrawComplete) {
785 return false;
786 }
787
788 mKeyguardDrawComplete = true;
789 mWindowManagerDrawComplete = false;
790 }
791 return true;
792 }
793
794 /** Return false if screen is not turned on or we did already handle this case earlier. */
795 public boolean finishWindowsDrawn() {
796 synchronized (mLock) {
797 if (!mScreenOnEarly || mWindowManagerDrawComplete) {
798 return false;
799 }
800
801 mWindowManagerDrawComplete = true;
802 }
803 return true;
804 }
805
806 /** Return false if it is not ready to turn on. */
807 public boolean finishScreenTurningOn() {
808 synchronized (mLock) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200809 ProtoLog.d(WM_DEBUG_SCREEN_ON,
810 "finishScreenTurningOn: mAwake=%b, mScreenOnEarly=%b, "
811 + "mScreenOnFully=%b, mKeyguardDrawComplete=%b, "
812 + "mWindowManagerDrawComplete=%b",
813 mAwake, mScreenOnEarly, mScreenOnFully, mKeyguardDrawComplete,
814 mWindowManagerDrawComplete);
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800815
816 if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
817 || (mAwake && !mKeyguardDrawComplete)) {
818 return false;
819 }
820
Adrian Roosb125e0b2019-10-02 14:55:14 +0200821 ProtoLog.i(WM_DEBUG_SCREEN_ON, "Finished screen turning on...");
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800822 mScreenOnListener = null;
823 mScreenOnFully = true;
824 }
825 return true;
826 }
827
Jorim Jaggi4981f152019-03-26 18:58:45 +0100828 private boolean hasStatusBarServicePermission(int pid, int uid) {
829 return mContext.checkPermission(permission.STATUS_BAR_SERVICE, pid, uid)
830 == PackageManager.PERMISSION_GRANTED;
831 }
832
Tiger Huang7c610aa2018-10-27 00:01:01 +0800833 /**
834 * Sanitize the layout parameters coming from a client. Allows the policy
835 * to do things like ensure that windows of a specific type can't take
836 * input focus.
837 *
838 * @param attrs The window layout parameters to be modified. These values
839 * are modified in-place.
840 */
841 public void adjustWindowParamsLw(WindowState win, WindowManager.LayoutParams attrs,
Jorim Jaggi4981f152019-03-26 18:58:45 +0100842 int callingPid, int callingUid) {
Tiger Huang7c610aa2018-10-27 00:01:01 +0800843
844 final boolean isScreenDecor = (attrs.privateFlags & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0;
845 if (mScreenDecorWindows.contains(win)) {
846 if (!isScreenDecor) {
847 // No longer has the flag set, so remove from the set.
848 mScreenDecorWindows.remove(win);
849 }
Jorim Jaggi4981f152019-03-26 18:58:45 +0100850 } else if (isScreenDecor && hasStatusBarServicePermission(callingPid, callingUid)) {
Tiger Huang7c610aa2018-10-27 00:01:01 +0800851 mScreenDecorWindows.add(win);
852 }
853
854 switch (attrs.type) {
855 case TYPE_SYSTEM_OVERLAY:
856 case TYPE_SECURE_SYSTEM_OVERLAY:
857 // These types of windows can't receive input events.
858 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
859 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
860 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
861 break;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800862 case TYPE_WALLPAPER:
863 // Dreams and wallpapers don't have an app window token and can thus not be
864 // letterboxed. Hence always let them extend under the cutout.
shawnlin465b7de2020-02-11 20:45:35 +0800865 attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800866 break;
wilsonshihe8321942019-10-18 18:39:46 +0800867 case TYPE_NOTIFICATION_SHADE:
Tiger Huang7c610aa2018-10-27 00:01:01 +0800868 // If the Keyguard is in a hidden state (occluded by another window), we force to
869 // remove the wallpaper and keyguard flag so that any change in-flight after setting
870 // the keyguard as occluded wouldn't set these flags again.
871 // See {@link #processKeyguardSetHiddenResultLw}.
872 if (mService.mPolicy.isKeyguardOccluded()) {
873 attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800874 }
875 break;
876
877 case TYPE_SCREENSHOT:
878 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
879 break;
880
881 case TYPE_TOAST:
882 // While apps should use the dedicated toast APIs to add such windows
883 // it possible legacy apps to add the window directly. Therefore, we
884 // make windows added directly by the app behave as a toast as much
885 // as possible in terms of timeout and animation.
886 if (attrs.hideTimeoutMilliseconds < 0
887 || attrs.hideTimeoutMilliseconds > TOAST_WINDOW_TIMEOUT) {
888 attrs.hideTimeoutMilliseconds = TOAST_WINDOW_TIMEOUT;
889 }
Rhed Jao406d3a22018-11-30 19:28:58 +0800890 // Accessibility users may need longer timeout duration. This api compares
891 // original timeout with user's preference and return longer one. It returns
892 // original timeout if there's no preference.
893 attrs.hideTimeoutMilliseconds = mAccessibilityManager.getRecommendedTimeoutMillis(
894 (int) attrs.hideTimeoutMilliseconds,
895 AccessibilityManager.FLAG_CONTENT_TEXT);
Tiger Huang7c610aa2018-10-27 00:01:01 +0800896 attrs.windowAnimations = com.android.internal.R.style.Animation_Toast;
Jeff Changb10fac72019-04-09 17:28:30 +0800897 // Toast can show with below conditions when the screen is locked.
898 if (canToastShowWhenLocked(callingPid)) {
899 attrs.flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
900 }
Bernardo Rufino974de952019-10-22 11:53:42 +0100901 // Toasts can't be clickable
902 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800903 break;
Jorim Jaggi0da8fd12020-01-10 01:23:21 +0100904
905 case TYPE_BASE_APPLICATION:
906
907 // A non-translucent main app window isn't allowed to fit insets, as it would create
908 // a hole on the display!
909 if (attrs.isFullscreen() && win.mActivityRecord != null
910 && win.mActivityRecord.fillsParent()
911 && (win.mAttrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0
Tiger Huang52724442020-01-20 21:38:42 +0800912 && attrs.getFitInsetsTypes() != 0) {
Jorim Jaggi0da8fd12020-01-10 01:23:21 +0100913 throw new RuntimeException("Illegal attributes: Main activity window that isn't"
914 + " translucent trying to fit insets: "
Tiger Huang52724442020-01-20 21:38:42 +0800915 + attrs.getFitInsetsTypes()
Jorim Jaggi0da8fd12020-01-10 01:23:21 +0100916 + " attrs=" + attrs);
917 }
918 break;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800919 }
Tiger Huang7c610aa2018-10-27 00:01:01 +0800920 }
921
922 /**
Jeff Changb10fac72019-04-09 17:28:30 +0800923 * @return {@code true} if the calling activity initiate toast and is visible with
924 * {@link WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} flag.
925 */
926 boolean canToastShowWhenLocked(int callingPid) {
927 return mDisplayContent.forAllWindows(w -> {
928 return callingPid == w.mSession.mPid && w.isVisible() && w.canShowWhenLocked();
929 }, true /* traverseTopToBottom */);
930 }
931
932 /**
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800933 * Check if a window can be added to the system.
Tiger Huang7c610aa2018-10-27 00:01:01 +0800934 *
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800935 * Currently enforces that two window types are singletons per display:
Tiger Huang7c610aa2018-10-27 00:01:01 +0800936 * <ul>
937 * <li>{@link WindowManager.LayoutParams#TYPE_STATUS_BAR}</li>
wilsonshihe8321942019-10-18 18:39:46 +0800938 * <li>{@link WindowManager.LayoutParams#TYPE_NOTIFICATION_SHADE}</li>
Tiger Huang7c610aa2018-10-27 00:01:01 +0800939 * <li>{@link WindowManager.LayoutParams#TYPE_NAVIGATION_BAR}</li>
940 * </ul>
941 *
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800942 * @param attrs Information about the window to be added.
Tiger Huang7c610aa2018-10-27 00:01:01 +0800943 *
944 * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons,
945 * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
946 */
Riddle Hsu1371c572020-02-13 13:41:53 +0800947 int validateAddingWindowLw(WindowManager.LayoutParams attrs, int callingPid, int callingUid) {
Tiger Huang7c610aa2018-10-27 00:01:01 +0800948 if ((attrs.privateFlags & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0) {
Riddle Hsu1371c572020-02-13 13:41:53 +0800949 mContext.enforcePermission(
950 android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
Tiger Huang7c610aa2018-10-27 00:01:01 +0800951 "DisplayPolicy");
Tiger Huang7c610aa2018-10-27 00:01:01 +0800952 }
953
954 switch (attrs.type) {
955 case TYPE_STATUS_BAR:
Riddle Hsu1371c572020-02-13 13:41:53 +0800956 mContext.enforcePermission(
957 android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
Tiger Huang7c610aa2018-10-27 00:01:01 +0800958 "DisplayPolicy");
959 if (mStatusBar != null) {
960 if (mStatusBar.isAlive()) {
961 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
962 }
963 }
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800964 break;
wilsonshihe8321942019-10-18 18:39:46 +0800965 case TYPE_NOTIFICATION_SHADE:
Riddle Hsu1371c572020-02-13 13:41:53 +0800966 mContext.enforcePermission(
967 android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
wilsonshihe8321942019-10-18 18:39:46 +0800968 "DisplayPolicy");
969 if (mNotificationShade != null) {
970 if (mNotificationShade.isAlive()) {
971 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
972 }
973 }
974 break;
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800975 case TYPE_NAVIGATION_BAR:
Riddle Hsu1371c572020-02-13 13:41:53 +0800976 mContext.enforcePermission(
977 android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800978 "DisplayPolicy");
979 if (mNavigationBar != null) {
980 if (mNavigationBar.isAlive()) {
981 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
982 }
983 }
984 break;
985 case TYPE_NAVIGATION_BAR_PANEL:
Matt Casey27f0bdd2020-01-28 12:19:28 -0500986 // Check for permission if the caller is not the recents component.
Riddle Hsu1371c572020-02-13 13:41:53 +0800987 if (!mService.mAtmInternal.isCallerRecents(callingUid)) {
988 mContext.enforcePermission(
989 android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
990 "DisplayPolicy");
Matt Casey27f0bdd2020-01-28 12:19:28 -0500991 }
992 break;
Heemin Seog2cf45dd2020-02-24 15:43:29 -0800993 case TYPE_STATUS_BAR_ADDITIONAL:
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800994 case TYPE_STATUS_BAR_SUB_PANEL:
995 case TYPE_VOICE_INTERACTION_STARTING:
Riddle Hsu1371c572020-02-13 13:41:53 +0800996 mContext.enforcePermission(
997 android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800998 "DisplayPolicy");
999 break;
Joshua Tsuji94d4c342020-05-04 14:00:24 -04001000 case TYPE_TRUSTED_APPLICATION_OVERLAY:
1001 mContext.enforcePermission(
1002 android.Manifest.permission.INTERNAL_SYSTEM_WINDOW, callingPid, callingUid,
1003 "DisplayPolicy");
1004 break;
Heemin Seog2cf45dd2020-02-24 15:43:29 -08001005 case TYPE_STATUS_BAR_PANEL:
1006 return WindowManagerGlobal.ADD_INVALID_TYPE;
Tiger Huang5f6cbca2019-07-18 19:00:01 +08001007 }
Yuncheol Heo13a6eb62020-03-04 23:50:37 -08001008
1009 if (attrs.providesInsetsTypes != null) {
1010 mContext.enforcePermission(
1011 android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
1012 "DisplayPolicy");
1013 enforceSingleInsetsTypeCorrespondingToWindowType(attrs.providesInsetsTypes);
1014 }
Tiger Huang5f6cbca2019-07-18 19:00:01 +08001015 return ADD_OKAY;
1016 }
1017
1018 /**
1019 * Called when a window is being added to the system. Must not throw an exception.
1020 *
1021 * @param win The window being added.
1022 * @param attrs Information about the window to be added.
1023 */
1024 void addWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
1025 if ((attrs.privateFlags & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0) {
1026 mScreenDecorWindows.add(win);
1027 }
1028
1029 switch (attrs.type) {
wilsonshihe8321942019-10-18 18:39:46 +08001030 case TYPE_NOTIFICATION_SHADE:
1031 mNotificationShade = win;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001032 if (mDisplayContent.isDefaultDisplay) {
1033 mService.mPolicy.setKeyguardCandidateLw(win);
1034 }
wilsonshihe8321942019-10-18 18:39:46 +08001035 break;
1036 case TYPE_STATUS_BAR:
1037 mStatusBar = win;
1038 mStatusBarController.setWindow(win);
Adrian Roos11dfd272019-03-25 19:21:26 +01001039 final TriConsumer<DisplayFrames, WindowState, Rect> frameProvider =
Jorim Jaggif96c90a2018-09-26 16:55:15 +02001040 (displayFrames, windowState, rect) -> {
1041 rect.top = 0;
1042 rect.bottom = getStatusBarHeight(displayFrames);
Adrian Roos11dfd272019-03-25 19:21:26 +01001043 };
Tiger Huang332793b2019-10-29 23:21:27 +08001044 mDisplayContent.setInsetProvider(ITYPE_STATUS_BAR, win, frameProvider);
1045 mDisplayContent.setInsetProvider(ITYPE_TOP_GESTURES, win, frameProvider);
1046 mDisplayContent.setInsetProvider(ITYPE_TOP_TAPPABLE_ELEMENT, win, frameProvider);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001047 break;
1048 case TYPE_NAVIGATION_BAR:
Tiger Huang7c610aa2018-10-27 00:01:01 +08001049 mNavigationBar = win;
1050 mNavigationBarController.setWindow(win);
1051 mNavigationBarController.setOnBarVisibilityChangedListener(
1052 mNavBarVisibilityListener, true);
Jorim Jaggidd3d5102020-01-28 12:09:03 +01001053 mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, win,
1054 (displayFrames, windowState, inOutFrame) -> {
1055
1056 // In Gesture Nav, navigation bar frame is larger than frame to
1057 // calculate inset.
Riddle Hsu55d7c402020-02-26 22:49:29 +08001058 if (navigationBarPosition(displayFrames.mDisplayWidth,
1059 displayFrames.mDisplayHeight,
Sunny Goyal38412952020-04-17 11:35:37 -07001060 displayFrames.mRotation) == NAV_BAR_BOTTOM
1061 && !mNavButtonForcedVisible) {
1062
Jorim Jaggidd3d5102020-01-28 12:09:03 +01001063 sTmpRect.set(displayFrames.mUnrestricted);
1064 sTmpRect.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
1065 inOutFrame.top = sTmpRect.bottom
1066 - getNavigationBarHeight(displayFrames.mRotation,
Sunny Goyal38412952020-04-17 11:35:37 -07001067 mDisplayContent.getConfiguration().uiMode);
Jorim Jaggidd3d5102020-01-28 12:09:03 +01001068 }
Jorim Jaggi9b4f4202020-01-28 17:05:06 +01001069 },
1070
1071 // For IME we use regular frame.
1072 (displayFrames, windowState, inOutFrame) ->
1073 inOutFrame.set(windowState.getFrameLw()));
1074
Tiger Huang332793b2019-10-29 23:21:27 +08001075 mDisplayContent.setInsetProvider(ITYPE_BOTTOM_GESTURES, win,
Adrian Roos11dfd272019-03-25 19:21:26 +01001076 (displayFrames, windowState, inOutFrame) -> {
1077 inOutFrame.top -= mBottomGestureAdditionalInset;
1078 });
Tiger Huang332793b2019-10-29 23:21:27 +08001079 mDisplayContent.setInsetProvider(ITYPE_LEFT_GESTURES, win,
Adrian Roos11dfd272019-03-25 19:21:26 +01001080 (displayFrames, windowState, inOutFrame) -> {
1081 inOutFrame.left = 0;
1082 inOutFrame.top = 0;
1083 inOutFrame.bottom = displayFrames.mDisplayHeight;
Mehdi Alizadehf2b28e92019-12-05 20:13:49 -08001084 inOutFrame.right = displayFrames.mUnrestricted.left + mLeftGestureInset;
Adrian Roos11dfd272019-03-25 19:21:26 +01001085 });
Tiger Huang332793b2019-10-29 23:21:27 +08001086 mDisplayContent.setInsetProvider(ITYPE_RIGHT_GESTURES, win,
Adrian Roos11dfd272019-03-25 19:21:26 +01001087 (displayFrames, windowState, inOutFrame) -> {
Mehdi Alizadehf2b28e92019-12-05 20:13:49 -08001088 inOutFrame.left = displayFrames.mUnrestricted.right
1089 - mRightGestureInset;
Adrian Roos11dfd272019-03-25 19:21:26 +01001090 inOutFrame.top = 0;
1091 inOutFrame.bottom = displayFrames.mDisplayHeight;
1092 inOutFrame.right = displayFrames.mDisplayWidth;
1093 });
Tiger Huang332793b2019-10-29 23:21:27 +08001094 mDisplayContent.setInsetProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT, win,
Adrian Roos11dfd272019-03-25 19:21:26 +01001095 (displayFrames, windowState, inOutFrame) -> {
1096 if ((windowState.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0
1097 || mNavigationBarLetsThroughTaps) {
1098 inOutFrame.setEmpty();
1099 }
1100 });
Tiger Huang7c610aa2018-10-27 00:01:01 +08001101 if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
1102 break;
Yuncheol Heo13a6eb62020-03-04 23:50:37 -08001103 default:
1104 if (attrs.providesInsetsTypes != null) {
1105 for (int insetsType : attrs.providesInsetsTypes) {
1106 mDisplayContent.setInsetProvider(insetsType, win, null);
1107 }
1108 }
1109 break;
1110 }
1111 }
1112
1113 private static void enforceSingleInsetsTypeCorrespondingToWindowType(int[] insetsTypes) {
1114 int count = 0;
1115 for (int insetsType : insetsTypes) {
1116 switch (insetsType) {
1117 case ITYPE_NAVIGATION_BAR:
1118 case ITYPE_STATUS_BAR:
1119 case ITYPE_CAPTION_BAR:
1120 if (++count > 1) {
1121 throw new IllegalArgumentException(
1122 "Multiple InsetsTypes corresponding to Window type");
1123 }
1124 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001125 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001126 }
1127
1128 /**
1129 * Called when a window is being removed from a window manager. Must not
1130 * throw an exception -- clean up as much as possible.
1131 *
1132 * @param win The window being removed.
1133 */
Tiger Huang5f6cbca2019-07-18 19:00:01 +08001134 void removeWindowLw(WindowState win) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001135 if (mStatusBar == win) {
1136 mStatusBar = null;
1137 mStatusBarController.setWindow(null);
Tiger Huang332793b2019-10-29 23:21:27 +08001138 mDisplayContent.setInsetProvider(ITYPE_STATUS_BAR, null, null);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001139 } else if (mNavigationBar == win) {
1140 mNavigationBar = null;
1141 mNavigationBarController.setWindow(null);
Tiger Huang332793b2019-10-29 23:21:27 +08001142 mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, null, null);
wilsonshihe8321942019-10-18 18:39:46 +08001143 } else if (mNotificationShade == win) {
1144 mNotificationShade = null;
1145 if (mDisplayContent.isDefaultDisplay) {
1146 mService.mPolicy.setKeyguardCandidateLw(null);
1147 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001148 }
1149 if (mLastFocusedWindow == win) {
1150 mLastFocusedWindow = null;
1151 }
1152 mScreenDecorWindows.remove(win);
1153 }
1154
Jorim Jaggif96c90a2018-09-26 16:55:15 +02001155 private int getStatusBarHeight(DisplayFrames displayFrames) {
1156 return Math.max(mStatusBarHeightForRotation[displayFrames.mRotation],
1157 displayFrames.mDisplayCutoutSafe.top);
1158 }
1159
Jorim Jaggi28620472019-01-02 23:21:49 +01001160 WindowState getStatusBar() {
1161 return mStatusBar;
1162 }
1163
wilsonshihe8321942019-10-18 18:39:46 +08001164 WindowState getNotificationShade() {
1165 return mNotificationShade;
1166 }
1167
Jorim Jaggi28620472019-01-02 23:21:49 +01001168 WindowState getNavigationBar() {
1169 return mNavigationBar;
1170 }
1171
Tiger Huang7c610aa2018-10-27 00:01:01 +08001172 /**
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001173 * Control the animation to run when a window's state changes. Return a positive number to
1174 * force the animation to a specific resource ID, {@link #ANIMATION_STYLEABLE} to use the
1175 * style resource defining the animation, or {@link #ANIMATION_NONE} for no animation.
Tiger Huang7c610aa2018-10-27 00:01:01 +08001176 *
1177 * @param win The window that is changing.
1178 * @param transit What is happening to the window:
1179 * {@link com.android.server.policy.WindowManagerPolicy#TRANSIT_ENTER},
1180 * {@link com.android.server.policy.WindowManagerPolicy#TRANSIT_EXIT},
1181 * {@link com.android.server.policy.WindowManagerPolicy#TRANSIT_SHOW}, or
1182 * {@link com.android.server.policy.WindowManagerPolicy#TRANSIT_HIDE}.
1183 *
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001184 * @return Resource ID of the actual animation to use, or {@link #ANIMATION_NONE} for none.
Tiger Huang7c610aa2018-10-27 00:01:01 +08001185 */
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001186 int selectAnimation(WindowState win, int transit) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001187 if (DEBUG_ANIM) Slog.i(TAG, "selectAnimation in " + win
1188 + ": transit=" + transit);
1189 if (win == mStatusBar) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001190 if (transit == TRANSIT_EXIT
1191 || transit == TRANSIT_HIDE) {
1192 return R.anim.dock_top_exit;
1193 } else if (transit == TRANSIT_ENTER
1194 || transit == TRANSIT_SHOW) {
1195 return R.anim.dock_top_enter;
1196 }
1197 } else if (win == mNavigationBar) {
1198 if (win.getAttrs().windowAnimations != 0) {
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001199 return ANIMATION_STYLEABLE;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001200 }
1201 // This can be on either the bottom or the right or the left.
1202 if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
1203 if (transit == TRANSIT_EXIT
1204 || transit == TRANSIT_HIDE) {
1205 if (mService.mPolicy.isKeyguardShowingAndNotOccluded()) {
1206 return R.anim.dock_bottom_exit_keyguard;
1207 } else {
1208 return R.anim.dock_bottom_exit;
1209 }
1210 } else if (transit == TRANSIT_ENTER
1211 || transit == TRANSIT_SHOW) {
1212 return R.anim.dock_bottom_enter;
1213 }
1214 } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
1215 if (transit == TRANSIT_EXIT
1216 || transit == TRANSIT_HIDE) {
1217 return R.anim.dock_right_exit;
1218 } else if (transit == TRANSIT_ENTER
1219 || transit == TRANSIT_SHOW) {
1220 return R.anim.dock_right_enter;
1221 }
1222 } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
1223 if (transit == TRANSIT_EXIT
1224 || transit == TRANSIT_HIDE) {
1225 return R.anim.dock_left_exit;
1226 } else if (transit == TRANSIT_ENTER
1227 || transit == TRANSIT_SHOW) {
1228 return R.anim.dock_left_enter;
1229 }
1230 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001231 }
1232
1233 if (transit == TRANSIT_PREVIEW_DONE) {
1234 if (win.hasAppShownWindows()) {
Riddle Hsu3b9ac732020-02-18 16:10:29 +08001235 if (win.isActivityTypeHome()) {
1236 // Dismiss the starting window as soon as possible to avoid the crossfade out
1237 // with old content because home is easier to have different UI states.
1238 return ANIMATION_NONE;
1239 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001240 if (DEBUG_ANIM) Slog.i(TAG, "**** STARTING EXIT");
1241 return R.anim.app_starting_exit;
1242 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001243 }
1244
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001245 return ANIMATION_STYLEABLE;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001246 }
1247
Tiger Huang7c610aa2018-10-27 00:01:01 +08001248 /**
Tiger Huang7c610aa2018-10-27 00:01:01 +08001249 * Called when a new system UI visibility is being reported, allowing
1250 * the policy to adjust what is actually reported.
1251 * @param visibility The raw visibility reported by the status bar.
1252 * @return The new desired visibility.
1253 */
1254 public int adjustSystemUiVisibilityLw(int visibility) {
1255 mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
1256 mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
1257
1258 // Reset any bits in mForceClearingStatusBarVisibility that
1259 // are now clear.
1260 mResettingSystemUiFlags &= visibility;
1261 // Clear any bits in the new visibility that are currently being
1262 // force cleared, before reporting it.
1263 return visibility & ~mResettingSystemUiFlags
1264 & ~mForceClearedSystemUiFlags;
1265 }
1266
1267 /**
Brad Stenninge0573692019-03-11 13:52:46 -07001268 * @return true if the system bars are forced to stay visible
Tiger Huang7c610aa2018-10-27 00:01:01 +08001269 */
Brad Stenninge0573692019-03-11 13:52:46 -07001270 public boolean areSystemBarsForcedShownLw(WindowState windowState) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001271 return mForceShowSystemBars;
1272 }
1273
1274 // TODO: Should probably be moved into DisplayFrames.
1275 /**
1276 * Return the layout hints for a newly added window. These values are computed on the
1277 * most recent layout, so they are not guaranteed to be correct.
1278 *
1279 * @param attrs The LayoutParams of the window.
Riddle Hsu55d7c402020-02-26 22:49:29 +08001280 * @param windowToken The token of the window.
Tiger Huang7c610aa2018-10-27 00:01:01 +08001281 * @param outFrame The frame of the window.
1282 * @param outContentInsets The areas covered by system windows, expressed as positive insets.
1283 * @param outStableInsets The areas covered by stable system windows irrespective of their
1284 * current visibility. Expressed as positive insets.
Tiger Huang7c610aa2018-10-27 00:01:01 +08001285 * @param outDisplayCutout The area that has been cut away from the display.
Brad Stenninge0573692019-03-11 13:52:46 -07001286 * @return Whether to always consume the system bars.
1287 * See {@link #areSystemBarsForcedShownLw(WindowState)}.
Tiger Huang7c610aa2018-10-27 00:01:01 +08001288 */
Riddle Hsu55d7c402020-02-26 22:49:29 +08001289 boolean getLayoutHint(LayoutParams attrs, WindowToken windowToken, Rect outFrame,
Tiger Huang7c610aa2018-10-27 00:01:01 +08001290 Rect outContentInsets, Rect outStableInsets,
Jorim Jaggif081f062019-10-24 16:24:54 +02001291 DisplayCutout.ParcelableWrapper outDisplayCutout) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001292 final int fl = PolicyControl.getWindowFlags(null, attrs);
1293 final int pfl = attrs.privateFlags;
1294 final int requestedSysUiVis = PolicyControl.getSystemUiVisibility(null, attrs);
1295 final int sysUiVis = requestedSysUiVis | getImpliedSysUiFlagsForLayout(attrs);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001296
1297 final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) != 0;
1298 final boolean layoutInScreenAndInsetDecor = layoutInScreen
1299 && (fl & FLAG_LAYOUT_INSET_DECOR) != 0;
1300 final boolean screenDecor = (pfl & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0;
1301
Riddle Hsu55d7c402020-02-26 22:49:29 +08001302 final boolean isFixedRotationTransforming =
1303 windowToken != null && windowToken.isFixedRotationTransforming();
1304 final ActivityRecord activity = windowToken != null ? windowToken.asActivityRecord() : null;
1305 final Task task = activity != null ? activity.getTask() : null;
1306 final Rect taskBounds = isFixedRotationTransforming
1307 // Use token (activity) bounds if it is rotated because its task is not rotated.
1308 ? windowToken.getBounds()
1309 : (task != null ? task.getBounds() : null);
1310 final DisplayFrames displayFrames = isFixedRotationTransforming
1311 ? windowToken.getFixedRotationTransformDisplayFrames()
1312 : mDisplayContent.mDisplayFrames;
1313
Tiger Huang7c610aa2018-10-27 00:01:01 +08001314 if (layoutInScreenAndInsetDecor && !screenDecor) {
Tiger Huang4a7835f2019-11-06 00:07:56 +08001315 if ((sysUiVis & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
Tiger Huang52724442020-01-20 21:38:42 +08001316 || (attrs.getFitInsetsTypes() & Type.navigationBars()) == 0) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001317 outFrame.set(displayFrames.mUnrestricted);
1318 } else {
1319 outFrame.set(displayFrames.mRestricted);
1320 }
1321
Riddle Hsu55d7c402020-02-26 22:49:29 +08001322 final boolean isFloatingTask = task != null && task.isFloating();
1323 final Rect sf = isFloatingTask ? null : displayFrames.mStable;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001324 final Rect cf;
Riddle Hsu55d7c402020-02-26 22:49:29 +08001325 if (isFloatingTask) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001326 cf = null;
1327 } else if ((sysUiVis & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
1328 if ((fl & FLAG_FULLSCREEN) != 0) {
1329 cf = displayFrames.mStableFullscreen;
1330 } else {
1331 cf = displayFrames.mStable;
1332 }
Jorim Jaggif081f062019-10-24 16:24:54 +02001333 } else if ((fl & FLAG_FULLSCREEN) != 0) {
1334 cf = displayFrames.mUnrestricted;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001335 } else {
1336 cf = displayFrames.mCurrent;
1337 }
1338
1339 if (taskBounds != null) {
1340 outFrame.intersect(taskBounds);
1341 }
1342 InsetUtils.insetsBetweenFrames(outFrame, cf, outContentInsets);
1343 InsetUtils.insetsBetweenFrames(outFrame, sf, outStableInsets);
1344 outDisplayCutout.set(displayFrames.mDisplayCutout.calculateRelativeTo(outFrame)
1345 .getDisplayCutout());
1346 return mForceShowSystemBars;
1347 } else {
1348 if (layoutInScreen) {
1349 outFrame.set(displayFrames.mUnrestricted);
1350 } else {
1351 outFrame.set(displayFrames.mStable);
1352 }
1353 if (taskBounds != null) {
1354 outFrame.intersect(taskBounds);
1355 }
1356
1357 outContentInsets.setEmpty();
1358 outStableInsets.setEmpty();
1359 outDisplayCutout.set(DisplayCutout.NO_CUTOUT);
1360 return mForceShowSystemBars;
1361 }
1362 }
1363
Tiger Huang4a7835f2019-11-06 00:07:56 +08001364 // TODO(b/118118435): remove after migration
Tiger Huang7c610aa2018-10-27 00:01:01 +08001365 private static int getImpliedSysUiFlagsForLayout(LayoutParams attrs) {
1366 int impliedFlags = 0;
Jorim Jaggia6aabac2019-03-11 14:23:16 -07001367 final boolean forceWindowDrawsBarBackgrounds =
1368 (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0
Tiger Huang4a7835f2019-11-06 00:07:56 +08001369 && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001370 if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
Jorim Jaggia6aabac2019-03-11 14:23:16 -07001371 || forceWindowDrawsBarBackgrounds) {
Jorim Jaggid6490572019-04-16 14:57:56 +02001372 impliedFlags |= SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001373 impliedFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
1374 }
1375 return impliedFlags;
1376 }
1377
Tiger Huang7c610aa2018-10-27 00:01:01 +08001378 private final Runnable mClearHideNavigationFlag = new Runnable() {
1379 @Override
1380 public void run() {
1381 synchronized (mLock) {
1382 mForceClearedSystemUiFlags &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
1383 mDisplayContent.reevaluateStatusBarVisibility();
1384 }
1385 }
1386 };
1387
1388 /**
1389 * Input handler used while nav bar is hidden. Captures any touch on the screen,
1390 * to determine when the nav bar should be shown and prevent applications from
1391 * receiving those touches.
1392 */
1393 private final class HideNavInputEventReceiver extends InputEventReceiver {
1394 HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
1395 super(inputChannel, looper);
1396 }
1397
1398 @Override
1399 public void onInputEvent(InputEvent event) {
1400 try {
1401 if (event instanceof MotionEvent
1402 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
1403 final MotionEvent motionEvent = (MotionEvent) event;
1404 if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
1405 // When the user taps down, we re-show the nav bar.
1406 boolean changed = false;
1407 synchronized (mLock) {
1408 if (mInputConsumer == null) {
1409 return;
1410 }
Tiger Huang9ff42bd2020-05-01 03:27:33 +08001411 showNavigationBar();
Tiger Huang7c610aa2018-10-27 00:01:01 +08001412 // Any user activity always causes us to show the
1413 // navigation controls, if they had been hidden.
1414 // We also clear the low profile and only content
1415 // flags so that tapping on the screen will atomically
1416 // restore all currently hidden screen decorations.
1417 int newVal = mResettingSystemUiFlags
1418 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
1419 | View.SYSTEM_UI_FLAG_LOW_PROFILE
1420 | View.SYSTEM_UI_FLAG_FULLSCREEN;
1421 if (mResettingSystemUiFlags != newVal) {
1422 mResettingSystemUiFlags = newVal;
1423 changed = true;
1424 }
1425 // We don't allow the system's nav bar to be hidden
1426 // again for 1 second, to prevent applications from
1427 // spamming us and keeping it from being shown.
1428 newVal = mForceClearedSystemUiFlags
1429 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
1430 if (mForceClearedSystemUiFlags != newVal) {
1431 mForceClearedSystemUiFlags = newVal;
1432 changed = true;
1433 mHandler.postDelayed(mClearHideNavigationFlag, 1000);
1434 }
1435 if (changed) {
1436 mDisplayContent.reevaluateStatusBarVisibility();
1437 }
1438 }
1439 }
1440 }
1441 } finally {
1442 finishInputEvent(event, false /* handled */);
1443 }
1444 }
Tiger Huang9ff42bd2020-05-01 03:27:33 +08001445
1446 private void showNavigationBar() {
1447 final InsetsSourceProvider provider = mDisplayContent.getInsetsStateController()
1448 .peekSourceProvider(ITYPE_NAVIGATION_BAR);
1449 final InsetsControlTarget target =
1450 provider != null ? provider.getControlTarget() : null;
1451 if (target != null) {
1452 target.showInsets(Type.navigationBars(), false /* fromIme */);
1453 }
1454 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001455 }
1456
Riddle Hsu6f548e92020-01-13 13:34:09 +08001457 private void simulateLayoutDecorWindow(WindowState win, DisplayFrames displayFrames,
Riddle Hsuc7175762020-01-10 21:03:48 +08001458 InsetsState insetsState, WindowFrames simulatedWindowFrames, Runnable layout) {
1459 win.setSimulatedWindowFrames(simulatedWindowFrames);
1460 try {
1461 layout.run();
1462 } finally {
1463 win.setSimulatedWindowFrames(null);
1464 }
1465 mDisplayContent.getInsetsStateController().computeSimulatedState(insetsState, win,
1466 displayFrames, simulatedWindowFrames);
1467 }
1468
1469 /**
1470 * Computes the frames of display (its logical size, rotation and cutout should already be set)
1471 * used to layout window. The result of display frames and insets state should be the same as
1472 * using {@link #beginLayoutLw}, but this method only changes the given display frames, insets
1473 * state and some temporal states. In other words, it doesn't change the window frames used to
1474 * show on screen.
1475 */
1476 void simulateLayoutDisplay(DisplayFrames displayFrames, InsetsState insetsState, int uiMode) {
1477 displayFrames.onBeginLayout();
Tiger Huange16645a2020-02-25 22:24:39 +08001478 updateInsetsStateForDisplayCutout(displayFrames, insetsState);
Riddle Hsu55d7c402020-02-26 22:49:29 +08001479 insetsState.setDisplayFrame(displayFrames.mUnrestricted);
Riddle Hsuc7175762020-01-10 21:03:48 +08001480 final WindowFrames simulatedWindowFrames = new WindowFrames();
1481 if (mNavigationBar != null) {
1482 simulateLayoutDecorWindow(
Riddle Hsu6f548e92020-01-13 13:34:09 +08001483 mNavigationBar, displayFrames, insetsState, simulatedWindowFrames,
Riddle Hsuc7175762020-01-10 21:03:48 +08001484 () -> layoutNavigationBar(displayFrames, uiMode, mLastNavVisible,
1485 mLastNavTranslucent, mLastNavAllowedHidden,
1486 mLastNotificationShadeForcesShowingNavigation,
1487 false /* isRealLayout */));
1488 }
1489 if (mStatusBar != null) {
1490 simulateLayoutDecorWindow(
Riddle Hsu6f548e92020-01-13 13:34:09 +08001491 mStatusBar, displayFrames, insetsState, simulatedWindowFrames,
Riddle Hsuc7175762020-01-10 21:03:48 +08001492 () -> layoutStatusBar(displayFrames, mLastSystemUiFlags,
1493 false /* isRealLayout */));
1494 }
1495 layoutScreenDecorWindows(displayFrames, simulatedWindowFrames);
1496 postAdjustDisplayFrames(displayFrames);
1497 }
1498
Tiger Huang7c610aa2018-10-27 00:01:01 +08001499 /**
1500 * Called when layout of the windows is about to start.
1501 *
1502 * @param displayFrames frames of the display we are doing layout on.
1503 * @param uiMode The current uiMode in configuration.
1504 */
1505 public void beginLayoutLw(DisplayFrames displayFrames, int uiMode) {
1506 displayFrames.onBeginLayout();
Tiger Huang57e2e1c2020-03-13 22:54:36 +08001507 updateInsetsStateForDisplayCutout(displayFrames,
1508 mDisplayContent.getInsetsStateController().getRawInsetsState());
Tiger Huang7c610aa2018-10-27 00:01:01 +08001509 mSystemGestures.screenWidth = displayFrames.mUnrestricted.width();
1510 mSystemGestures.screenHeight = displayFrames.mUnrestricted.height();
1511
1512 // For purposes of putting out fake window up to steal focus, we will
1513 // drive nav being hidden only by whether it is requested.
1514 final int sysui = mLastSystemUiFlags;
Tiger Huang4a7835f2019-11-06 00:07:56 +08001515 final int behavior = mLastBehavior;
Tiger Huang9ff42bd2020-05-01 03:27:33 +08001516 final InsetsSourceProvider provider =
1517 mDisplayContent.getInsetsStateController().peekSourceProvider(ITYPE_NAVIGATION_BAR);
Tiger Huang4a7835f2019-11-06 00:07:56 +08001518 boolean navVisible = ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL
1519 ? (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
Tiger Huang9ff42bd2020-05-01 03:27:33 +08001520 : provider != null
1521 ? provider.isClientVisible()
1522 : InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001523 boolean navTranslucent = (sysui
1524 & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
Tiger Huang4a7835f2019-11-06 00:07:56 +08001525 boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0
1526 || (behavior & BEHAVIOR_SHOW_BARS_BY_SWIPE) != 0;
1527 boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0
1528 || (behavior & BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE) != 0;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001529 boolean navAllowedHidden = immersive || immersiveSticky;
1530 navTranslucent &= !immersiveSticky; // transient trumps translucent
wilsonshihe8321942019-10-18 18:39:46 +08001531 boolean isKeyguardShowing = isKeyguardShowing() && !isKeyguardOccluded();
1532 boolean notificationShadeForcesShowingNavigation =
1533 !isKeyguardShowing && mNotificationShade != null
1534 && (mNotificationShade.getAttrs().privateFlags
Tiger Huang7c610aa2018-10-27 00:01:01 +08001535 & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0;
1536
Tiger Huang9ff42bd2020-05-01 03:27:33 +08001537 updateHideNavInputEventReceiver();
Tiger Huang7c610aa2018-10-27 00:01:01 +08001538
1539 // For purposes of positioning and showing the nav bar, if we have decided that it can't
1540 // be hidden (because of the screen aspect ratio), then take that into account.
1541 navVisible |= !canHideNavigationBar();
1542
1543 boolean updateSysUiVisibility = layoutNavigationBar(displayFrames, uiMode, navVisible,
Riddle Hsuc7175762020-01-10 21:03:48 +08001544 navTranslucent, navAllowedHidden, notificationShadeForcesShowingNavigation,
1545 true /* isRealLayout */);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001546 if (DEBUG_LAYOUT) Slog.i(TAG, "mDock rect:" + displayFrames.mDock);
Riddle Hsuc7175762020-01-10 21:03:48 +08001547 updateSysUiVisibility |= layoutStatusBar(displayFrames, sysui, true /* isRealLayout */);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001548 if (updateSysUiVisibility) {
1549 updateSystemUiVisibilityLw();
1550 }
Riddle Hsu6f548e92020-01-13 13:34:09 +08001551 layoutScreenDecorWindows(displayFrames, null /* simulatedFrames */);
Riddle Hsuc7175762020-01-10 21:03:48 +08001552 postAdjustDisplayFrames(displayFrames);
1553 mLastNavVisible = navVisible;
1554 mLastNavTranslucent = navTranslucent;
1555 mLastNavAllowedHidden = navAllowedHidden;
1556 mLastNotificationShadeForcesShowingNavigation = notificationShadeForcesShowingNavigation;
1557 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001558
Tiger Huang9ff42bd2020-05-01 03:27:33 +08001559 void updateHideNavInputEventReceiver() {
1560 final InsetsSourceProvider provider = mDisplayContent.getInsetsStateController()
1561 .peekSourceProvider(ITYPE_NAVIGATION_BAR);
1562 final InsetsControlTarget navControlTarget =
1563 provider != null ? provider.getControlTarget() : null;
1564 final WindowState navControllingWin =
1565 navControlTarget instanceof WindowState ? (WindowState) navControlTarget : null;
1566 final InsetsState requestedState = navControllingWin != null
1567 ? navControllingWin.getRequestedInsetsState() : null;
1568 final InsetsSource navSource = requestedState != null
1569 ? requestedState.peekSource(ITYPE_NAVIGATION_BAR) : null;
1570 final boolean navVisible = navSource != null
1571 ? navSource.isVisible() : InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR);
1572 final boolean showBarsByTouch = navControllingWin != null
1573 && navControllingWin.mAttrs.insetsFlags.behavior == BEHAVIOR_SHOW_BARS_BY_TOUCH;
Tiger Huangd611a9b2020-03-25 17:52:17 +08001574 // When the navigation bar isn't visible, we put up a fake input window to catch all
1575 // touch events. This way we can detect when the user presses anywhere to bring back the
1576 // nav bar and ensure the application doesn't see the event.
Tiger Huang9ff42bd2020-05-01 03:27:33 +08001577 if (navVisible || !showBarsByTouch) {
Tiger Huangd611a9b2020-03-25 17:52:17 +08001578 if (mInputConsumer != null) {
1579 mInputConsumer.dismiss();
1580 mHandler.sendMessage(
1581 mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
1582 mInputConsumer = null;
Tiger Huang9ff42bd2020-05-01 03:27:33 +08001583 Slog.v(TAG, INPUT_CONSUMER_NAVIGATION + " dismissed.");
Tiger Huangd611a9b2020-03-25 17:52:17 +08001584 }
1585 } else if (mInputConsumer == null && mStatusBar != null && canHideNavigationBar()) {
1586 mInputConsumer = mDisplayContent.getInputMonitor().createInputConsumer(
1587 mHandler.getLooper(),
1588 INPUT_CONSUMER_NAVIGATION,
1589 HideNavInputEventReceiver::new);
Tiger Huang9ff42bd2020-05-01 03:27:33 +08001590 Slog.v(TAG, INPUT_CONSUMER_NAVIGATION + " created.");
Tiger Huangd611a9b2020-03-25 17:52:17 +08001591 // As long as mInputConsumer is active, hover events are not dispatched to the app
1592 // and the pointer icon is likely to become stale. Hide it to avoid confusion.
1593 InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL);
1594 }
1595 }
1596
Tiger Huange16645a2020-02-25 22:24:39 +08001597 private static void updateInsetsStateForDisplayCutout(DisplayFrames displayFrames,
1598 InsetsState state) {
1599 if (displayFrames.mDisplayCutout.getDisplayCutout().isEmpty()) {
1600 state.removeSource(ITYPE_LEFT_DISPLAY_CUTOUT);
1601 state.removeSource(ITYPE_TOP_DISPLAY_CUTOUT);
1602 state.removeSource(ITYPE_RIGHT_DISPLAY_CUTOUT);
1603 state.removeSource(ITYPE_BOTTOM_DISPLAY_CUTOUT);
1604 return;
1605 }
1606 final Rect u = displayFrames.mUnrestricted;
1607 final Rect s = displayFrames.mDisplayCutoutSafe;
1608 state.getSource(ITYPE_LEFT_DISPLAY_CUTOUT).setFrame(u.left, u.top, s.left, u.bottom);
1609 state.getSource(ITYPE_TOP_DISPLAY_CUTOUT).setFrame(u.left, u.top, u.right, s.top);
1610 state.getSource(ITYPE_RIGHT_DISPLAY_CUTOUT).setFrame(s.right, u.top, u.right, u.bottom);
1611 state.getSource(ITYPE_BOTTOM_DISPLAY_CUTOUT).setFrame(u.left, s.bottom, u.right, u.bottom);
1612 }
1613
Riddle Hsuc7175762020-01-10 21:03:48 +08001614 /** Enforces the last layout policy for display frames. */
1615 private void postAdjustDisplayFrames(DisplayFrames displayFrames) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001616 if (displayFrames.mDisplayCutoutSafe.top > displayFrames.mUnrestricted.top) {
1617 // Make sure that the zone we're avoiding for the cutout is at least as tall as the
1618 // status bar; otherwise fullscreen apps will end up cutting halfway into the status
1619 // bar.
1620 displayFrames.mDisplayCutoutSafe.top = Math.max(displayFrames.mDisplayCutoutSafe.top,
1621 displayFrames.mStable.top);
1622 }
Issei Suzukia5dbf522019-02-01 17:58:15 +01001623
1624 // In case this is a virtual display, and the host display has insets that overlap this
1625 // virtual display, apply the insets of the overlapped area onto the current and content
1626 // frame of this virtual display. This let us layout windows in the virtual display as
1627 // expected when the window needs to avoid overlap with the system windows.
1628 // TODO: Generalize the forwarded insets, so that we can handle system windows other than
1629 // IME.
1630 displayFrames.mCurrent.inset(mForwardedInsets);
1631 displayFrames.mContent.inset(mForwardedInsets);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001632 }
1633
Riddle Hsuc7175762020-01-10 21:03:48 +08001634 /**
1635 * Layout the decor windows with {@link #PRIVATE_FLAG_IS_SCREEN_DECOR}.
1636 *
1637 * @param displayFrames The display frames to be layouted.
1638 * @param simulatedFrames Non-null if the caller only needs the result of display frames (see
1639 * {@link WindowState#mSimulatedWindowFrames}).
1640 */
1641 private void layoutScreenDecorWindows(DisplayFrames displayFrames,
1642 WindowFrames simulatedFrames) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001643 if (mScreenDecorWindows.isEmpty()) {
1644 return;
1645 }
1646
1647 sTmpRect.setEmpty();
Tiger Huang7c610aa2018-10-27 00:01:01 +08001648 final int displayId = displayFrames.mDisplayId;
1649 final Rect dockFrame = displayFrames.mDock;
1650 final int displayHeight = displayFrames.mDisplayHeight;
1651 final int displayWidth = displayFrames.mDisplayWidth;
1652
1653 for (int i = mScreenDecorWindows.size() - 1; i >= 0; --i) {
1654 final WindowState w = mScreenDecorWindows.valueAt(i);
1655 if (w.getDisplayId() != displayId || !w.isVisibleLw()) {
1656 // Skip if not on the same display or not visible.
1657 continue;
1658 }
1659
Riddle Hsuc7175762020-01-10 21:03:48 +08001660 final boolean isSimulatedLayout = simulatedFrames != null;
1661 if (isSimulatedLayout) {
1662 w.setSimulatedWindowFrames(simulatedFrames);
1663 }
1664 final WindowFrames windowFrames = w.getLayoutingWindowFrames();
1665 windowFrames.setFrames(displayFrames.mUnrestricted /* parentFrame */,
chaviw0d833762019-06-20 17:09:53 -07001666 displayFrames.mUnrestricted /* displayFrame */,
chaviw0d833762019-06-20 17:09:53 -07001667 displayFrames.mUnrestricted /* contentFrame */,
1668 displayFrames.mUnrestricted /* visibleFrame */, sTmpRect /* decorFrame */,
Jorim Jaggif081f062019-10-24 16:24:54 +02001669 displayFrames.mUnrestricted /* stableFrame */);
Riddle Hsuc7175762020-01-10 21:03:48 +08001670 try {
1671 w.computeFrame(displayFrames);
1672 } finally {
1673 if (isSimulatedLayout) {
1674 w.setSimulatedWindowFrames(null);
1675 }
Tiger Huang4a7835f2019-11-06 00:07:56 +08001676 }
Riddle Hsuc7175762020-01-10 21:03:48 +08001677 final Rect frame = windowFrames.mFrame;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001678
1679 if (frame.left <= 0 && frame.top <= 0) {
1680 // Docked at left or top.
1681 if (frame.bottom >= displayHeight) {
1682 // Docked left.
1683 dockFrame.left = Math.max(frame.right, dockFrame.left);
1684 } else if (frame.right >= displayWidth) {
1685 // Docked top.
1686 dockFrame.top = Math.max(frame.bottom, dockFrame.top);
1687 } else {
1688 Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w
1689 + " not docked on left or top of display. frame=" + frame
1690 + " displayWidth=" + displayWidth + " displayHeight=" + displayHeight);
1691 }
1692 } else if (frame.right >= displayWidth && frame.bottom >= displayHeight) {
1693 // Docked at right or bottom.
1694 if (frame.top <= 0) {
1695 // Docked right.
1696 dockFrame.right = Math.min(frame.left, dockFrame.right);
1697 } else if (frame.left <= 0) {
1698 // Docked bottom.
1699 dockFrame.bottom = Math.min(frame.top, dockFrame.bottom);
1700 } else {
1701 Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w
1702 + " not docked on right or bottom" + " of display. frame=" + frame
1703 + " displayWidth=" + displayWidth + " displayHeight=" + displayHeight);
1704 }
1705 } else {
1706 // Screen decor windows are required to be docked on one of the sides of the screen.
1707 Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w
1708 + " not docked on one of the sides of the display. frame=" + frame
1709 + " displayWidth=" + displayWidth + " displayHeight=" + displayHeight);
1710 }
1711 }
1712
1713 displayFrames.mRestricted.set(dockFrame);
1714 displayFrames.mCurrent.set(dockFrame);
1715 displayFrames.mVoiceContent.set(dockFrame);
1716 displayFrames.mSystem.set(dockFrame);
1717 displayFrames.mContent.set(dockFrame);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001718 }
1719
Riddle Hsuc7175762020-01-10 21:03:48 +08001720 private boolean layoutStatusBar(DisplayFrames displayFrames, int sysui, boolean isRealLayout) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001721 // decide where the status bar goes ahead of time
1722 if (mStatusBar == null) {
1723 return false;
1724 }
1725 // apply any navigation bar insets
1726 sTmpRect.setEmpty();
Riddle Hsuc7175762020-01-10 21:03:48 +08001727 final WindowFrames windowFrames = mStatusBar.getLayoutingWindowFrames();
Jorim Jaggi4981f152019-03-26 18:58:45 +01001728 windowFrames.setFrames(displayFrames.mUnrestricted /* parentFrame */,
Tiger Huang7c610aa2018-10-27 00:01:01 +08001729 displayFrames.mUnrestricted /* displayFrame */,
Jorim Jaggif081f062019-10-24 16:24:54 +02001730 displayFrames.mStable /* contentFrame */,
Tiger Huang7c610aa2018-10-27 00:01:01 +08001731 displayFrames.mStable /* visibleFrame */, sTmpRect /* decorFrame */,
Jorim Jaggif081f062019-10-24 16:24:54 +02001732 displayFrames.mStable /* stableFrame */);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001733 // Let the status bar determine its size.
Riddle Hsuc7175762020-01-10 21:03:48 +08001734 mStatusBar.computeFrame(displayFrames);
Tiger Huang4a7835f2019-11-06 00:07:56 +08001735
Tiger Huang7c610aa2018-10-27 00:01:01 +08001736 // For layout, the status bar is always at the top with our fixed height.
1737 displayFrames.mStable.top = displayFrames.mUnrestricted.top
1738 + mStatusBarHeightForRotation[displayFrames.mRotation];
1739 // Make sure the status bar covers the entire cutout height
1740 displayFrames.mStable.top = Math.max(displayFrames.mStable.top,
1741 displayFrames.mDisplayCutoutSafe.top);
1742
Riddle Hsuc7175762020-01-10 21:03:48 +08001743 if (isRealLayout) {
1744 // Tell the bar controller where the collapsed status bar content is.
1745 sTmpRect.set(windowFrames.mContentFrame);
1746 sTmpRect.intersect(displayFrames.mDisplayCutoutSafe);
1747 sTmpRect.top = windowFrames.mContentFrame.top; // Ignore top display cutout inset
1748 sTmpRect.bottom = displayFrames.mStable.top; // Use collapsed status bar size
1749 mStatusBarController.setContentFrame(sTmpRect);
1750 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001751
Tiger Huang4a7835f2019-11-06 00:07:56 +08001752 boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0
1753 || mDisplayContent.getInsetsPolicy().isTransient(ITYPE_STATUS_BAR);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001754 boolean statusBarTranslucent = (sysui
1755 & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001756
1757 // If the status bar is hidden, we don't want to cause windows behind it to scroll.
1758 if (mStatusBar.isVisibleLw() && !statusBarTransient) {
1759 // Status bar may go away, so the screen area it occupies is available to apps but just
1760 // covering them when the status bar is visible.
1761 final Rect dockFrame = displayFrames.mDock;
1762 dockFrame.top = displayFrames.mStable.top;
1763 displayFrames.mContent.set(dockFrame);
1764 displayFrames.mVoiceContent.set(dockFrame);
1765 displayFrames.mCurrent.set(dockFrame);
1766
1767 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " + String.format(
1768 "dock=%s content=%s cur=%s", dockFrame.toString(),
1769 displayFrames.mContent.toString(), displayFrames.mCurrent.toString()));
1770
Jorim Jaggi4981f152019-03-26 18:58:45 +01001771 if (!statusBarTranslucent && !mStatusBarController.wasRecentlyTranslucent()
1772 && !mStatusBar.isAnimatingLw()) {
1773
Tiger Huang7c610aa2018-10-27 00:01:01 +08001774 // If the opaque status bar is currently requested to be visible, and not in the
1775 // process of animating on or off, then we can tell the app that it is covered by
1776 // it.
1777 displayFrames.mSystem.top = displayFrames.mStable.top;
1778 }
1779 }
1780 return mStatusBarController.checkHiddenLw();
1781 }
1782
1783 private boolean layoutNavigationBar(DisplayFrames displayFrames, int uiMode, boolean navVisible,
1784 boolean navTranslucent, boolean navAllowedHidden,
Riddle Hsuc7175762020-01-10 21:03:48 +08001785 boolean statusBarForcesShowingNavigation, boolean isRealLayout) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001786 if (mNavigationBar == null) {
1787 return false;
1788 }
1789
1790 final Rect navigationFrame = sTmpNavFrame;
1791 boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
1792 // Force the navigation bar to its appropriate place and size. We need to do this directly,
1793 // instead of relying on it to bubble up from the nav bar, because this needs to change
1794 // atomically with screen rotations.
1795 final int rotation = displayFrames.mRotation;
1796 final int displayHeight = displayFrames.mDisplayHeight;
1797 final int displayWidth = displayFrames.mDisplayWidth;
1798 final Rect dockFrame = displayFrames.mDock;
Riddle Hsuc7175762020-01-10 21:03:48 +08001799 final int navBarPosition = navigationBarPosition(displayWidth, displayHeight, rotation);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001800
1801 final Rect cutoutSafeUnrestricted = sTmpRect;
1802 cutoutSafeUnrestricted.set(displayFrames.mUnrestricted);
1803 cutoutSafeUnrestricted.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
1804
Riddle Hsuc7175762020-01-10 21:03:48 +08001805 if (navBarPosition == NAV_BAR_BOTTOM) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001806 // It's a system nav bar or a portrait screen; nav bar goes on bottom.
1807 final int top = cutoutSafeUnrestricted.bottom
1808 - getNavigationBarHeight(rotation, uiMode);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001809 final int topNavBar = cutoutSafeUnrestricted.bottom
Matthew Nga7f24bc2019-04-09 17:06:41 -07001810 - getNavigationBarFrameHeight(rotation, uiMode);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001811 navigationFrame.set(0, topNavBar, displayWidth, displayFrames.mUnrestricted.bottom);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001812 displayFrames.mStable.bottom = displayFrames.mStableFullscreen.bottom = top;
1813 if (transientNavBarShowing) {
1814 mNavigationBarController.setBarShowingLw(true);
1815 } else if (navVisible) {
1816 mNavigationBarController.setBarShowingLw(true);
Jorim Jaggif081f062019-10-24 16:24:54 +02001817 dockFrame.bottom = displayFrames.mRestricted.bottom = top;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001818 } else {
1819 // We currently want to hide the navigation UI - unless we expanded the status bar.
1820 mNavigationBarController.setBarShowingLw(statusBarForcesShowingNavigation);
1821 }
1822 if (navVisible && !navTranslucent && !navAllowedHidden
1823 && !mNavigationBar.isAnimatingLw()
1824 && !mNavigationBarController.wasRecentlyTranslucent()) {
1825 // If the opaque nav bar is currently requested to be visible and not in the process
1826 // of animating on or off, then we can tell the app that it is covered by it.
1827 displayFrames.mSystem.bottom = top;
1828 }
Riddle Hsuc7175762020-01-10 21:03:48 +08001829 } else if (navBarPosition == NAV_BAR_RIGHT) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001830 // Landscape screen; nav bar goes to the right.
1831 final int left = cutoutSafeUnrestricted.right
1832 - getNavigationBarWidth(rotation, uiMode);
Matthew Nga7f24bc2019-04-09 17:06:41 -07001833 navigationFrame.set(left, 0, displayFrames.mUnrestricted.right, displayHeight);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001834 displayFrames.mStable.right = displayFrames.mStableFullscreen.right = left;
1835 if (transientNavBarShowing) {
1836 mNavigationBarController.setBarShowingLw(true);
1837 } else if (navVisible) {
1838 mNavigationBarController.setBarShowingLw(true);
Jorim Jaggif081f062019-10-24 16:24:54 +02001839 dockFrame.right = displayFrames.mRestricted.right = left;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001840 } else {
1841 // We currently want to hide the navigation UI - unless we expanded the status bar.
1842 mNavigationBarController.setBarShowingLw(statusBarForcesShowingNavigation);
1843 }
1844 if (navVisible && !navTranslucent && !navAllowedHidden
1845 && !mNavigationBar.isAnimatingLw()
1846 && !mNavigationBarController.wasRecentlyTranslucent()) {
1847 // If the nav bar is currently requested to be visible, and not in the process of
1848 // animating on or off, then we can tell the app that it is covered by it.
1849 displayFrames.mSystem.right = left;
1850 }
Riddle Hsuc7175762020-01-10 21:03:48 +08001851 } else if (navBarPosition == NAV_BAR_LEFT) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001852 // Seascape screen; nav bar goes to the left.
1853 final int right = cutoutSafeUnrestricted.left
1854 + getNavigationBarWidth(rotation, uiMode);
Matthew Nga7f24bc2019-04-09 17:06:41 -07001855 navigationFrame.set(displayFrames.mUnrestricted.left, 0, right, displayHeight);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001856 displayFrames.mStable.left = displayFrames.mStableFullscreen.left = right;
1857 if (transientNavBarShowing) {
1858 mNavigationBarController.setBarShowingLw(true);
1859 } else if (navVisible) {
1860 mNavigationBarController.setBarShowingLw(true);
Jorim Jaggif081f062019-10-24 16:24:54 +02001861 dockFrame.left = displayFrames.mRestricted.left = right;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001862 } else {
1863 // We currently want to hide the navigation UI - unless we expanded the status bar.
1864 mNavigationBarController.setBarShowingLw(statusBarForcesShowingNavigation);
1865 }
1866 if (navVisible && !navTranslucent && !navAllowedHidden
1867 && !mNavigationBar.isAnimatingLw()
1868 && !mNavigationBarController.wasRecentlyTranslucent()) {
1869 // If the nav bar is currently requested to be visible, and not in the process of
1870 // animating on or off, then we can tell the app that it is covered by it.
1871 displayFrames.mSystem.left = right;
1872 }
1873 }
1874
1875 // Make sure the content and current rectangles are updated to account for the restrictions
1876 // from the navigation bar.
1877 displayFrames.mCurrent.set(dockFrame);
1878 displayFrames.mVoiceContent.set(dockFrame);
1879 displayFrames.mContent.set(dockFrame);
1880 // And compute the final frame.
1881 sTmpRect.setEmpty();
Riddle Hsuc7175762020-01-10 21:03:48 +08001882 final WindowFrames windowFrames = mNavigationBar.getLayoutingWindowFrames();
1883 windowFrames.setFrames(navigationFrame /* parentFrame */,
Jorim Jaggif081f062019-10-24 16:24:54 +02001884 navigationFrame /* displayFrame */,
Tiger Huang7c610aa2018-10-27 00:01:01 +08001885 displayFrames.mDisplayCutoutSafe /* contentFrame */,
1886 navigationFrame /* visibleFrame */, sTmpRect /* decorFrame */,
Jorim Jaggif081f062019-10-24 16:24:54 +02001887 navigationFrame /* stableFrame */);
Riddle Hsuc7175762020-01-10 21:03:48 +08001888 mNavigationBar.computeFrame(displayFrames);
1889 if (isRealLayout) {
1890 mNavigationBarPosition = navBarPosition;
1891 mNavigationBarController.setContentFrame(windowFrames.mContentFrame);
Tiger Huang4a7835f2019-11-06 00:07:56 +08001892 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001893
1894 if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + navigationFrame);
1895 return mNavigationBarController.checkHiddenLw();
1896 }
1897
1898 private void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
Jorim Jaggif081f062019-10-24 16:24:54 +02001899 boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf,
Tiger Huang7c610aa2018-10-27 00:01:01 +08001900 DisplayFrames displayFrames) {
1901 if (!win.isInputMethodTarget() && attached.isInputMethodTarget()) {
1902 // Here's a special case: if the child window is not the 'dock window'
1903 // or input method target, and the window it is attached to is below
1904 // the dock window, then the frames we computed for the window it is
1905 // attached to can not be used because the dock is effectively part
1906 // of the underlying window and the attached window is floating on top
1907 // of the whole thing. So, we ignore the attached window and explicitly
1908 // compute the frames that would be appropriate without the dock.
1909 vf.set(displayFrames.mDock);
1910 cf.set(displayFrames.mDock);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001911 df.set(displayFrames.mDock);
1912 } else {
Jorim Jaggid6490572019-04-16 14:57:56 +02001913
Jorim Jaggif081f062019-10-24 16:24:54 +02001914 // In case we forced the window to draw behind the navigation bar, restrict df to
1915 // DF.Restricted to simulate old compat behavior.
Jorim Jaggia72b4cc2019-04-16 15:38:49 +02001916 Rect parentDisplayFrame = attached.getDisplayFrameLw();
Jorim Jaggid6490572019-04-16 14:57:56 +02001917 final WindowManager.LayoutParams attachedAttrs = attached.mAttrs;
1918 if ((attachedAttrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0
1919 && (attachedAttrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
1920 && (attachedAttrs.systemUiVisibility
1921 & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0) {
Jorim Jaggia72b4cc2019-04-16 15:38:49 +02001922 parentDisplayFrame = new Rect(parentDisplayFrame);
Jorim Jaggif081f062019-10-24 16:24:54 +02001923 parentDisplayFrame.intersect(displayFrames.mRestricted);
Jorim Jaggid6490572019-04-16 14:57:56 +02001924 }
1925
Tiger Huang7c610aa2018-10-27 00:01:01 +08001926 // The effective display frame of the attached window depends on whether it is taking
1927 // care of insetting its content. If not, we need to use the parent's content frame so
1928 // that the entire window is positioned within that content. Otherwise we can use the
Jorim Jaggif081f062019-10-24 16:24:54 +02001929 // parent display frame and let the attached window take care of positioning its content
Tiger Huang7c610aa2018-10-27 00:01:01 +08001930 // appropriately.
1931 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
1932 // Set the content frame of the attached window to the parent's decor frame
1933 // (same as content frame when IME isn't present) if specifically requested by
1934 // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
1935 // Otherwise, use the overscan frame.
1936 cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
Jorim Jaggif081f062019-10-24 16:24:54 +02001937 ? attached.getContentFrameLw() : parentDisplayFrame);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001938 } else {
1939 // If the window is resizing, then we want to base the content frame on our attached
1940 // content frame to resize...however, things can be tricky if the attached window is
1941 // NOT in resize mode, in which case its content frame will be larger.
1942 // Ungh. So to deal with that, make sure the content frame we end up using is not
1943 // covering the IM dock.
1944 cf.set(attached.getContentFrameLw());
1945 if (attached.isVoiceInteraction()) {
1946 cf.intersectUnchecked(displayFrames.mVoiceContent);
1947 } else if (win.isInputMethodTarget() || attached.isInputMethodTarget()) {
1948 cf.intersectUnchecked(displayFrames.mContent);
1949 }
1950 }
Jorim Jaggid6490572019-04-16 14:57:56 +02001951 df.set(insetDecors ? parentDisplayFrame : cf);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001952 vf.set(attached.getVisibleFrameLw());
1953 }
1954 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached window should be
1955 // positioned relative to its parent or the entire screen.
1956 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 ? attached.getFrameLw() : df);
1957 }
1958
1959 private void applyStableConstraints(int sysui, int fl, Rect r, DisplayFrames displayFrames) {
1960 if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) == 0) {
1961 return;
1962 }
1963 // If app is requesting a stable layout, don't let the content insets go below the stable
1964 // values.
1965 if ((fl & FLAG_FULLSCREEN) != 0) {
1966 r.intersectUnchecked(displayFrames.mStableFullscreen);
1967 } else {
1968 r.intersectUnchecked(displayFrames.mStable);
1969 }
1970 }
1971
1972 private boolean canReceiveInput(WindowState win) {
1973 boolean notFocusable =
1974 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
1975 boolean altFocusableIm =
1976 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
1977 boolean notFocusableForIm = notFocusable ^ altFocusableIm;
1978 return !notFocusableForIm;
1979 }
1980
1981 /**
1982 * Called for each window attached to the window manager as layout is proceeding. The
1983 * implementation of this function must take care of setting the window's frame, either here or
1984 * in finishLayout().
1985 *
1986 * @param win The window being positioned.
1987 * @param attached For sub-windows, the window it is attached to; this
1988 * window will already have had layoutWindow() called on it
1989 * so you can use its Rect. Otherwise null.
1990 * @param displayFrames The display frames.
1991 */
1992 public void layoutWindowLw(WindowState win, WindowState attached, DisplayFrames displayFrames) {
1993 // We've already done the navigation bar, status bar, and all screen decor windows. If the
1994 // status bar can receive input, we need to layout it again to accommodate for the IME
1995 // window.
1996 if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar
1997 || mScreenDecorWindows.contains(win)) {
1998 return;
1999 }
2000 final WindowManager.LayoutParams attrs = win.getAttrs();
Tiger Huang7c610aa2018-10-27 00:01:01 +08002001
2002 final int type = attrs.type;
2003 final int fl = PolicyControl.getWindowFlags(win, attrs);
2004 final int pfl = attrs.privateFlags;
2005 final int sim = attrs.softInputMode;
2006 final int requestedSysUiFl = PolicyControl.getSystemUiVisibility(null, attrs);
2007 final int sysUiFl = requestedSysUiFl | getImpliedSysUiFlagsForLayout(attrs);
2008
Riddle Hsu6f548e92020-01-13 13:34:09 +08002009 displayFrames = win.getDisplayFrames(displayFrames);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002010 final WindowFrames windowFrames = win.getWindowFrames();
2011
Tiger Huang7c610aa2018-10-27 00:01:01 +08002012 sTmpLastParentFrame.set(windowFrames.mParentFrame);
2013 final Rect pf = windowFrames.mParentFrame;
2014 final Rect df = windowFrames.mDisplayFrame;
Tiger Huang7c610aa2018-10-27 00:01:01 +08002015 final Rect cf = windowFrames.mContentFrame;
2016 final Rect vf = windowFrames.mVisibleFrame;
2017 final Rect dcf = windowFrames.mDecorFrame;
2018 final Rect sf = windowFrames.mStableFrame;
2019 dcf.setEmpty();
2020 windowFrames.setParentFrameWasClippedByDisplayCutout(false);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002021
2022 final boolean hasNavBar = hasNavigationBar() && mNavigationBar != null
2023 && mNavigationBar.isVisibleLw();
2024
2025 final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
2026
Tiger Huang7c610aa2018-10-27 00:01:01 +08002027 final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) == FLAG_LAYOUT_IN_SCREEN;
2028 final boolean layoutInsetDecor = (fl & FLAG_LAYOUT_INSET_DECOR) == FLAG_LAYOUT_INSET_DECOR;
2029
2030 sf.set(displayFrames.mStable);
2031
Tiger Huang4a7835f2019-11-06 00:07:56 +08002032 if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
Tiger Huang52724442020-01-20 21:38:42 +08002033 final @InsetsType int typesToFit = attrs.getFitInsetsTypes();
2034 final @InsetsSide int sidesToFit = attrs.getFitInsetsSides();
Tiger Huang4a7835f2019-11-06 00:07:56 +08002035 final ArraySet<Integer> types = InsetsState.toInternalType(typesToFit);
2036 final Rect dfu = displayFrames.mUnrestricted;
2037 Insets insets = Insets.of(0, 0, 0, 0);
2038 for (int i = types.size() - 1; i >= 0; i--) {
Tiger Huang82520fc2019-12-19 22:29:20 +08002039 insets = Insets.max(insets, mDisplayContent.getInsetsPolicy()
Tiger Huang4a7835f2019-11-06 00:07:56 +08002040 .getInsetsForDispatch(win).getSource(types.valueAt(i))
Tiger Huang52724442020-01-20 21:38:42 +08002041 .calculateInsets(dfu, attrs.isFitInsetsIgnoringVisibility()));
Tiger Huang4a7835f2019-11-06 00:07:56 +08002042 }
2043 final int left = (sidesToFit & Side.LEFT) != 0 ? insets.left : 0;
2044 final int top = (sidesToFit & Side.TOP) != 0 ? insets.top : 0;
2045 final int right = (sidesToFit & Side.RIGHT) != 0 ? insets.right : 0;
2046 final int bottom = (sidesToFit & Side.BOTTOM) != 0 ? insets.bottom : 0;
2047 df.set(left, top, dfu.right - right, dfu.bottom - bottom);
2048 if (attached == null) {
2049 pf.set(df);
2050 vf.set(adjust != SOFT_INPUT_ADJUST_NOTHING
2051 ? displayFrames.mCurrent : displayFrames.mDock);
2052 } else {
2053 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 ? attached.getFrameLw() : df);
2054 vf.set(attached.getVisibleFrameLw());
2055 }
2056 cf.set(adjust != SOFT_INPUT_ADJUST_RESIZE
2057 ? displayFrames.mDock : displayFrames.mContent);
2058 dcf.set(displayFrames.mSystem);
2059 } else if (type == TYPE_INPUT_METHOD) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002060 vf.set(displayFrames.mDock);
2061 cf.set(displayFrames.mDock);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002062 df.set(displayFrames.mDock);
Tiger Huang4a7835f2019-11-06 00:07:56 +08002063 pf.set(displayFrames.mDock);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002064 // IM dock windows layout below the nav bar...
Jorim Jaggif081f062019-10-24 16:24:54 +02002065 pf.bottom = df.bottom = displayFrames.mUnrestricted.bottom;
Tiger Huang7c610aa2018-10-27 00:01:01 +08002066 // ...with content insets above the nav bar
2067 cf.bottom = vf.bottom = displayFrames.mStable.bottom;
2068 if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
2069 // The status bar forces the navigation bar while it's visible. Make sure the IME
2070 // avoids the navigation bar in that case.
2071 if (mNavigationBarPosition == NAV_BAR_RIGHT) {
Jorim Jaggif081f062019-10-24 16:24:54 +02002072 pf.right = df.right = cf.right = vf.right =
Tiger Huang7c610aa2018-10-27 00:01:01 +08002073 displayFrames.mStable.right;
2074 } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
Jorim Jaggif081f062019-10-24 16:24:54 +02002075 pf.left = df.left = cf.left = vf.left = displayFrames.mStable.left;
Tiger Huang7c610aa2018-10-27 00:01:01 +08002076 }
2077 }
2078
Matthew Nga7f24bc2019-04-09 17:06:41 -07002079 // In case the navigation bar is on the bottom, we use the frame height instead of the
2080 // regular height for the insets we send to the IME as we need some space to show
2081 // additional buttons in SystemUI when the IME is up.
2082 if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
2083 final int rotation = displayFrames.mRotation;
2084 final int uimode = mService.mPolicy.getUiMode();
2085 final int navHeightOffset = getNavigationBarFrameHeight(rotation, uimode)
2086 - getNavigationBarHeight(rotation, uimode);
2087 if (navHeightOffset > 0) {
2088 cf.bottom -= navHeightOffset;
2089 sf.bottom -= navHeightOffset;
2090 vf.bottom -= navHeightOffset;
2091 dcf.bottom -= navHeightOffset;
2092 }
2093 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002094
2095 // IM dock windows always go to the bottom of the screen.
2096 attrs.gravity = Gravity.BOTTOM;
2097 } else if (type == TYPE_VOICE_INTERACTION) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002098 df.set(displayFrames.mUnrestricted);
2099 pf.set(displayFrames.mUnrestricted);
2100 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
2101 cf.set(displayFrames.mDock);
2102 } else {
2103 cf.set(displayFrames.mContent);
2104 }
2105 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
2106 vf.set(displayFrames.mCurrent);
2107 } else {
2108 vf.set(cf);
2109 }
2110 } else if (type == TYPE_WALLPAPER) {
Jorim Jaggif081f062019-10-24 16:24:54 +02002111 layoutWallpaper(displayFrames, pf, df, cf);
Jorim Jaggif2ce4fa2020-01-21 22:32:37 +01002112 } else if (win == mStatusBar || type == TYPE_NOTIFICATION_SHADE) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002113 df.set(displayFrames.mUnrestricted);
2114 pf.set(displayFrames.mUnrestricted);
2115 cf.set(displayFrames.mStable);
2116 vf.set(displayFrames.mStable);
2117
2118 if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
Tiger Huang7fe7f682019-10-26 01:11:23 +08002119 // cf.bottom should not be below the stable bottom, or the content might be obscured
2120 // by the navigation bar.
2121 if (cf.bottom > displayFrames.mContent.bottom) {
2122 cf.bottom = displayFrames.mContent.bottom;
2123 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002124 } else {
Tiger Huang7fe7f682019-10-26 01:11:23 +08002125 if (cf.bottom > displayFrames.mDock.bottom) {
2126 cf.bottom = displayFrames.mDock.bottom;
2127 }
2128 if (vf.bottom > displayFrames.mContent.bottom) {
2129 vf.bottom = displayFrames.mContent.bottom;
2130 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002131 }
2132 } else {
2133 dcf.set(displayFrames.mSystem);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002134 final boolean isAppWindow =
2135 type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW;
2136 final boolean topAtRest =
2137 win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
Jorim Jaggia2e648e2019-10-25 15:06:53 +02002138 if (isAppWindow && !topAtRest) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002139 if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
2140 && (fl & FLAG_FULLSCREEN) == 0
2141 && (fl & FLAG_TRANSLUCENT_STATUS) == 0
2142 && (fl & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
Jorim Jaggia6aabac2019-03-11 14:23:16 -07002143 && (pfl & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) == 0) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002144 // Ensure policy decor includes status bar
2145 dcf.top = displayFrames.mStable.top;
2146 }
2147 if ((fl & FLAG_TRANSLUCENT_NAVIGATION) == 0
2148 && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
Jorim Jaggia6aabac2019-03-11 14:23:16 -07002149 && (fl & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
2150 && (pfl & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) == 0) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002151 // Ensure policy decor includes navigation bar
2152 dcf.bottom = displayFrames.mStable.bottom;
2153 dcf.right = displayFrames.mStable.right;
2154 }
2155 }
2156
2157 if (layoutInScreen && layoutInsetDecor) {
2158 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
2159 + "): IN_SCREEN, INSET_DECOR");
2160 // This is the case for a normal activity window: we want it to cover all of the
2161 // screen space, and it can take care of moving its contents to account for screen
2162 // decorations that intrude into that space.
2163 if (attached != null) {
2164 // If this window is attached to another, our display
2165 // frame is the same as the one we are attached to.
Jorim Jaggif081f062019-10-24 16:24:54 +02002166 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, cf, vf,
Tiger Huang7c610aa2018-10-27 00:01:01 +08002167 displayFrames);
2168 } else {
Heemin Seog2cf45dd2020-02-24 15:43:29 -08002169 if (type == TYPE_STATUS_BAR_ADDITIONAL || type == TYPE_STATUS_BAR_SUB_PANEL) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002170 // Status bar panels are the only windows who can go on top of the status
2171 // bar. They are protected by the STATUS_BAR_SERVICE permission, so they
2172 // have the same privileges as the status bar itself.
2173 //
2174 // However, they should still dodge the navigation bar if it exists.
2175
Jorim Jaggif081f062019-10-24 16:24:54 +02002176 pf.left = df.left = hasNavBar
Tiger Huang7c610aa2018-10-27 00:01:01 +08002177 ? displayFrames.mDock.left : displayFrames.mUnrestricted.left;
Jorim Jaggif081f062019-10-24 16:24:54 +02002178 pf.top = df.top = displayFrames.mUnrestricted.top;
2179 pf.right = df.right = hasNavBar
Tiger Huang7c610aa2018-10-27 00:01:01 +08002180 ? displayFrames.mRestricted.right
2181 : displayFrames.mUnrestricted.right;
Jorim Jaggif081f062019-10-24 16:24:54 +02002182 pf.bottom = df.bottom = hasNavBar
Tiger Huang7c610aa2018-10-27 00:01:01 +08002183 ? displayFrames.mRestricted.bottom
2184 : displayFrames.mUnrestricted.bottom;
2185
2186 if (DEBUG_LAYOUT) Slog.v(TAG, "Laying out status bar window: " + pf);
Jorim Jaggid6490572019-04-16 14:57:56 +02002187 } else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
Tiger Huang7c610aa2018-10-27 00:01:01 +08002188 && (type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW
Charles Chen64172bb2019-04-22 17:30:29 +08002189 || type == TYPE_VOLUME_OVERLAY
2190 || type == TYPE_KEYGUARD_DIALOG)) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002191 // Asking for layout as if the nav bar is hidden, lets the application
2192 // extend into the unrestricted overscan screen area. We only do this for
2193 // application windows and certain system windows to ensure no window that
2194 // can be above the nav bar can do this.
Jorim Jaggif081f062019-10-24 16:24:54 +02002195 df.set(displayFrames.mUnrestricted);
2196 pf.set(displayFrames.mUnrestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002197 } else {
Jorim Jaggif081f062019-10-24 16:24:54 +02002198 df.set(displayFrames.mRestricted);
2199 pf.set(displayFrames.mRestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002200 }
2201
2202 if ((fl & FLAG_FULLSCREEN) == 0) {
2203 if (win.isVoiceInteraction()) {
2204 cf.set(displayFrames.mVoiceContent);
2205 } else {
Jorim Jaggi648e5882019-01-24 13:24:02 +01002206 // IME Insets are handled on the client for ADJUST_RESIZE in the new
2207 // insets world
2208 if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_NONE
2209 || adjust != SOFT_INPUT_ADJUST_RESIZE) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002210 cf.set(displayFrames.mDock);
2211 } else {
2212 cf.set(displayFrames.mContent);
2213 }
2214 }
2215 } else {
2216 // Full screen windows are always given a layout that is as if the status
2217 // bar and other transient decors are gone. This is to avoid bad states when
2218 // moving from a window that is not hiding the status bar to one that is.
2219 cf.set(displayFrames.mRestricted);
2220 }
2221 applyStableConstraints(sysUiFl, fl, cf, displayFrames);
Jorim Jaggi4e04eb22020-01-09 16:42:14 +01002222 if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE
2223 && adjust != SOFT_INPUT_ADJUST_NOTHING) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002224 vf.set(displayFrames.mCurrent);
2225 } else {
2226 vf.set(cf);
2227 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002228 }
2229 } else if (layoutInScreen || (sysUiFl
Tiger Huang4a7835f2019-11-06 00:07:56 +08002230 & (SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
Jorim Jaggid6490572019-04-16 14:57:56 +02002231 | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002232 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
2233 + "): IN_SCREEN");
2234 // A window that has requested to fill the entire screen just
2235 // gets everything, period.
Heemin Seog2cf45dd2020-02-24 15:43:29 -08002236 if (type == TYPE_STATUS_BAR_ADDITIONAL || type == TYPE_STATUS_BAR_SUB_PANEL) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002237 cf.set(displayFrames.mUnrestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002238 df.set(displayFrames.mUnrestricted);
2239 pf.set(displayFrames.mUnrestricted);
2240 if (hasNavBar) {
Jorim Jaggif081f062019-10-24 16:24:54 +02002241 pf.left = df.left = cf.left = displayFrames.mDock.left;
2242 pf.right = df.right = cf.right = displayFrames.mRestricted.right;
2243 pf.bottom = df.bottom = cf.bottom =
Tiger Huang7c610aa2018-10-27 00:01:01 +08002244 displayFrames.mRestricted.bottom;
2245 }
2246 if (DEBUG_LAYOUT) Slog.v(TAG, "Laying out IN_SCREEN status bar window: " + pf);
2247 } else if (type == TYPE_NAVIGATION_BAR || type == TYPE_NAVIGATION_BAR_PANEL) {
2248 // The navigation bar has Real Ultimate Power.
Tiger Huang7c610aa2018-10-27 00:01:01 +08002249 df.set(displayFrames.mUnrestricted);
2250 pf.set(displayFrames.mUnrestricted);
2251 if (DEBUG_LAYOUT) Slog.v(TAG, "Laying out navigation bar window: " + pf);
2252 } else if ((type == TYPE_SECURE_SYSTEM_OVERLAY || type == TYPE_SCREENSHOT)
2253 && ((fl & FLAG_FULLSCREEN) != 0)) {
2254 // Fullscreen secure system overlays get what they ask for. Screenshot region
2255 // selection overlay should also expand to full screen.
Jorim Jaggif081f062019-10-24 16:24:54 +02002256 cf.set(displayFrames.mUnrestricted);
2257 df.set(displayFrames.mUnrestricted);
2258 pf.set(displayFrames.mUnrestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002259 } else if (type == TYPE_BOOT_PROGRESS) {
2260 // Boot progress screen always covers entire display.
Jorim Jaggif081f062019-10-24 16:24:54 +02002261 cf.set(displayFrames.mUnrestricted);
2262 df.set(displayFrames.mUnrestricted);
2263 pf.set(displayFrames.mUnrestricted);
Jorim Jaggid6490572019-04-16 14:57:56 +02002264 } else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
wilsonshihe8321942019-10-18 18:39:46 +08002265 && (type == TYPE_NOTIFICATION_SHADE
Tiger Huang7c610aa2018-10-27 00:01:01 +08002266 || type == TYPE_TOAST
2267 || type == TYPE_DOCK_DIVIDER
2268 || type == TYPE_VOICE_INTERACTION_STARTING
2269 || (type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW))) {
2270 // Asking for layout as if the nav bar is hidden, lets the
2271 // application extend into the unrestricted screen area. We
2272 // only do this for application windows (or toasts) to ensure no window that
2273 // can be above the nav bar can do this.
2274 // XXX This assumes that an app asking for this will also
2275 // ask for layout in only content. We can't currently figure out
2276 // what the screen would be if only laying out to hide the nav bar.
2277 cf.set(displayFrames.mUnrestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002278 df.set(displayFrames.mUnrestricted);
2279 pf.set(displayFrames.mUnrestricted);
Tiger Huang4a7835f2019-11-06 00:07:56 +08002280 } else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002281 df.set(displayFrames.mRestricted);
2282 pf.set(displayFrames.mRestricted);
Jorim Jaggi648e5882019-01-24 13:24:02 +01002283
2284 // IME Insets are handled on the client for ADJUST_RESIZE in the new insets
2285 // world
2286 if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_NONE
2287 || adjust != SOFT_INPUT_ADJUST_RESIZE) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002288 cf.set(displayFrames.mDock);
2289 } else {
2290 cf.set(displayFrames.mContent);
2291 }
2292 } else {
2293 cf.set(displayFrames.mRestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002294 df.set(displayFrames.mRestricted);
2295 pf.set(displayFrames.mRestricted);
2296 }
2297
2298 applyStableConstraints(sysUiFl, fl, cf, displayFrames);
2299
Jorim Jaggi4e04eb22020-01-09 16:42:14 +01002300 if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE
2301 && adjust != SOFT_INPUT_ADJUST_NOTHING) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002302 vf.set(displayFrames.mCurrent);
2303 } else {
2304 vf.set(cf);
2305 }
2306 } else if (attached != null) {
2307 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
2308 + "): attached to " + attached);
2309 // A child window should be placed inside of the same visible
2310 // frame that its parent had.
Jorim Jaggif081f062019-10-24 16:24:54 +02002311 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, cf, vf,
Tiger Huang7c610aa2018-10-27 00:01:01 +08002312 displayFrames);
2313 } else {
2314 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
2315 + "): normal window");
2316 // Otherwise, a normal window must be placed inside the content
2317 // of all screen decorations.
Heemin Seog2cf45dd2020-02-24 15:43:29 -08002318 if (type == TYPE_STATUS_BAR_ADDITIONAL) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002319 // Status bar panels can go on
2320 // top of the status bar. They are protected by the STATUS_BAR_SERVICE
2321 // permission, so they have the same privileges as the status bar itself.
2322 cf.set(displayFrames.mRestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002323 df.set(displayFrames.mRestricted);
2324 pf.set(displayFrames.mRestricted);
Vishnu Nair9ccb1d22019-03-20 16:32:44 +00002325 } else if (type == TYPE_TOAST || type == TYPE_SYSTEM_ALERT) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002326 // These dialogs are stable to interim decor changes.
2327 cf.set(displayFrames.mStable);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002328 df.set(displayFrames.mStable);
2329 pf.set(displayFrames.mStable);
2330 } else {
2331 pf.set(displayFrames.mContent);
2332 if (win.isVoiceInteraction()) {
2333 cf.set(displayFrames.mVoiceContent);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002334 df.set(displayFrames.mVoiceContent);
2335 } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
2336 cf.set(displayFrames.mDock);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002337 df.set(displayFrames.mDock);
2338 } else {
2339 cf.set(displayFrames.mContent);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002340 df.set(displayFrames.mContent);
2341 }
Jorim Jaggi4e04eb22020-01-09 16:42:14 +01002342 if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE
2343 && adjust != SOFT_INPUT_ADJUST_NOTHING) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002344 vf.set(displayFrames.mCurrent);
2345 } else {
2346 vf.set(cf);
2347 }
2348 }
2349 }
2350 }
2351
2352 final int cutoutMode = attrs.layoutInDisplayCutoutMode;
2353 final boolean attachedInParent = attached != null && !layoutInScreen;
Tiger Huang4a7835f2019-11-06 00:07:56 +08002354 final boolean requestedFullscreen = (fl & FLAG_FULLSCREEN) != 0
2355 || (requestedSysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0
Jorim Jaggi0dd0cf92019-12-27 15:17:44 +01002356 || (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL
2357 && !win.getRequestedInsetsState().getSource(ITYPE_STATUS_BAR).isVisible());
Tiger Huang7c610aa2018-10-27 00:01:01 +08002358 final boolean requestedHideNavigation =
Tiger Huang4a7835f2019-11-06 00:07:56 +08002359 (requestedSysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
Jorim Jaggi0dd0cf92019-12-27 15:17:44 +01002360 || (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL
2361 && !win.getRequestedInsetsState().getSource(ITYPE_NAVIGATION_BAR)
2362 .isVisible());
Tiger Huang7c610aa2018-10-27 00:01:01 +08002363
2364 // TYPE_BASE_APPLICATION windows are never considered floating here because they don't get
2365 // cropped / shifted to the displayFrame in WindowState.
2366 final boolean floatingInScreenWindow = !attrs.isFullscreen() && layoutInScreen
2367 && type != TYPE_BASE_APPLICATION;
Tiger Huang7c610aa2018-10-27 00:01:01 +08002368 // Ensure that windows with a DEFAULT or NEVER display cutout mode are laid out in
2369 // the cutout safe zone.
shawnlin465b7de2020-02-11 20:45:35 +08002370 if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002371 final Rect displayCutoutSafeExceptMaybeBars = sTmpDisplayCutoutSafeExceptMaybeBarsRect;
2372 displayCutoutSafeExceptMaybeBars.set(displayFrames.mDisplayCutoutSafe);
shawnlin465b7de2020-02-11 20:45:35 +08002373 if (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES) {
2374 if (displayFrames.mDisplayWidth < displayFrames.mDisplayHeight) {
2375 displayCutoutSafeExceptMaybeBars.top = Integer.MIN_VALUE;
2376 displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
2377 } else {
2378 displayCutoutSafeExceptMaybeBars.left = Integer.MIN_VALUE;
2379 displayCutoutSafeExceptMaybeBars.right = Integer.MAX_VALUE;
2380 }
2381 }
2382
Tiger Huang7c610aa2018-10-27 00:01:01 +08002383 if (layoutInScreen && layoutInsetDecor && !requestedFullscreen
shawnlin465b7de2020-02-11 20:45:35 +08002384 && (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
2385 || cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES)) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002386 // At the top we have the status bar, so apps that are
2387 // LAYOUT_IN_SCREEN | LAYOUT_INSET_DECOR but not FULLSCREEN
2388 // already expect that there's an inset there and we don't need to exclude
2389 // the window from that area.
2390 displayCutoutSafeExceptMaybeBars.top = Integer.MIN_VALUE;
2391 }
2392 if (layoutInScreen && layoutInsetDecor && !requestedHideNavigation
shawnlin465b7de2020-02-11 20:45:35 +08002393 && (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
2394 || cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES)) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002395 // Same for the navigation bar.
2396 switch (mNavigationBarPosition) {
2397 case NAV_BAR_BOTTOM:
2398 displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
2399 break;
2400 case NAV_BAR_RIGHT:
2401 displayCutoutSafeExceptMaybeBars.right = Integer.MAX_VALUE;
2402 break;
2403 case NAV_BAR_LEFT:
2404 displayCutoutSafeExceptMaybeBars.left = Integer.MIN_VALUE;
2405 break;
2406 }
2407 }
2408 if (type == TYPE_INPUT_METHOD && mNavigationBarPosition == NAV_BAR_BOTTOM) {
2409 // The IME can always extend under the bottom cutout if the navbar is there.
2410 displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
2411 }
2412 // Windows that are attached to a parent and laid out in said parent already avoid
2413 // the cutout according to that parent and don't need to be further constrained.
2414 // Floating IN_SCREEN windows get what they ask for and lay out in the full screen.
2415 // They will later be cropped or shifted using the displayFrame in WindowState,
2416 // which prevents overlap with the DisplayCutout.
2417 if (!attachedInParent && !floatingInScreenWindow) {
2418 sTmpRect.set(pf);
2419 pf.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
2420 windowFrames.setParentFrameWasClippedByDisplayCutout(!sTmpRect.equals(pf));
2421 }
2422 // Make sure that NO_LIMITS windows clipped to the display don't extend under the
2423 // cutout.
2424 df.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
2425 }
2426
2427 // Content should never appear in the cutout.
2428 cf.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
2429
2430 // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
2431 // Also, we don't allow windows in multi-window mode to extend out of the screen.
2432 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && type != TYPE_SYSTEM_ERROR
Evan Rosky4fb1e912019-03-06 13:54:43 -08002433 && !win.inMultiWindowMode()) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002434 df.left = df.top = -10000;
2435 df.right = df.bottom = 10000;
2436 if (type != TYPE_WALLPAPER) {
Jorim Jaggif081f062019-10-24 16:24:54 +02002437 cf.left = cf.top = vf.left = vf.top = -10000;
2438 cf.right = cf.bottom = vf.right = vf.bottom = 10000;
Tiger Huang7c610aa2018-10-27 00:01:01 +08002439 }
2440 }
2441
2442 if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
2443 + ": sim=#" + Integer.toHexString(sim)
2444 + " attach=" + attached + " type=" + type
2445 + String.format(" flags=0x%08x", fl)
2446 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
Tiger Huang7c610aa2018-10-27 00:01:01 +08002447 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
2448 + " dcf=" + dcf.toShortString()
Jorim Jaggif081f062019-10-24 16:24:54 +02002449 + " sf=" + sf.toShortString());
Tiger Huang7c610aa2018-10-27 00:01:01 +08002450
2451 if (!sTmpLastParentFrame.equals(pf)) {
2452 windowFrames.setContentChanged(true);
2453 }
2454
Riddle Hsuc7175762020-01-10 21:03:48 +08002455 win.computeFrame(displayFrames);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002456 // Dock windows carve out the bottom of the screen, so normal windows
2457 // can't appear underneath them.
2458 if (type == TYPE_INPUT_METHOD && win.isVisibleLw()
2459 && !win.getGivenInsetsPendingLw()) {
2460 offsetInputMethodWindowLw(win, displayFrames);
2461 }
2462 if (type == TYPE_VOICE_INTERACTION && win.isVisibleLw()
2463 && !win.getGivenInsetsPendingLw()) {
2464 offsetVoiceInputWindowLw(win, displayFrames);
2465 }
2466 }
2467
Jorim Jaggif081f062019-10-24 16:24:54 +02002468 private void layoutWallpaper(DisplayFrames displayFrames, Rect pf, Rect df, Rect cf) {
2469 // The wallpaper has Real Ultimate Power
2470 df.set(displayFrames.mUnrestricted);
2471 pf.set(displayFrames.mUnrestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002472 cf.set(displayFrames.mUnrestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002473 }
2474
2475 private void offsetInputMethodWindowLw(WindowState win, DisplayFrames displayFrames) {
Winson Chung913690d2019-11-14 16:06:01 -08002476 final int rotation = displayFrames.mRotation;
2477 final int navBarPosition = navigationBarPosition(displayFrames.mDisplayWidth,
2478 displayFrames.mDisplayHeight, rotation);
2479
Tiger Huang7c610aa2018-10-27 00:01:01 +08002480 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
2481 top += win.getGivenContentInsetsLw().top;
2482 displayFrames.mContent.bottom = Math.min(displayFrames.mContent.bottom, top);
Winson Chung913690d2019-11-14 16:06:01 -08002483 if (navBarPosition == NAV_BAR_BOTTOM) {
2484 // Always account for the nav bar frame height on the bottom since in all navigation
2485 // modes we make room to show the dismiss-ime button, even if the IME does not report
2486 // insets (ie. when floating)
2487 final int uimode = mService.mPolicy.getUiMode();
2488 final int navFrameHeight = getNavigationBarFrameHeight(rotation, uimode);
2489 displayFrames.mContent.bottom = Math.min(displayFrames.mContent.bottom,
2490 displayFrames.mUnrestricted.bottom - navFrameHeight);
2491 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002492 displayFrames.mVoiceContent.bottom = Math.min(displayFrames.mVoiceContent.bottom, top);
2493 top = win.getVisibleFrameLw().top;
2494 top += win.getGivenVisibleInsetsLw().top;
2495 displayFrames.mCurrent.bottom = Math.min(displayFrames.mCurrent.bottom, top);
2496 if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
2497 + displayFrames.mDock.bottom + " mContentBottom="
2498 + displayFrames.mContent.bottom + " mCurBottom=" + displayFrames.mCurrent.bottom);
2499 }
2500
2501 private void offsetVoiceInputWindowLw(WindowState win, DisplayFrames displayFrames) {
2502 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
2503 top += win.getGivenContentInsetsLw().top;
2504 displayFrames.mVoiceContent.bottom = Math.min(displayFrames.mVoiceContent.bottom, top);
2505 }
2506
Riddle Hsuccf09402019-08-13 00:33:06 +08002507 WindowState getTopFullscreenOpaqueWindow() {
2508 return mTopFullscreenOpaqueWindowState;
2509 }
2510
2511 boolean isTopLayoutFullscreen() {
2512 return mTopIsFullscreen;
2513 }
2514
Tiger Huang7c610aa2018-10-27 00:01:01 +08002515 /**
2516 * Called following layout of all windows before each window has policy applied.
2517 */
2518 public void beginPostLayoutPolicyLw() {
2519 mTopFullscreenOpaqueWindowState = null;
2520 mTopFullscreenOpaqueOrDimmingWindowState = null;
2521 mTopDockedOpaqueWindowState = null;
2522 mTopDockedOpaqueOrDimmingWindowState = null;
2523 mForceStatusBar = false;
Tiger Huang7c610aa2018-10-27 00:01:01 +08002524 mForcingShowNavBar = false;
2525 mForcingShowNavBarLayer = -1;
2526
2527 mAllowLockscreenWhenOn = false;
2528 mShowingDream = false;
HEO SEUNG22d3ec22019-05-30 20:28:53 +09002529 mIsFreeformWindowOverlappingWithNavBar = false;
Tiger Huang7c610aa2018-10-27 00:01:01 +08002530 }
2531
2532 /**
2533 * Called following layout of all window to apply policy to each window.
2534 *
2535 * @param win The window being positioned.
2536 * @param attrs The LayoutParams of the window.
2537 * @param attached For sub-windows, the window it is attached to. Otherwise null.
2538 */
2539 public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
2540 WindowState attached, WindowState imeTarget) {
2541 final boolean affectsSystemUi = win.canAffectSystemUiFlags();
2542 if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": affectsSystemUi=" + affectsSystemUi);
2543 mService.mPolicy.applyKeyguardPolicyLw(win, imeTarget);
2544 final int fl = PolicyControl.getWindowFlags(win, attrs);
2545 if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi
2546 && attrs.type == TYPE_INPUT_METHOD) {
2547 mForcingShowNavBar = true;
2548 mForcingShowNavBarLayer = win.getSurfaceLayer();
2549 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002550
2551 boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
2552 && attrs.type < FIRST_SYSTEM_WINDOW;
2553 final int windowingMode = win.getWindowingMode();
2554 final boolean inFullScreenOrSplitScreenSecondaryWindowingMode =
2555 windowingMode == WINDOWING_MODE_FULLSCREEN
2556 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
2557 if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi) {
2558 if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
2559 mForceStatusBar = true;
2560 }
Galia Peycheva70b55712020-03-16 18:31:34 +01002561 if (win.isDreamWindow()) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002562 // If the lockscreen was showing when the dream started then wait
2563 // for the dream to draw before hiding the lockscreen.
2564 if (!mDreamingLockscreen
2565 || (win.isVisibleLw() && win.hasDrawnLw())) {
2566 mShowingDream = true;
2567 appWindow = true;
2568 }
2569 }
2570
2571 // For app windows that are not attached, we decide if all windows in the app they
2572 // represent should be hidden or if we should hide the lockscreen. For attached app
2573 // windows we defer the decision to the window it is attached to.
2574 if (appWindow && attached == null) {
2575 if (attrs.isFullscreen() && inFullScreenOrSplitScreenSecondaryWindowingMode) {
2576 if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
2577 mTopFullscreenOpaqueWindowState = win;
2578 if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
2579 mTopFullscreenOpaqueOrDimmingWindowState = win;
2580 }
2581 if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
2582 mAllowLockscreenWhenOn = true;
2583 }
2584 }
2585 }
2586 }
2587
2588 // Voice interaction overrides both top fullscreen and top docked.
Jorim Jaggi50150152019-03-27 23:08:58 +01002589 if (affectsSystemUi && attrs.type == TYPE_VOICE_INTERACTION) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002590 if (mTopFullscreenOpaqueWindowState == null) {
2591 mTopFullscreenOpaqueWindowState = win;
2592 if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
2593 mTopFullscreenOpaqueOrDimmingWindowState = win;
2594 }
2595 }
2596 if (mTopDockedOpaqueWindowState == null) {
2597 mTopDockedOpaqueWindowState = win;
2598 if (mTopDockedOpaqueOrDimmingWindowState == null) {
2599 mTopDockedOpaqueOrDimmingWindowState = win;
2600 }
2601 }
2602 }
2603
2604 // Keep track of the window if it's dimming but not necessarily fullscreen.
2605 if (mTopFullscreenOpaqueOrDimmingWindowState == null && affectsSystemUi
2606 && win.isDimming() && inFullScreenOrSplitScreenSecondaryWindowingMode) {
2607 mTopFullscreenOpaqueOrDimmingWindowState = win;
2608 }
2609
2610 // We need to keep track of the top "fullscreen" opaque window for the docked stack
2611 // separately, because both the "real fullscreen" opaque window and the one for the docked
2612 // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
2613 if (mTopDockedOpaqueWindowState == null && affectsSystemUi && appWindow && attached == null
2614 && attrs.isFullscreen() && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
2615 mTopDockedOpaqueWindowState = win;
2616 if (mTopDockedOpaqueOrDimmingWindowState == null) {
2617 mTopDockedOpaqueOrDimmingWindowState = win;
2618 }
2619 }
2620
HEO SEUNG22d3ec22019-05-30 20:28:53 +09002621 // Check if the freeform window overlaps with the navigation bar area.
2622 final WindowState navBarWin = hasNavigationBar() ? mNavigationBar : null;
2623 if (!mIsFreeformWindowOverlappingWithNavBar && win.inFreeformWindowingMode()
2624 && isOverlappingWithNavBar(win, navBarWin)) {
2625 mIsFreeformWindowOverlappingWithNavBar = true;
2626 }
2627
Tiger Huang7c610aa2018-10-27 00:01:01 +08002628 // Also keep track of any windows that are dimming but not necessarily fullscreen in the
2629 // docked stack.
2630 if (mTopDockedOpaqueOrDimmingWindowState == null && affectsSystemUi && win.isDimming()
2631 && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
2632 mTopDockedOpaqueOrDimmingWindowState = win;
2633 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002634 }
2635
2636 /**
2637 * Called following layout of all windows and after policy has been applied
2638 * to each window. If in this function you do
2639 * something that may have modified the animation state of another window,
2640 * be sure to return non-zero in order to perform another pass through layout.
2641 *
2642 * @return Return any bit set of
2643 * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_LAYOUT},
2644 * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_CONFIG},
2645 * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_WALLPAPER}, or
2646 * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_ANIM}.
2647 */
2648 public int finishPostLayoutPolicyLw() {
2649 int changes = 0;
2650 boolean topIsFullscreen = false;
2651
2652 // If we are not currently showing a dream then remember the current
2653 // lockscreen state. We will use this to determine whether the dream
2654 // started while the lockscreen was showing and remember this state
2655 // while the dream is showing.
2656 if (!mShowingDream) {
2657 mDreamingLockscreen = mService.mPolicy.isKeyguardShowingAndNotOccluded();
Tiger Huang7c610aa2018-10-27 00:01:01 +08002658 }
2659
2660 if (mStatusBar != null) {
2661 if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
Tiger Huang7c610aa2018-10-27 00:01:01 +08002662 + " top=" + mTopFullscreenOpaqueWindowState);
wilsonshihe8321942019-10-18 18:39:46 +08002663 final boolean forceShowStatusBar = (mStatusBar.getAttrs().privateFlags
2664 & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0;
2665 final boolean notificationShadeForcesShowingNavigation =
2666 mNotificationShade != null
2667 && (mNotificationShade.getAttrs().privateFlags
Tiger Huang7c610aa2018-10-27 00:01:01 +08002668 & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0;
wilsonshihe8321942019-10-18 18:39:46 +08002669
Tiger Huang7c610aa2018-10-27 00:01:01 +08002670 boolean topAppHidesStatusBar = topAppHidesStatusBar();
wilsonshihe8321942019-10-18 18:39:46 +08002671 if (mForceStatusBar || forceShowStatusBar) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002672 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
2673 if (mStatusBarController.setBarShowingLw(true)) {
2674 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2675 }
2676 // Maintain fullscreen layout until incoming animation is complete.
2677 topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
wilsonshihe8321942019-10-18 18:39:46 +08002678 // Transient status bar is not allowed if notification shade is expecting the
2679 // navigation keys from the user.
2680 if (notificationShadeForcesShowingNavigation
Tiger Huang7c610aa2018-10-27 00:01:01 +08002681 && mStatusBarController.isTransientShowing()) {
2682 mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
2683 mLastSystemUiFlags, mLastSystemUiFlags);
2684 }
2685 } else if (mTopFullscreenOpaqueWindowState != null) {
2686 topIsFullscreen = topAppHidesStatusBar;
2687 // The subtle difference between the window for mTopFullscreenOpaqueWindowState
2688 // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
2689 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the
2690 // case though.
2691 if (mStatusBarController.isTransientShowing()) {
2692 if (mStatusBarController.setBarShowingLw(true)) {
2693 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2694 }
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07002695 } else if (topIsFullscreen && !mDisplayContent.getDefaultTaskDisplayArea()
2696 .isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002697 if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
2698 if (mStatusBarController.setBarShowingLw(false)) {
2699 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2700 } else {
2701 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
2702 }
2703 } else {
2704 if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
2705 if (mStatusBarController.setBarShowingLw(true)) {
2706 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2707 }
2708 topAppHidesStatusBar = false;
2709 }
2710 }
2711 mStatusBarController.setTopAppHidesStatusBar(topAppHidesStatusBar);
2712 }
2713
2714 if (mTopIsFullscreen != topIsFullscreen) {
2715 if (!topIsFullscreen) {
2716 // Force another layout when status bar becomes fully shown.
2717 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2718 }
2719 mTopIsFullscreen = topIsFullscreen;
2720 }
2721
2722 if ((updateSystemUiVisibilityLw() & SYSTEM_UI_CHANGING_LAYOUT) != 0) {
2723 // If the navigation bar has been hidden or shown, we need to do another
2724 // layout pass to update that window.
2725 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2726 }
2727
2728 if (mShowingDream != mLastShowingDream) {
2729 mLastShowingDream = mShowingDream;
2730 mService.notifyShowingDreamChanged();
2731 }
2732
Tiger Huang7c610aa2018-10-27 00:01:01 +08002733 mService.mPolicy.setAllowLockscreenWhenOn(getDisplayId(), mAllowLockscreenWhenOn);
2734 return changes;
2735 }
2736
Tiger Huang7c610aa2018-10-27 00:01:01 +08002737 /**
2738 * @return Whether the top app should hide the statusbar based on the top fullscreen opaque
2739 * window.
2740 */
2741 private boolean topAppHidesStatusBar() {
hyok.kim332ccfc2019-07-02 15:39:43 +09002742 if (mTopFullscreenOpaqueWindowState == null || mForceShowSystemBars) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002743 return false;
2744 }
2745 final int fl = PolicyControl.getWindowFlags(null,
2746 mTopFullscreenOpaqueWindowState.getAttrs());
Adam Pardyl8c2d19c2019-09-16 17:15:38 +02002747 if (WindowManagerDebugConfig.DEBUG) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002748 Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw());
2749 Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
2750 + " lp.flags=0x" + Integer.toHexString(fl));
2751 }
2752 return (fl & LayoutParams.FLAG_FULLSCREEN) != 0
2753 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
2754 }
2755
2756 /**
Winson Chungda20fec2019-04-10 12:19:59 -07002757 * Called when the user is switched.
2758 */
2759 public void switchUser() {
2760 updateCurrentUserResources();
2761 }
2762
2763 /**
Tiger Huang7c610aa2018-10-27 00:01:01 +08002764 * Called when the resource overlays change.
2765 */
2766 public void onOverlayChangedLw() {
Winson Chungda20fec2019-04-10 12:19:59 -07002767 updateCurrentUserResources();
Tiger Huang7c610aa2018-10-27 00:01:01 +08002768 onConfigurationChanged();
Jeff Changb0a061e2019-03-11 11:39:54 +08002769 mSystemGestures.onConfigurationChanged();
Tiger Huang7c610aa2018-10-27 00:01:01 +08002770 }
2771
2772 /**
2773 * Called when the configuration has changed, and it's safe to load new values from resources.
2774 */
2775 public void onConfigurationChanged() {
2776 final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation();
2777
Winson Chungda20fec2019-04-10 12:19:59 -07002778 final Resources res = getCurrentUserResources();
Tiger Huang7c610aa2018-10-27 00:01:01 +08002779 final int portraitRotation = displayRotation.getPortraitRotation();
2780 final int upsideDownRotation = displayRotation.getUpsideDownRotation();
2781 final int landscapeRotation = displayRotation.getLandscapeRotation();
2782 final int seascapeRotation = displayRotation.getSeascapeRotation();
Matthew Nga7f24bc2019-04-09 17:06:41 -07002783 final int uiMode = mService.mPolicy.getUiMode();
Tiger Huang7c610aa2018-10-27 00:01:01 +08002784
Louis Changfc64c832018-12-04 11:38:26 +08002785 if (hasStatusBar()) {
2786 mStatusBarHeightForRotation[portraitRotation] =
2787 mStatusBarHeightForRotation[upsideDownRotation] =
2788 res.getDimensionPixelSize(R.dimen.status_bar_height_portrait);
2789 mStatusBarHeightForRotation[landscapeRotation] =
2790 mStatusBarHeightForRotation[seascapeRotation] =
2791 res.getDimensionPixelSize(R.dimen.status_bar_height_landscape);
2792 } else {
2793 mStatusBarHeightForRotation[portraitRotation] =
2794 mStatusBarHeightForRotation[upsideDownRotation] =
2795 mStatusBarHeightForRotation[landscapeRotation] =
2796 mStatusBarHeightForRotation[seascapeRotation] = 0;
2797 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002798
2799 // Height of the navigation bar when presented horizontally at bottom
2800 mNavigationBarHeightForRotationDefault[portraitRotation] =
2801 mNavigationBarHeightForRotationDefault[upsideDownRotation] =
2802 res.getDimensionPixelSize(R.dimen.navigation_bar_height);
2803 mNavigationBarHeightForRotationDefault[landscapeRotation] =
2804 mNavigationBarHeightForRotationDefault[seascapeRotation] =
2805 res.getDimensionPixelSize(R.dimen.navigation_bar_height_landscape);
2806
Matthew Nga7f24bc2019-04-09 17:06:41 -07002807 // Height of the navigation bar frame when presented horizontally at bottom
2808 mNavigationBarFrameHeightForRotationDefault[portraitRotation] =
2809 mNavigationBarFrameHeightForRotationDefault[upsideDownRotation] =
2810 res.getDimensionPixelSize(R.dimen.navigation_bar_frame_height);
2811 mNavigationBarFrameHeightForRotationDefault[landscapeRotation] =
2812 mNavigationBarFrameHeightForRotationDefault[seascapeRotation] =
2813 res.getDimensionPixelSize(R.dimen.navigation_bar_frame_height_landscape);
2814
Tiger Huang7c610aa2018-10-27 00:01:01 +08002815 // Width of the navigation bar when presented vertically along one side
2816 mNavigationBarWidthForRotationDefault[portraitRotation] =
2817 mNavigationBarWidthForRotationDefault[upsideDownRotation] =
2818 mNavigationBarWidthForRotationDefault[landscapeRotation] =
2819 mNavigationBarWidthForRotationDefault[seascapeRotation] =
2820 res.getDimensionPixelSize(R.dimen.navigation_bar_width);
2821
2822 if (ALTERNATE_CAR_MODE_NAV_SIZE) {
2823 // Height of the navigation bar when presented horizontally at bottom
2824 mNavigationBarHeightForRotationInCarMode[portraitRotation] =
2825 mNavigationBarHeightForRotationInCarMode[upsideDownRotation] =
2826 res.getDimensionPixelSize(R.dimen.navigation_bar_height_car_mode);
2827 mNavigationBarHeightForRotationInCarMode[landscapeRotation] =
2828 mNavigationBarHeightForRotationInCarMode[seascapeRotation] =
2829 res.getDimensionPixelSize(R.dimen.navigation_bar_height_landscape_car_mode);
2830
2831 // Width of the navigation bar when presented vertically along one side
2832 mNavigationBarWidthForRotationInCarMode[portraitRotation] =
2833 mNavigationBarWidthForRotationInCarMode[upsideDownRotation] =
2834 mNavigationBarWidthForRotationInCarMode[landscapeRotation] =
2835 mNavigationBarWidthForRotationInCarMode[seascapeRotation] =
2836 res.getDimensionPixelSize(R.dimen.navigation_bar_width_car_mode);
2837 }
2838
Winson Chung4723b4e2019-03-25 16:49:36 -07002839 mNavBarOpacityMode = res.getInteger(R.integer.config_navBarOpacityMode);
Mehdi Alizadehf2b28e92019-12-05 20:13:49 -08002840 mLeftGestureInset = mGestureNavigationSettingsObserver.getLeftSensitivity(res);
2841 mRightGestureInset = mGestureNavigationSettingsObserver.getRightSensitivity(res);
Sunny Goyal38412952020-04-17 11:35:37 -07002842 mNavButtonForcedVisible =
2843 mGestureNavigationSettingsObserver.areNavigationButtonForcedVisible();
Adrian Roos11dfd272019-03-25 19:21:26 +01002844 mNavigationBarLetsThroughTaps = res.getBoolean(R.bool.config_navBarTapThrough);
Winson Chung36941632019-04-19 15:21:38 -07002845 mNavigationBarAlwaysShowOnSideGesture =
2846 res.getBoolean(R.bool.config_navBarAlwaysShowOnSideEdgeGesture);
Winson Chung4723b4e2019-03-25 16:49:36 -07002847
Matthew Nga7f24bc2019-04-09 17:06:41 -07002848 // This should calculate how much above the frame we accept gestures.
Sunny Goyalb5e5bcb2019-05-22 14:28:44 -07002849 mBottomGestureAdditionalInset =
Matthew Nga7f24bc2019-04-09 17:06:41 -07002850 res.getDimensionPixelSize(R.dimen.navigation_bar_gesture_height)
Sunny Goyalb5e5bcb2019-05-22 14:28:44 -07002851 - getNavigationBarFrameHeight(portraitRotation, uiMode);
Adrian Roos11dfd272019-03-25 19:21:26 +01002852
Winson Chung4723b4e2019-03-25 16:49:36 -07002853 updateConfigurationAndScreenSizeDependentBehaviors();
2854 }
2855
2856 void updateConfigurationAndScreenSizeDependentBehaviors() {
Winson Chungda20fec2019-04-10 12:19:59 -07002857 final Resources res = getCurrentUserResources();
Winson Chung4723b4e2019-03-25 16:49:36 -07002858 mNavigationBarCanMove =
2859 mDisplayContent.mBaseDisplayWidth != mDisplayContent.mBaseDisplayHeight
2860 && res.getBoolean(R.bool.config_navBarCanMove);
Riddle Hsuccf09402019-08-13 00:33:06 +08002861 mDisplayContent.getDisplayRotation().updateUserDependentConfiguration(res);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002862 }
2863
Winson Chungda20fec2019-04-10 12:19:59 -07002864 /**
2865 * Updates the current user's resources to pick up any changes for the current user (including
2866 * overlay paths)
2867 */
2868 private void updateCurrentUserResources() {
2869 final int userId = mService.mAmInternal.getCurrentUserId();
2870 final Context uiContext = getSystemUiContext();
Winson Chung203e1522019-05-02 15:42:22 -07002871
2872 if (userId == UserHandle.USER_SYSTEM) {
2873 // Skip the (expensive) recreation of resources for the system user below and just
2874 // use the resources from the system ui context
2875 mCurrentUserResources = uiContext.getResources();
2876 return;
2877 }
2878
2879 // For non-system users, ensure that the resources are loaded from the current
2880 // user's package info (see ContextImpl.createDisplayContext)
Winson Chungda20fec2019-04-10 12:19:59 -07002881 final LoadedApk pi = ActivityThread.currentActivityThread().getPackageInfo(
2882 uiContext.getPackageName(), null, 0, userId);
Winson Chungda20fec2019-04-10 12:19:59 -07002883 mCurrentUserResources = ResourcesManager.getInstance().getResources(null,
2884 pi.getResDir(),
2885 null /* splitResDirs */,
2886 pi.getOverlayDirs(),
2887 pi.getApplicationInfo().sharedLibraryFiles,
2888 mDisplayContent.getDisplayId(),
2889 null /* overrideConfig */,
2890 uiContext.getResources().getCompatibilityInfo(),
Ryan Mitchell4579c0a2020-01-08 16:29:11 -08002891 null /* classLoader */,
2892 null /* loaders */);
Winson Chungda20fec2019-04-10 12:19:59 -07002893 }
2894
Tiger Huang7c610aa2018-10-27 00:01:01 +08002895 @VisibleForTesting
Winson Chungda20fec2019-04-10 12:19:59 -07002896 Resources getCurrentUserResources() {
2897 if (mCurrentUserResources == null) {
2898 updateCurrentUserResources();
2899 }
2900 return mCurrentUserResources;
2901 }
2902
2903 @VisibleForTesting
2904 Context getContext() {
2905 return mContext;
2906 }
2907
Charles Chen173ae782019-11-11 20:39:02 +08002908 Context getSystemUiContext() {
2909 return mUiContext;
Tiger Huang7c610aa2018-10-27 00:01:01 +08002910 }
2911
2912 private int getNavigationBarWidth(int rotation, int uiMode) {
2913 if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2914 return mNavigationBarWidthForRotationInCarMode[rotation];
2915 } else {
2916 return mNavigationBarWidthForRotationDefault[rotation];
2917 }
2918 }
2919
Charles Chen3dedec32019-01-24 22:19:37 +08002920 void notifyDisplayReady() {
wilsonshih643bf132019-02-27 12:49:19 +08002921 mHandler.post(() -> {
2922 final int displayId = getDisplayId();
2923 getStatusBarManagerInternal().onDisplayReady(displayId);
Felipe Leme34a861a2019-08-05 16:00:12 -07002924 final WallpaperManagerInternal wpMgr = LocalServices
2925 .getService(WallpaperManagerInternal.class);
2926 if (wpMgr != null) {
2927 wpMgr.onDisplayReady(displayId);
2928 }
wilsonshih643bf132019-02-27 12:49:19 +08002929 });
Charles Chen3dedec32019-01-24 22:19:37 +08002930 }
2931
Tiger Huang7c610aa2018-10-27 00:01:01 +08002932 /**
2933 * Return the display width available after excluding any screen
2934 * decorations that could never be removed in Honeycomb. That is, system bar or
2935 * button bar.
2936 */
2937 public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
2938 DisplayCutout displayCutout) {
2939 int width = fullWidth;
2940 if (hasNavigationBar()) {
Tiger Huang3d2b8982019-01-29 22:56:48 +08002941 final int navBarPosition = navigationBarPosition(fullWidth, fullHeight, rotation);
2942 if (navBarPosition == NAV_BAR_LEFT || navBarPosition == NAV_BAR_RIGHT) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002943 width -= getNavigationBarWidth(rotation, uiMode);
2944 }
2945 }
2946 if (displayCutout != null) {
2947 width -= displayCutout.getSafeInsetLeft() + displayCutout.getSafeInsetRight();
2948 }
2949 return width;
2950 }
2951
2952 private int getNavigationBarHeight(int rotation, int uiMode) {
2953 if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2954 return mNavigationBarHeightForRotationInCarMode[rotation];
2955 } else {
2956 return mNavigationBarHeightForRotationDefault[rotation];
2957 }
2958 }
2959
2960 /**
Matthew Nga7f24bc2019-04-09 17:06:41 -07002961 * Get the Navigation Bar Frame height. This dimension is the height of the navigation bar that
2962 * is used for spacing to show additional buttons on the navigation bar (such as the ime
2963 * switcher when ime is visible) while {@link #getNavigationBarHeight} is used for the visible
2964 * height that we send to the app as content insets that can be smaller.
2965 * <p>
2966 * In car mode it will return the same height as {@link #getNavigationBarHeight}
2967 *
2968 * @param rotation specifies rotation to return dimension from
2969 * @param uiMode to determine if in car mode
2970 * @return navigation bar frame height
2971 */
2972 private int getNavigationBarFrameHeight(int rotation, int uiMode) {
2973 if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2974 return mNavigationBarHeightForRotationInCarMode[rotation];
2975 } else {
2976 return mNavigationBarFrameHeightForRotationDefault[rotation];
2977 }
2978 }
2979
2980 /**
Tiger Huang7c610aa2018-10-27 00:01:01 +08002981 * Return the display height available after excluding any screen
2982 * decorations that could never be removed in Honeycomb. That is, system bar or
2983 * button bar.
2984 */
2985 public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
2986 DisplayCutout displayCutout) {
2987 int height = fullHeight;
2988 if (hasNavigationBar()) {
Tiger Huang3d2b8982019-01-29 22:56:48 +08002989 final int navBarPosition = navigationBarPosition(fullWidth, fullHeight, rotation);
2990 if (navBarPosition == NAV_BAR_BOTTOM) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002991 height -= getNavigationBarHeight(rotation, uiMode);
2992 }
2993 }
2994 if (displayCutout != null) {
2995 height -= displayCutout.getSafeInsetTop() + displayCutout.getSafeInsetBottom();
2996 }
2997 return height;
2998 }
2999
3000 /**
3001 * Return the available screen width that we should report for the
3002 * configuration. This must be no larger than
3003 * {@link #getNonDecorDisplayWidth(int, int, int, int, DisplayCutout)}; it may be smaller
3004 * than that to account for more transient decoration like a status bar.
3005 */
3006 public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
3007 DisplayCutout displayCutout) {
3008 return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode, displayCutout);
3009 }
3010
3011 /**
3012 * Return the available screen height that we should report for the
3013 * configuration. This must be no larger than
3014 * {@link #getNonDecorDisplayHeight(int, int, int, int, DisplayCutout)}; it may be smaller
3015 * than that to account for more transient decoration like a status bar.
3016 */
3017 public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
3018 DisplayCutout displayCutout) {
3019 // There is a separate status bar at the top of the display. We don't count that as part
3020 // of the fixed decor, since it can hide; however, for purposes of configurations,
3021 // we do want to exclude it since applications can't generally use that part
3022 // of the screen.
3023 int statusBarHeight = mStatusBarHeightForRotation[rotation];
3024 if (displayCutout != null) {
3025 // If there is a cutout, it may already have accounted for some part of the status
3026 // bar height.
3027 statusBarHeight = Math.max(0, statusBarHeight - displayCutout.getSafeInsetTop());
3028 }
3029 return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayCutout)
3030 - statusBarHeight;
3031 }
3032
Tiger Huang43b8fc22019-04-26 11:49:29 +08003033 /**
3034 * Return corner radius in pixels that should be used on windows in order to cover the display.
Dominik Laskowski26290bb2020-01-15 16:09:55 -08003035 *
3036 * The radius is only valid for internal displays, since the corner radius of external displays
3037 * is not known at build time when window corners are configured.
Tiger Huang43b8fc22019-04-26 11:49:29 +08003038 */
3039 float getWindowCornerRadius() {
Dominik Laskowski26290bb2020-01-15 16:09:55 -08003040 return mDisplayContent.getDisplay().getType() == TYPE_INTERNAL
Tiger Huang43b8fc22019-04-26 11:49:29 +08003041 ? ScreenDecorationsUtils.getWindowCornerRadius(mContext.getResources()) : 0f;
3042 }
3043
Tiger Huang7c610aa2018-10-27 00:01:01 +08003044 boolean isShowingDreamLw() {
3045 return mShowingDream;
3046 }
3047
3048 /**
Riddle Hsu61987bc2019-04-03 13:08:47 +08003049 * Calculates the stable insets if we already have the non-decor insets.
3050 *
3051 * @param inOutInsets The known non-decor insets. It will be modified to stable insets.
3052 * @param rotation The current display rotation.
3053 */
3054 void convertNonDecorInsetsToStableInsets(Rect inOutInsets, int rotation) {
3055 inOutInsets.top = Math.max(inOutInsets.top, mStatusBarHeightForRotation[rotation]);
3056 }
3057
3058 /**
Tiger Huang7c610aa2018-10-27 00:01:01 +08003059 * Calculates the stable insets without running a layout.
3060 *
3061 * @param displayRotation the current display rotation
3062 * @param displayWidth the current display width
3063 * @param displayHeight the current display height
3064 * @param displayCutout the current display cutout
3065 * @param outInsets the insets to return
3066 */
3067 public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
3068 DisplayCutout displayCutout, Rect outInsets) {
3069 outInsets.setEmpty();
3070
3071 // Navigation bar and status bar.
3072 getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, displayCutout, outInsets);
Riddle Hsu61987bc2019-04-03 13:08:47 +08003073 convertNonDecorInsetsToStableInsets(outInsets, displayRotation);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003074 }
3075
3076 /**
3077 * Calculates the insets for the areas that could never be removed in Honeycomb, i.e. system
3078 * bar or button bar. See {@link #getNonDecorDisplayWidth}.
3079 *
3080 * @param displayRotation the current display rotation
3081 * @param displayWidth the current display width
3082 * @param displayHeight the current display height
3083 * @param displayCutout the current display cutout
3084 * @param outInsets the insets to return
3085 */
3086 public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
3087 DisplayCutout displayCutout, Rect outInsets) {
3088 outInsets.setEmpty();
3089
3090 // Only navigation bar
3091 if (hasNavigationBar()) {
3092 final int uiMode = mService.mPolicy.getUiMode();
3093 int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
3094 if (position == NAV_BAR_BOTTOM) {
3095 outInsets.bottom = getNavigationBarHeight(displayRotation, uiMode);
3096 } else if (position == NAV_BAR_RIGHT) {
3097 outInsets.right = getNavigationBarWidth(displayRotation, uiMode);
3098 } else if (position == NAV_BAR_LEFT) {
3099 outInsets.left = getNavigationBarWidth(displayRotation, uiMode);
3100 }
3101 }
3102
3103 if (displayCutout != null) {
3104 outInsets.left += displayCutout.getSafeInsetLeft();
3105 outInsets.top += displayCutout.getSafeInsetTop();
3106 outInsets.right += displayCutout.getSafeInsetRight();
3107 outInsets.bottom += displayCutout.getSafeInsetBottom();
3108 }
3109 }
3110
Issei Suzukia5dbf522019-02-01 17:58:15 +01003111 /**
3112 * @see IWindowManager#setForwardedInsets
3113 */
3114 public void setForwardedInsets(@NonNull Insets forwardedInsets) {
3115 mForwardedInsets = forwardedInsets;
3116 }
3117
3118 @NonNull
3119 public Insets getForwardedInsets() {
3120 return mForwardedInsets;
3121 }
3122
Tiger Huang7c610aa2018-10-27 00:01:01 +08003123 @NavigationBarPosition
3124 int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
3125 if (navigationBarCanMove() && displayWidth > displayHeight) {
3126 if (displayRotation == Surface.ROTATION_270) {
3127 return NAV_BAR_LEFT;
3128 } else if (displayRotation == Surface.ROTATION_90) {
3129 return NAV_BAR_RIGHT;
3130 }
3131 }
3132 return NAV_BAR_BOTTOM;
3133 }
3134
3135 /**
3136 * @return The side of the screen where navigation bar is positioned.
3137 * @see WindowManagerPolicyConstants#NAV_BAR_LEFT
3138 * @see WindowManagerPolicyConstants#NAV_BAR_RIGHT
3139 * @see WindowManagerPolicyConstants#NAV_BAR_BOTTOM
3140 */
3141 @NavigationBarPosition
3142 public int getNavBarPosition() {
3143 return mNavigationBarPosition;
3144 }
3145
3146 /**
3147 * A new window has been focused.
3148 */
3149 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
3150 mFocusedWindow = newFocus;
3151 mLastFocusedWindow = lastFocus;
Issei Suzuki9f840c72018-12-07 15:09:30 -08003152 if (mDisplayContent.isDefaultDisplay) {
3153 mService.mPolicy.onDefaultDisplayFocusChangedLw(newFocus);
3154 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08003155 if ((updateSystemUiVisibilityLw() & SYSTEM_UI_CHANGING_LAYOUT) != 0) {
3156 // If the navigation bar has been hidden or shown, we need to do another
3157 // layout pass to update that window.
3158 return FINISH_LAYOUT_REDO_LAYOUT;
3159 }
3160 return 0;
3161 }
3162
Tiger Huang7c610aa2018-10-27 00:01:01 +08003163 private void requestTransientBars(WindowState swipeTarget) {
Tiger Huang82fd0ad2020-03-09 17:55:47 +08003164 if (!mService.mPolicy.isUserSetupComplete()) {
3165 // Swipe-up for navigation bar is disabled during setup
3166 return;
3167 }
3168 if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
3169 if (swipeTarget == mNavigationBar
3170 && !getInsetsPolicy().isHidden(ITYPE_NAVIGATION_BAR)) {
3171 // Don't show status bar when swiping on already visible navigation bar
Tiger Huang7c610aa2018-10-27 00:01:01 +08003172 return;
3173 }
Tiger Huang82fd0ad2020-03-09 17:55:47 +08003174 final InsetsSourceProvider provider = swipeTarget.getControllableInsetProvider();
3175 final InsetsControlTarget controlTarget = provider != null
3176 ? provider.getControlTarget() : null;
Jorim Jaggi026ed752020-01-29 00:30:24 +01003177
Tiger Huang82fd0ad2020-03-09 17:55:47 +08003178 // No transient mode on lockscreen (in notification shade window).
3179 if (controlTarget == null || controlTarget == getNotificationShade()) {
3180 return;
3181 }
3182 if (controlTarget.canShowTransient()) {
3183 mDisplayContent.getInsetsPolicy().showTransient(IntArray.wrap(
3184 new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
3185 } else {
3186 controlTarget.showInsets(Type.systemBars(), false);
3187 }
3188 } else {
3189 boolean sb = mStatusBarController.checkShowTransientBarLw();
3190 boolean nb = mNavigationBarController.checkShowTransientBarLw()
3191 && !isNavBarEmpty(mLastSystemUiFlags);
3192 if (sb || nb) {
3193 // Don't show status bar when swiping on already visible navigation bar
3194 if (!nb && swipeTarget == mNavigationBar) {
3195 if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
Jorim Jaggi956ca412019-01-07 14:49:14 +01003196 return;
3197 }
Tiger Huang82fd0ad2020-03-09 17:55:47 +08003198 if (sb) mStatusBarController.showTransient();
3199 if (nb) mNavigationBarController.showTransient();
3200 updateSystemUiVisibilityLw();
Tiger Huang7c610aa2018-10-27 00:01:01 +08003201 }
3202 }
Tiger Huang82fd0ad2020-03-09 17:55:47 +08003203 mImmersiveModeConfirmation.confirmCurrentPrompt();
Tiger Huang7c610aa2018-10-27 00:01:01 +08003204 }
3205
3206 private void disposeInputConsumer(InputConsumer inputConsumer) {
3207 if (inputConsumer != null) {
Arthur Hungde767252020-02-03 19:22:16 +08003208 inputConsumer.dispose();
Tiger Huang7c610aa2018-10-27 00:01:01 +08003209 }
3210 }
3211
wilsonshihe8321942019-10-18 18:39:46 +08003212 boolean isKeyguardShowing() {
3213 return mService.mPolicy.isKeyguardShowing();
Tiger Huang7c610aa2018-10-27 00:01:01 +08003214 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08003215 private boolean isKeyguardOccluded() {
3216 // TODO (b/113840485): Handle per display keyguard.
3217 return mService.mPolicy.isKeyguardOccluded();
3218 }
3219
Jorim Jaggi956ca412019-01-07 14:49:14 +01003220 InsetsPolicy getInsetsPolicy() {
3221 return mDisplayContent.getInsetsPolicy();
3222 }
3223
Tiger Huang7c610aa2018-10-27 00:01:01 +08003224 void resetSystemUiVisibilityLw() {
3225 mLastSystemUiFlags = 0;
3226 updateSystemUiVisibilityLw();
3227 }
3228
Tiger Huangdd6db472020-02-13 21:38:46 +08003229 int updateSystemUiVisibilityLw() {
Tiger Huang7c610aa2018-10-27 00:01:01 +08003230 // If there is no window focused, there will be nobody to handle the events
3231 // anyway, so just hang on in whatever state we're in until things settle down.
3232 WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
3233 : mTopFullscreenOpaqueWindowState;
3234 if (winCandidate == null) {
3235 return 0;
3236 }
3237
3238 // The immersive mode confirmation should never affect the system bar visibility, otherwise
3239 // it will unhide the navigation bar and hide itself.
3240 if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
3241
3242 // The immersive mode confirmation took the focus from mLastFocusedWindow which was
3243 // controlling the system ui visibility. So if mLastFocusedWindow can still receive
3244 // keys, we let it keep controlling the visibility.
3245 final boolean lastFocusCanReceiveKeys =
3246 (mLastFocusedWindow != null && mLastFocusedWindow.canReceiveKeys());
wilsonshihe8321942019-10-18 18:39:46 +08003247 winCandidate = isKeyguardShowing() ? mNotificationShade
Tiger Huang7c610aa2018-10-27 00:01:01 +08003248 : lastFocusCanReceiveKeys ? mLastFocusedWindow
3249 : mTopFullscreenOpaqueWindowState;
3250 if (winCandidate == null) {
3251 return 0;
3252 }
3253 }
3254 final WindowState win = winCandidate;
wilsonshihe8321942019-10-18 18:39:46 +08003255 if (win.getAttrs().type == TYPE_NOTIFICATION_SHADE && isKeyguardShowing()
3256 && isKeyguardOccluded()) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08003257 // We are updating at a point where the keyguard has gotten
3258 // focus, but we were last in a state where the top window is
3259 // hiding it. This is probably because the keyguard as been
3260 // shown while the top window was displayed, so we want to ignore
3261 // it here because this is just a very transient change and it
3262 // will quickly lose focus once it correctly gets hidden.
3263 return 0;
3264 }
3265
Jorim Jaggi28620472019-01-02 23:21:49 +01003266 mDisplayContent.getInsetsPolicy().updateBarControlTarget(win);
Jorim Jaggib6030952018-10-23 18:31:52 +02003267
Tiger Huang7c610aa2018-10-27 00:01:01 +08003268 int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
3269 & ~mResettingSystemUiFlags
3270 & ~mForceClearedSystemUiFlags;
3271 if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
3272 tmpVisibility
3273 &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
3274 }
3275
Jorim Jaggi956ca412019-01-07 14:49:14 +01003276 final int fullscreenAppearance = updateLightStatusBarAppearanceLw(0 /* vis */,
3277 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
3278 final int dockedAppearance = updateLightStatusBarAppearanceLw(0 /* vis */,
3279 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
Evan Rosky40bf15c2020-04-02 20:23:36 -07003280 final boolean inSplitScreen =
Andrii Kulianf9df4a82020-03-31 12:09:27 -07003281 mService.mRoot.getDefaultTaskDisplayArea().isSplitScreenModeActivated();
Evan Rosky40bf15c2020-04-02 20:23:36 -07003282 if (inSplitScreen) {
3283 mService.getStackBounds(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD,
3284 mDockedStackBounds);
3285 } else {
3286 mDockedStackBounds.setEmpty();
3287 }
Jorim Jaggi956ca412019-01-07 14:49:14 +01003288 mService.getStackBounds(inSplitScreen ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
3289 : WINDOWING_MODE_FULLSCREEN,
Tiger Huangd5f0b9a2019-10-10 10:34:57 +02003290 ACTIVITY_TYPE_UNDEFINED, mNonDockedStackBounds);
Tiger Huange218e422020-03-06 21:36:12 +08003291 final Pair<Integer, WindowState> result =
Tarandeep Singhe439dec2019-04-22 12:28:43 -07003292 updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
3293 final int visibility = result.first;
Tiger Huange218e422020-03-06 21:36:12 +08003294 final WindowState navColorWin = result.second;
3295 final boolean isNavbarColorManagedByIme =
3296 navColorWin != null && navColorWin == mDisplayContent.mInputMethodWindow;
3297 final int opaqueAppearance = InsetsFlags.getAppearance(visibility)
3298 & (APPEARANCE_OPAQUE_STATUS_BARS | APPEARANCE_OPAQUE_NAVIGATION_BARS);
3299 final int appearance = ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL
3300 ? updateLightNavigationBarAppearanceLw(win.mAttrs.insetsFlags.appearance,
3301 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState,
3302 mDisplayContent.mInputMethodWindow, navColorWin) | opaqueAppearance
3303 : InsetsFlags.getAppearance(visibility);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003304 final int diff = visibility ^ mLastSystemUiFlags;
Jorim Jaggi956ca412019-01-07 14:49:14 +01003305 final InsetsPolicy insetsPolicy = getInsetsPolicy();
3306 final boolean isFullscreen = (visibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
3307 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)) != 0
3308 || (PolicyControl.getWindowFlags(win, win.mAttrs) & FLAG_FULLSCREEN) != 0
Tiger Huang332793b2019-10-29 23:21:27 +08003309 || (mStatusBar != null && insetsPolicy.isHidden(ITYPE_STATUS_BAR))
Jorim Jaggi956ca412019-01-07 14:49:14 +01003310 || (mNavigationBar != null && insetsPolicy.isHidden(
Tiger Huang332793b2019-10-29 23:21:27 +08003311 ITYPE_NAVIGATION_BAR));
Jorim Jaggi956ca412019-01-07 14:49:14 +01003312 final int behavior = win.mAttrs.insetsFlags.behavior;
3313 final boolean isImmersive = (visibility & (View.SYSTEM_UI_FLAG_IMMERSIVE
3314 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)) != 0
3315 || behavior == BEHAVIOR_SHOW_BARS_BY_SWIPE
3316 || behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
Tiger Huang0dbd5372019-10-26 00:24:22 +08003317 if (diff == 0
Jorim Jaggi956ca412019-01-07 14:49:14 +01003318 && mLastAppearance == appearance
3319 && mLastFullscreenAppearance == fullscreenAppearance
3320 && mLastDockedAppearance == dockedAppearance
Tiger Huang4a7835f2019-11-06 00:07:56 +08003321 && mLastBehavior == behavior
Jorim Jaggi956ca412019-01-07 14:49:14 +01003322 && mLastFocusIsFullscreen == isFullscreen
3323 && mLastFocusIsImmersive == isImmersive
Tiger Huang7c610aa2018-10-27 00:01:01 +08003324 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
3325 && mLastDockedStackBounds.equals(mDockedStackBounds)) {
3326 return 0;
3327 }
Tiger Huang0dbd5372019-10-26 00:24:22 +08003328
3329 // Obtains which types should show transient and which types should abort transient.
3330 // If there is no transient state change, this pair will contain two empty arrays.
3331 final Pair<int[], int[]> transientState = getTransientState(visibility, mLastSystemUiFlags);
3332
Tiger Huang7c610aa2018-10-27 00:01:01 +08003333 mLastSystemUiFlags = visibility;
Jorim Jaggi956ca412019-01-07 14:49:14 +01003334 mLastAppearance = appearance;
3335 mLastFullscreenAppearance = fullscreenAppearance;
3336 mLastDockedAppearance = dockedAppearance;
Tiger Huang4a7835f2019-11-06 00:07:56 +08003337 mLastBehavior = behavior;
Jorim Jaggi956ca412019-01-07 14:49:14 +01003338 mLastFocusIsFullscreen = isFullscreen;
3339 mLastFocusIsImmersive = isImmersive;
Riddle Hsu4d6a63f2019-03-29 19:14:43 +08003340 mLastNonDockedStackBounds.set(mNonDockedStackBounds);
3341 mLastDockedStackBounds.set(mDockedStackBounds);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003342 final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
3343 final Rect dockedStackBounds = new Rect(mDockedStackBounds);
Jorim Jaggi956ca412019-01-07 14:49:14 +01003344 final AppearanceRegion[] appearanceRegions = inSplitScreen
3345 ? new AppearanceRegion[]{
3346 new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds),
3347 new AppearanceRegion(dockedAppearance, dockedStackBounds)}
3348 : new AppearanceRegion[]{
3349 new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds)};
Vishnu Nair015d8cd2019-11-18 15:56:30 -08003350 String cause = win.toString();
Tiger Huang7c610aa2018-10-27 00:01:01 +08003351 mHandler.post(() -> {
3352 StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
3353 if (statusBar != null) {
3354 final int displayId = getDisplayId();
Tiger Huang0dbd5372019-10-26 00:24:22 +08003355 statusBar.setDisableFlags(displayId, visibility & StatusBarManager.DISABLE_MASK,
Vishnu Nair015d8cd2019-11-18 15:56:30 -08003356 cause);
Tiger Huang0dbd5372019-10-26 00:24:22 +08003357 if (transientState.first.length > 0) {
3358 statusBar.showTransient(displayId, transientState.first);
Jorim Jaggi956ca412019-01-07 14:49:14 +01003359 }
Tiger Huang0dbd5372019-10-26 00:24:22 +08003360 if (transientState.second.length > 0) {
3361 statusBar.abortTransient(displayId, transientState.second);
3362 }
3363 statusBar.onSystemBarAppearanceChanged(displayId, appearance,
3364 appearanceRegions, isNavbarColorManagedByIme);
Jorim Jaggi956ca412019-01-07 14:49:14 +01003365 statusBar.topAppWindowChanged(displayId, isFullscreen, isImmersive);
3366
3367 // TODO(b/118118435): Remove this after removing system UI visibilities.
Vishnu Nair015d8cd2019-11-18 15:56:30 -08003368 synchronized (mLock) {
3369 mDisplayContent.statusBarVisibilityChanged(
3370 visibility & ~(View.STATUS_BAR_UNHIDE | View.NAVIGATION_BAR_UNHIDE));
3371 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08003372 }
3373 });
3374 return diff;
3375 }
3376
Tiger Huang0dbd5372019-10-26 00:24:22 +08003377 private static Pair<int[], int[]> getTransientState(int vis, int oldVis) {
3378 final IntArray typesToShow = new IntArray(0);
3379 final IntArray typesToAbort = new IntArray(0);
Tiger Huang332793b2019-10-29 23:21:27 +08003380 updateTransientState(vis, oldVis, View.STATUS_BAR_TRANSIENT, ITYPE_STATUS_BAR, typesToShow,
Tiger Huang0dbd5372019-10-26 00:24:22 +08003381 typesToAbort);
3382 updateTransientState(vis, oldVis, View.NAVIGATION_BAR_TRANSIENT,
Tiger Huang332793b2019-10-29 23:21:27 +08003383 ITYPE_NAVIGATION_BAR, typesToShow, typesToAbort);
Tiger Huang0dbd5372019-10-26 00:24:22 +08003384 return Pair.create(typesToShow.toArray(), typesToAbort.toArray());
Tiger Huang7c610aa2018-10-27 00:01:01 +08003385 }
3386
Tiger Huang0dbd5372019-10-26 00:24:22 +08003387 private static void updateTransientState(int vis, int oldVis, int transientFlag,
Tiger Huang332793b2019-10-29 23:21:27 +08003388 @InternalInsetsType int type, IntArray typesToShow, IntArray typesToAbort) {
Tiger Huang0dbd5372019-10-26 00:24:22 +08003389 final boolean wasTransient = (oldVis & transientFlag) != 0;
3390 final boolean isTransient = (vis & transientFlag) != 0;
3391 if (!wasTransient && isTransient) {
3392 typesToShow.add(type);
3393 } else if (wasTransient && !isTransient) {
3394 typesToAbort.add(type);
3395 }
3396 }
3397
3398 private int updateLightStatusBarAppearanceLw(@Appearance int appearance, WindowState opaque,
Jorim Jaggi956ca412019-01-07 14:49:14 +01003399 WindowState opaqueOrDimming) {
wilsonshihe8321942019-10-18 18:39:46 +08003400 final boolean onKeyguard = isKeyguardShowing() && !isKeyguardOccluded();
3401 final WindowState statusColorWin = onKeyguard ? mNotificationShade : opaqueOrDimming;
Jorim Jaggi956ca412019-01-07 14:49:14 +01003402 if (statusColorWin != null && (statusColorWin == opaque || onKeyguard)) {
3403 // If the top fullscreen-or-dimming window is also the top fullscreen, respect
3404 // its light flag.
Tiger Huang332793b2019-10-29 23:21:27 +08003405 appearance &= ~APPEARANCE_LIGHT_STATUS_BARS;
Tiger Huang0dbd5372019-10-26 00:24:22 +08003406 final int legacyAppearance = InsetsFlags.getAppearance(
3407 PolicyControl.getSystemUiVisibility(statusColorWin, null));
3408 appearance |= (statusColorWin.mAttrs.insetsFlags.appearance | legacyAppearance)
Tiger Huang332793b2019-10-29 23:21:27 +08003409 & APPEARANCE_LIGHT_STATUS_BARS;
Jorim Jaggi956ca412019-01-07 14:49:14 +01003410 } else if (statusColorWin != null && statusColorWin.isDimming()) {
3411 // Otherwise if it's dimming, clear the light flag.
Tiger Huang332793b2019-10-29 23:21:27 +08003412 appearance &= ~APPEARANCE_LIGHT_STATUS_BARS;
Jorim Jaggi956ca412019-01-07 14:49:14 +01003413 }
3414 return appearance;
3415 }
3416
Tiger Huang7c610aa2018-10-27 00:01:01 +08003417 @VisibleForTesting
3418 @Nullable
3419 static WindowState chooseNavigationColorWindowLw(WindowState opaque,
3420 WindowState opaqueOrDimming, WindowState imeWindow,
3421 @NavigationBarPosition int navBarPosition) {
3422 // If the IME window is visible and FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS is set, then IME
3423 // window can be navigation color window.
3424 final boolean imeWindowCanNavColorWindow = imeWindow != null
3425 && imeWindow.isVisibleLw()
3426 && navBarPosition == NAV_BAR_BOTTOM
3427 && (PolicyControl.getWindowFlags(imeWindow, null)
3428 & WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
3429
3430 if (opaque != null && opaqueOrDimming == opaque) {
3431 // If the top fullscreen-or-dimming window is also the top fullscreen, respect it
3432 // unless IME window is also eligible, since currently the IME window is always show
3433 // above the opaque fullscreen app window, regardless of the IME target window.
3434 // TODO(b/31559891): Maybe we need to revisit this condition once b/31559891 is fixed.
3435 return imeWindowCanNavColorWindow ? imeWindow : opaque;
3436 }
3437
3438 if (opaqueOrDimming == null || !opaqueOrDimming.isDimming()) {
3439 // No dimming window is involved. Determine the result only with the IME window.
3440 return imeWindowCanNavColorWindow ? imeWindow : null;
3441 }
3442
3443 if (!imeWindowCanNavColorWindow) {
3444 // No IME window is involved. Determine the result only with opaqueOrDimming.
3445 return opaqueOrDimming;
3446 }
3447
3448 // The IME window and the dimming window are competing. Check if the dimming window can be
3449 // IME target or not.
3450 if (LayoutParams.mayUseInputMethod(PolicyControl.getWindowFlags(opaqueOrDimming, null))) {
3451 // The IME window is above the dimming window.
3452 return imeWindow;
3453 } else {
3454 // The dimming window is above the IME window.
3455 return opaqueOrDimming;
3456 }
3457 }
3458
3459 @VisibleForTesting
3460 static int updateLightNavigationBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming,
3461 WindowState imeWindow, WindowState navColorWin) {
3462
3463 if (navColorWin != null) {
3464 if (navColorWin == imeWindow || navColorWin == opaque) {
3465 // Respect the light flag.
3466 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
3467 vis |= PolicyControl.getSystemUiVisibility(navColorWin, null)
3468 & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
3469 } else if (navColorWin == opaqueOrDimming && navColorWin.isDimming()) {
3470 // Clear the light flag for dimming window.
3471 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
3472 }
3473 }
3474 return vis;
3475 }
3476
Tiger Huange218e422020-03-06 21:36:12 +08003477 @VisibleForTesting
3478 static int updateLightNavigationBarAppearanceLw(int appearance, WindowState opaque,
3479 WindowState opaqueOrDimming, WindowState imeWindow, WindowState navColorWin) {
3480
3481 if (navColorWin != null) {
3482 if (navColorWin == imeWindow || navColorWin == opaque) {
3483 // Respect the light flag.
3484 appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS;
3485 appearance |= navColorWin.mAttrs.insetsFlags.appearance
3486 & APPEARANCE_LIGHT_NAVIGATION_BARS;
3487 } else if (navColorWin == opaqueOrDimming && navColorWin.isDimming()) {
3488 // Clear the light flag for dimming window.
3489 appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS;
3490 }
3491 }
3492 return appearance;
3493 }
3494
3495 private Pair<Integer, WindowState> updateSystemBarsLw(WindowState win, int oldVis, int vis) {
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -07003496 final boolean dockedStackVisible = mDisplayContent.getDefaultTaskDisplayArea()
3497 .isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
3498 final boolean freeformStackVisible = mDisplayContent.getDefaultTaskDisplayArea()
3499 .isStackVisible(WINDOWING_MODE_FREEFORM);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003500 final boolean resizing = mDisplayContent.getDockedDividerController().isResizing();
3501
3502 // We need to force system bars when the docked stack is visible, when the freeform stack
hyok.kim332ccfc2019-07-02 15:39:43 +09003503 // is focused but also when we are resizing for the transitions when docked stack
Tiger Huang7c610aa2018-10-27 00:01:01 +08003504 // visibility changes.
hyok.kim332ccfc2019-07-02 15:39:43 +09003505 mForceShowSystemBars = dockedStackVisible || win.inFreeformWindowingMode() || resizing
Brad Stenninge0573692019-03-11 13:52:46 -07003506 || mForceShowSystemBarsFromExternal;
wilsonshihe8321942019-10-18 18:39:46 +08003507 final boolean forceOpaqueStatusBar = mForceShowSystemBars && !isKeyguardShowing();
Tiger Huang7c610aa2018-10-27 00:01:01 +08003508
3509 // apply translucent bar vis flags
wilsonshihe8321942019-10-18 18:39:46 +08003510 WindowState fullscreenTransWin = isKeyguardShowing() && !isKeyguardOccluded()
3511 ? mNotificationShade
Tiger Huang7c610aa2018-10-27 00:01:01 +08003512 : mTopFullscreenOpaqueWindowState;
3513 vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
3514 vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
Adrian Roosfaba4062019-05-14 15:27:17 +02003515 int dockedVis = mStatusBarController.applyTranslucentFlagLw(
Tiger Huang7c610aa2018-10-27 00:01:01 +08003516 mTopDockedOpaqueWindowState, 0, 0);
Adrian Roosfaba4062019-05-14 15:27:17 +02003517 dockedVis = mNavigationBarController.applyTranslucentFlagLw(
3518 mTopDockedOpaqueWindowState, dockedVis, 0);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003519
3520 final boolean fullscreenDrawsStatusBarBackground =
3521 drawsStatusBarBackground(vis, mTopFullscreenOpaqueWindowState);
3522 final boolean dockedDrawsStatusBarBackground =
3523 drawsStatusBarBackground(dockedVis, mTopDockedOpaqueWindowState);
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003524 final boolean fullscreenDrawsNavBarBackground =
3525 drawsNavigationBarBackground(vis, mTopFullscreenOpaqueWindowState);
Adrian Roosfaba4062019-05-14 15:27:17 +02003526 final boolean dockedDrawsNavigationBarBackground =
3527 drawsNavigationBarBackground(dockedVis, mTopDockedOpaqueWindowState);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003528
3529 // prevent status bar interaction from clearing certain flags
3530 int type = win.getAttrs().type;
wilsonshihe8321942019-10-18 18:39:46 +08003531 boolean notificationShadeHasFocus = type == TYPE_NOTIFICATION_SHADE;
3532 if (notificationShadeHasFocus && !isKeyguardShowing()) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08003533 int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
3534 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
3535 | View.SYSTEM_UI_FLAG_IMMERSIVE
3536 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
3537 | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
3538 if (isKeyguardOccluded()) {
3539 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
3540 }
3541 vis = (vis & ~flags) | (oldVis & flags);
3542 }
3543
3544 if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
3545 vis |= View.STATUS_BAR_TRANSPARENT;
3546 vis &= ~View.STATUS_BAR_TRANSLUCENT;
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003547 } else if (forceOpaqueStatusBar) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08003548 vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
3549 }
3550
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003551 vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing,
Adrian Roosfaba4062019-05-14 15:27:17 +02003552 fullscreenDrawsNavBarBackground, dockedDrawsNavigationBarBackground);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003553
3554 // update status bar
3555 boolean immersiveSticky =
3556 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
3557 final boolean hideStatusBarWM =
3558 mTopFullscreenOpaqueWindowState != null
3559 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
3560 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
3561 final boolean hideStatusBarSysui =
3562 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
3563 final boolean hideNavBarSysui =
3564 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
3565
3566 final boolean transientStatusBarAllowed = mStatusBar != null
wilsonshihe8321942019-10-18 18:39:46 +08003567 && (notificationShadeHasFocus || (!mForceShowSystemBars
Tiger Huang7c610aa2018-10-27 00:01:01 +08003568 && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
3569
3570 final boolean transientNavBarAllowed = mNavigationBar != null
3571 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
3572
3573 final long now = SystemClock.uptimeMillis();
3574 final boolean pendingPanic = mPendingPanicGestureUptime != 0
3575 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
3576 final DisplayPolicy defaultDisplayPolicy =
3577 mService.getDefaultDisplayContentLocked().getDisplayPolicy();
wilsonshihe8321942019-10-18 18:39:46 +08003578 if (pendingPanic && hideNavBarSysui && !isKeyguardShowing()
Tiger Huang7c610aa2018-10-27 00:01:01 +08003579 // TODO (b/111955725): Show keyguard presentation on all external displays
3580 && defaultDisplayPolicy.isKeyguardDrawComplete()) {
3581 // The user performed the panic gesture recently, we're about to hide the bars,
3582 // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
3583 mPendingPanicGestureUptime = 0;
3584 mStatusBarController.showTransient();
3585 if (!isNavBarEmpty(vis)) {
3586 mNavigationBarController.showTransient();
3587 }
3588 }
3589
3590 final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
3591 && !transientStatusBarAllowed && hideStatusBarSysui;
3592 final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
3593 && !transientNavBarAllowed;
3594 if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
3595 // clear the clearable flags instead
3596 clearClearableFlagsLw();
3597 vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
3598 }
3599
3600 final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
3601 immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
3602 final boolean navAllowedHidden = immersive || immersiveSticky;
3603
3604 if (hideNavBarSysui && !navAllowedHidden
3605 && mService.mPolicy.getWindowLayerLw(win)
3606 > mService.mPolicy.getWindowLayerFromTypeLw(TYPE_INPUT_CONSUMER)) {
3607 // We can't hide the navbar from this window otherwise the input consumer would not get
3608 // the input events.
3609 vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
3610 }
3611
3612 vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
3613
3614 // update navigation bar
Tiger Huangdd6db472020-02-13 21:38:46 +08003615 boolean newInsetsMode = ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL;
3616 boolean oldImmersiveMode = newInsetsMode ? mLastImmersiveMode : isImmersiveMode(oldVis);
3617 boolean newImmersiveMode = newInsetsMode ? isImmersiveMode(win) : isImmersiveMode(vis);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003618 if (oldImmersiveMode != newImmersiveMode) {
Tiger Huangdd6db472020-02-13 21:38:46 +08003619 mLastImmersiveMode = newImmersiveMode;
Tiger Huang7c610aa2018-10-27 00:01:01 +08003620 final String pkg = win.getOwningPackage();
3621 mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
3622 mService.mPolicy.isUserSetupComplete(),
3623 isNavBarEmpty(win.getSystemUiVisibility()));
3624 }
3625
3626 vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
3627
3628 final WindowState navColorWin = chooseNavigationColorWindowLw(
3629 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState,
3630 mDisplayContent.mInputMethodWindow, mNavigationBarPosition);
3631 vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState,
3632 mTopFullscreenOpaqueOrDimmingWindowState,
3633 mDisplayContent.mInputMethodWindow, navColorWin);
3634
Tiger Huange218e422020-03-06 21:36:12 +08003635 return Pair.create(vis, navColorWin);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003636 }
3637
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003638 private boolean drawsBarBackground(int vis, WindowState win, BarController controller,
3639 int translucentFlag) {
3640 if (!controller.isTransparentAllowed(win)) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08003641 return false;
3642 }
3643 if (win == null) {
3644 return true;
3645 }
3646
3647 final boolean drawsSystemBars =
3648 (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
3649 final boolean forceDrawsSystemBars =
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003650 (win.getAttrs().privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
Tiger Huang7c610aa2018-10-27 00:01:01 +08003651
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003652 return forceDrawsSystemBars || drawsSystemBars && (vis & translucentFlag) == 0;
3653 }
3654
3655 private boolean drawsStatusBarBackground(int vis, WindowState win) {
3656 return drawsBarBackground(vis, win, mStatusBarController, FLAG_TRANSLUCENT_STATUS);
3657 }
3658
3659 private boolean drawsNavigationBarBackground(int vis, WindowState win) {
3660 return drawsBarBackground(vis, win, mNavigationBarController, FLAG_TRANSLUCENT_NAVIGATION);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003661 }
3662
3663 /**
3664 * @return the current visibility flags with the nav-bar opacity related flags toggled based
3665 * on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
3666 */
3667 private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003668 boolean freeformStackVisible, boolean isDockedDividerResizing,
Adrian Roosfaba4062019-05-14 15:27:17 +02003669 boolean fullscreenDrawsBackground, boolean dockedDrawsNavigationBarBackground) {
3670 if (mNavBarOpacityMode == NAV_BAR_FORCE_TRANSPARENT) {
3671 if (fullscreenDrawsBackground && dockedDrawsNavigationBarBackground) {
3672 visibility = setNavBarTransparentFlag(visibility);
3673 } else if (dockedStackVisible) {
3674 visibility = setNavBarOpaqueFlag(visibility);
3675 }
3676 } else if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08003677 if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
HEO SEUNG22d3ec22019-05-30 20:28:53 +09003678 if (mIsFreeformWindowOverlappingWithNavBar) {
3679 visibility = setNavBarTranslucentFlag(visibility);
3680 } else {
3681 visibility = setNavBarOpaqueFlag(visibility);
3682 }
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003683 } else if (fullscreenDrawsBackground) {
3684 visibility = setNavBarTransparentFlag(visibility);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003685 }
3686 } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
3687 if (isDockedDividerResizing) {
3688 visibility = setNavBarOpaqueFlag(visibility);
3689 } else if (freeformStackVisible) {
3690 visibility = setNavBarTranslucentFlag(visibility);
3691 } else {
3692 visibility = setNavBarOpaqueFlag(visibility);
3693 }
3694 }
3695
Tiger Huang7c610aa2018-10-27 00:01:01 +08003696 return visibility;
3697 }
3698
3699 private int setNavBarOpaqueFlag(int visibility) {
3700 return visibility & ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
3701 }
3702
3703 private int setNavBarTranslucentFlag(int visibility) {
3704 visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
3705 return visibility | View.NAVIGATION_BAR_TRANSLUCENT;
3706 }
3707
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003708 private int setNavBarTransparentFlag(int visibility) {
3709 visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
3710 return visibility | View.NAVIGATION_BAR_TRANSPARENT;
3711 }
3712
Tiger Huang7c610aa2018-10-27 00:01:01 +08003713 private void clearClearableFlagsLw() {
3714 int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
3715 if (newVal != mResettingSystemUiFlags) {
3716 mResettingSystemUiFlags = newVal;
3717 mDisplayContent.reevaluateStatusBarVisibility();
3718 }
3719 }
3720
Tiger Huangdd6db472020-02-13 21:38:46 +08003721 // TODO(b/118118435): Remove this after migration
Tiger Huang7c610aa2018-10-27 00:01:01 +08003722 private boolean isImmersiveMode(int vis) {
3723 final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
3724 return mNavigationBar != null
3725 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
3726 && (vis & flags) != 0
3727 && canHideNavigationBar();
3728 }
3729
Tiger Huangdd6db472020-02-13 21:38:46 +08003730 private boolean isImmersiveMode(WindowState win) {
3731 final int behavior = win.mAttrs.insetsFlags.behavior;
3732 return mNavigationBar != null
3733 && canHideNavigationBar()
3734 && (behavior == BEHAVIOR_SHOW_BARS_BY_SWIPE
3735 || behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE)
3736 && getInsetsPolicy().isHidden(ITYPE_NAVIGATION_BAR)
3737 && win != getNotificationShade();
3738 }
3739
Tiger Huang7c610aa2018-10-27 00:01:01 +08003740 /**
3741 * @return whether the navigation bar can be hidden, e.g. the device has a navigation bar
3742 */
3743 private boolean canHideNavigationBar() {
3744 return hasNavigationBar();
3745 }
3746
3747 private static boolean isNavBarEmpty(int systemUiFlags) {
3748 final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
3749 | View.STATUS_BAR_DISABLE_BACK
3750 | View.STATUS_BAR_DISABLE_RECENT);
3751
3752 return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
3753 }
3754
Tiger Huang7c610aa2018-10-27 00:01:01 +08003755 private final Runnable mHiddenNavPanic = new Runnable() {
3756 @Override
3757 public void run() {
3758 synchronized (mLock) {
3759 if (!mService.mPolicy.isUserSetupComplete()) {
3760 // Swipe-up for navigation bar is disabled during setup
3761 return;
3762 }
3763 mPendingPanicGestureUptime = SystemClock.uptimeMillis();
3764 if (!isNavBarEmpty(mLastSystemUiFlags)) {
3765 mNavigationBarController.showTransient();
Jorim Jaggi956ca412019-01-07 14:49:14 +01003766 mDisplayContent.getInsetsPolicy().showTransient(IntArray.wrap(
Tiger Huang332793b2019-10-29 23:21:27 +08003767 new int[] {ITYPE_NAVIGATION_BAR}));
Tiger Huang7c610aa2018-10-27 00:01:01 +08003768 }
3769 }
3770 }
3771 };
3772
3773 void onPowerKeyDown(boolean isScreenOn) {
3774 // Detect user pressing the power button in panic when an application has
3775 // taken over the whole screen.
3776 boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(isScreenOn,
3777 SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags),
3778 isNavBarEmpty(mLastSystemUiFlags));
3779 if (panic) {
3780 mHandler.post(mHiddenNavPanic);
3781 }
3782 }
3783
3784 void onVrStateChangedLw(boolean enabled) {
3785 mImmersiveModeConfirmation.onVrStateChangedLw(enabled);
3786 }
3787
3788 /**
3789 * Called when the state of lock task mode changes. This should be used to disable immersive
3790 * mode confirmation.
3791 *
3792 * @param lockTaskState the new lock task mode state. One of
3793 * {@link ActivityManager#LOCK_TASK_MODE_NONE},
3794 * {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
3795 * {@link ActivityManager#LOCK_TASK_MODE_PINNED}.
3796 */
3797 public void onLockTaskStateChangedLw(int lockTaskState) {
3798 mImmersiveModeConfirmation.onLockTaskModeChangedLw(lockTaskState);
3799 }
3800
3801 /**
3802 * Request a screenshot be taken.
3803 *
3804 * @param screenshotType The type of screenshot, for example either
3805 * {@link WindowManager#TAKE_SCREENSHOT_FULLSCREEN} or
3806 * {@link WindowManager#TAKE_SCREENSHOT_SELECTED_REGION}
Miranda Kephart7b2c3132020-03-27 09:54:14 -04003807 * @param source Where the screenshot originated from (see WindowManager.ScreenshotSource)
Tiger Huang7c610aa2018-10-27 00:01:01 +08003808 */
Miranda Kephart7b2c3132020-03-27 09:54:14 -04003809 public void takeScreenshot(int screenshotType, int source) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08003810 if (mScreenshotHelper != null) {
3811 mScreenshotHelper.takeScreenshot(screenshotType,
3812 mStatusBar != null && mStatusBar.isVisibleLw(),
James O'Learyfa5bb7a2019-09-05 13:43:29 -04003813 mNavigationBar != null && mNavigationBar.isVisibleLw(),
Miranda Kephart7b2c3132020-03-27 09:54:14 -04003814 source, mHandler, null /* completionConsumer */);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003815 }
3816 }
3817
Ady Abrahamf3e05312019-05-13 18:04:59 -07003818 RefreshRatePolicy getRefreshRatePolicy() {
3819 return mRefreshRatePolicy;
3820 }
3821
Riddle Hsu5ce4bb32018-07-18 16:11:30 +08003822 void dump(String prefix, PrintWriter pw) {
Riddle Hsuccf09402019-08-13 00:33:06 +08003823 pw.print(prefix); pw.println("DisplayPolicy");
Tiger Huang7c610aa2018-10-27 00:01:01 +08003824 prefix += " ";
3825 pw.print(prefix);
3826 pw.print("mCarDockEnablesAccelerometer="); pw.print(mCarDockEnablesAccelerometer);
3827 pw.print(" mDeskDockEnablesAccelerometer=");
3828 pw.println(mDeskDockEnablesAccelerometer);
3829 pw.print(prefix); pw.print("mDockMode="); pw.print(Intent.dockStateToString(mDockMode));
3830 pw.print(" mLidState="); pw.println(WindowManagerFuncs.lidStateToString(mLidState));
3831 pw.print(prefix); pw.print("mAwake="); pw.print(mAwake);
3832 pw.print(" mScreenOnEarly="); pw.print(mScreenOnEarly);
3833 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
3834 pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
3835 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
3836 pw.print(prefix); pw.print("mHdmiPlugged="); pw.println(mHdmiPlugged);
3837 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
3838 || mForceClearedSystemUiFlags != 0) {
3839 pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
3840 pw.print(Integer.toHexString(mLastSystemUiFlags));
3841 pw.print(" mResettingSystemUiFlags=0x");
3842 pw.print(Integer.toHexString(mResettingSystemUiFlags));
3843 pw.print(" mForceClearedSystemUiFlags=0x");
3844 pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
3845 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08003846 pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
3847 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003848 if (mStatusBar != null) {
3849 pw.print(prefix); pw.print("mStatusBar="); pw.print(mStatusBar);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003850 }
wilsonshihe8321942019-10-18 18:39:46 +08003851 if (mNotificationShade != null) {
3852 pw.print(prefix); pw.print("mExpandedPanel="); pw.print(mNotificationShade);
3853 }
3854 pw.print(" isKeyguardShowing="); pw.println(isKeyguardShowing());
Tiger Huang7c610aa2018-10-27 00:01:01 +08003855 if (mNavigationBar != null) {
3856 pw.print(prefix); pw.print("mNavigationBar="); pw.println(mNavigationBar);
Winson Chung4723b4e2019-03-25 16:49:36 -07003857 pw.print(prefix); pw.print("mNavBarOpacityMode="); pw.println(mNavBarOpacityMode);
3858 pw.print(prefix); pw.print("mNavigationBarCanMove="); pw.println(mNavigationBarCanMove);
3859 pw.print(prefix); pw.print("mNavigationBarPosition=");
3860 pw.println(mNavigationBarPosition);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003861 }
3862 if (mFocusedWindow != null) {
3863 pw.print(prefix); pw.print("mFocusedWindow="); pw.println(mFocusedWindow);
3864 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08003865 if (mTopFullscreenOpaqueWindowState != null) {
3866 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
3867 pw.println(mTopFullscreenOpaqueWindowState);
3868 }
3869 if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
3870 pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
3871 pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
3872 }
3873 if (mForcingShowNavBar) {
3874 pw.print(prefix); pw.print("mForcingShowNavBar="); pw.println(mForcingShowNavBar);
3875 pw.print(prefix); pw.print("mForcingShowNavBarLayer=");
3876 pw.println(mForcingShowNavBarLayer);
3877 }
Riddle Hsuccf09402019-08-13 00:33:06 +08003878 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.println(mTopIsFullscreen);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003879 pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
Riddle Hsuccf09402019-08-13 00:33:06 +08003880 pw.print(prefix); pw.print("mForceShowSystemBarsFromExternal=");
3881 pw.print(mForceShowSystemBarsFromExternal);
3882 pw.print(" mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003883 mStatusBarController.dump(pw, prefix);
3884 mNavigationBarController.dump(pw, prefix);
3885
3886 pw.print(prefix); pw.println("Looper state:");
3887 mHandler.getLooper().dump(new PrintWriterPrinter(pw), prefix + " ");
Riddle Hsu5ce4bb32018-07-18 16:11:30 +08003888 }
Arthur Hung20479922019-02-27 17:13:22 +08003889
3890 private boolean supportsPointerLocation() {
3891 return mDisplayContent.isDefaultDisplay || !mDisplayContent.isPrivate();
3892 }
3893
3894 void setPointerLocationEnabled(boolean pointerLocationEnabled) {
3895 if (!supportsPointerLocation()) {
3896 return;
3897 }
3898
3899 mHandler.sendEmptyMessage(pointerLocationEnabled
3900 ? MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
3901 }
3902
3903 private void enablePointerLocation() {
3904 if (mPointerLocationView != null) {
3905 return;
3906 }
3907
3908 mPointerLocationView = new PointerLocationView(mContext);
3909 mPointerLocationView.setPrintCoords(false);
3910 final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
3911 WindowManager.LayoutParams.MATCH_PARENT,
3912 WindowManager.LayoutParams.MATCH_PARENT);
3913 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
Arthur Hungaf7f6a92020-03-16 19:17:47 +08003914 lp.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
Arthur Hung20479922019-02-27 17:13:22 +08003915 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
3916 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
Arthur Hungaf7f6a92020-03-16 19:17:47 +08003917 lp.setFitInsetsTypes(0);
Arthur Hung20479922019-02-27 17:13:22 +08003918 lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
3919 if (ActivityManager.isHighEndGfx()) {
3920 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
3921 lp.privateFlags |=
3922 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
3923 }
3924 lp.format = PixelFormat.TRANSLUCENT;
3925 lp.setTitle("PointerLocation - display " + getDisplayId());
3926 lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
3927 final WindowManager wm = mContext.getSystemService(WindowManager.class);
3928 wm.addView(mPointerLocationView, lp);
3929 mDisplayContent.registerPointerEventListener(mPointerLocationView);
3930 }
3931
3932 private void disablePointerLocation() {
3933 if (mPointerLocationView == null) {
3934 return;
3935 }
3936
3937 mDisplayContent.unregisterPointerEventListener(mPointerLocationView);
3938 final WindowManager wm = mContext.getSystemService(WindowManager.class);
3939 wm.removeView(mPointerLocationView);
3940 mPointerLocationView = null;
3941 }
HEO SEUNG22d3ec22019-05-30 20:28:53 +09003942
Arthur Hungfbc8f412019-08-01 19:57:54 +08003943 /**
3944 * Check if the window could be excluded from checking if the display has content.
3945 *
3946 * @param w WindowState to check if should be excluded.
3947 * @return True if the window type is PointerLocation which is excluded.
3948 */
3949 boolean isWindowExcludedFromContent(WindowState w) {
3950 if (w != null && mPointerLocationView != null) {
3951 return w.mClient == mPointerLocationView.getWindowToken();
3952 }
3953
3954 return false;
3955 }
3956
Mehdi Alizadehf2b28e92019-12-05 20:13:49 -08003957 void release() {
3958 mHandler.post(mGestureNavigationSettingsObserver::unregister);
3959 }
3960
HEO SEUNG22d3ec22019-05-30 20:28:53 +09003961 @VisibleForTesting
3962 static boolean isOverlappingWithNavBar(WindowState targetWindow, WindowState navBarWindow) {
3963 if (navBarWindow == null || !navBarWindow.isVisibleLw()
Garfield Tane8d84ab2019-10-11 09:49:40 -07003964 || targetWindow.mActivityRecord == null || !targetWindow.isVisibleLw()) {
HEO SEUNG22d3ec22019-05-30 20:28:53 +09003965 return false;
3966 }
3967
3968 return Rect.intersects(targetWindow.getFrameLw(), navBarWindow.getFrameLw());
3969 }
Riddle Hsu5ce4bb32018-07-18 16:11:30 +08003970}