blob: 8d5f90d53019b2a37ddefb5a057f66491d1804f8 [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;
Tiger Huang43b8fc22019-04-26 11:49:29 +080027import static android.view.Display.TYPE_BUILT_IN;
Tiger Huang332793b2019-10-29 23:21:27 +080028import static android.view.InsetsState.ITYPE_BOTTOM_GESTURES;
29import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
30import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
31import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
32import static android.view.InsetsState.ITYPE_RIGHT_GESTURES;
33import static android.view.InsetsState.ITYPE_STATUS_BAR;
34import static android.view.InsetsState.ITYPE_TOP_GESTURES;
35import static android.view.InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT;
Jorim Jaggid6490572019-04-16 14:57:56 +020036import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
Tiger Huang7c610aa2018-10-27 00:01:01 +080037import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
Jorim Jaggi956ca412019-01-07 14:49:14 +010038import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
Jorim Jaggi648e5882019-01-24 13:24:02 +010039import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
Tiger Huang332793b2019-10-29 23:21:27 +080040import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
Jorim Jaggi956ca412019-01-07 14:49:14 +010041import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE;
42import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
Tiger Huang7c610aa2018-10-27 00:01:01 +080043import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
44import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
45import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
46import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
47import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
48import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
49import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
50import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR;
51import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
52import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN;
53import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
54import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
Adrian Roos11dfd272019-03-25 19:21:26 +010055import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
Tiger Huang7c610aa2018-10-27 00:01:01 +080056import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
57import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
58import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
59import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
Tiger Huang7c610aa2018-10-27 00:01:01 +080060import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
Arthur Hung20479922019-02-27 17:13:22 +080061import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
Jorim Jaggia6aabac2019-03-11 14:23:16 -070062import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
Tiger Huang7c610aa2018-10-27 00:01:01 +080063import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
Tiger Huang7c610aa2018-10-27 00:01:01 +080064import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
65import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
66import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
Tiger Huang7c610aa2018-10-27 00:01:01 +080067import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
68import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
69import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
70import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
71import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
72import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
73import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
74import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
75import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
Charles Chen64172bb2019-04-22 17:30:29 +080076import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
Tiger Huang7c610aa2018-10-27 00:01:01 +080077import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
78import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
79import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
80import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
81import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
82import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
83import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
84import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
85import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
86import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
87import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
88import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
89import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING;
90import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
91import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
92import static android.view.WindowManagerGlobal.ADD_OKAY;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +080093import static android.view.WindowManagerPolicyConstants.ACTION_HDMI_PLUGGED;
94import static android.view.WindowManagerPolicyConstants.EXTRA_HDMI_PLUGGED_STATE;
Tiger Huang7c610aa2018-10-27 00:01:01 +080095import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
96import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
97import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;
98
99import static com.android.server.policy.PhoneWindowManager.TOAST_WINDOW_TIMEOUT;
100import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
101import static com.android.server.policy.WindowManagerPolicy.TRANSIT_ENTER;
102import static com.android.server.policy.WindowManagerPolicy.TRANSIT_EXIT;
103import static com.android.server.policy.WindowManagerPolicy.TRANSIT_HIDE;
104import static com.android.server.policy.WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
105import static com.android.server.policy.WindowManagerPolicy.TRANSIT_SHOW;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800106import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800107import static com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200108import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800109import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
110import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800111import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
112import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
113
Jorim Jaggi4981f152019-03-26 18:58:45 +0100114import android.Manifest.permission;
Issei Suzukia5dbf522019-02-01 17:58:15 +0100115import android.annotation.NonNull;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800116import android.annotation.Nullable;
Jorim Jaggi4981f152019-03-26 18:58:45 +0100117import android.annotation.Px;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800118import android.app.ActivityManager;
119import android.app.ActivityThread;
Winson Chungda20fec2019-04-10 12:19:59 -0700120import android.app.LoadedApk;
121import android.app.ResourcesManager;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800122import android.app.StatusBarManager;
123import android.content.Context;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800124import android.content.Intent;
Jorim Jaggi4981f152019-03-26 18:58:45 +0100125import android.content.pm.PackageManager;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800126import android.content.res.Resources;
Issei Suzukia5dbf522019-02-01 17:58:15 +0100127import android.graphics.Insets;
Arthur Hung20479922019-02-27 17:13:22 +0800128import android.graphics.PixelFormat;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800129import android.graphics.Rect;
Winson Chung36941632019-04-19 15:21:38 -0700130import android.graphics.Region;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800131import android.hardware.input.InputManager;
132import android.hardware.power.V1_0.PowerHint;
133import android.os.Handler;
134import android.os.Looper;
135import android.os.Message;
136import android.os.SystemClock;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800137import android.os.SystemProperties;
138import android.os.UserHandle;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800139import android.util.ArraySet;
Jorim Jaggi956ca412019-01-07 14:49:14 +0100140import android.util.IntArray;
Tarandeep Singhe439dec2019-04-22 12:28:43 -0700141import android.util.Pair;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800142import android.util.PrintWriterPrinter;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800143import android.util.Slog;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800144import android.view.DisplayCutout;
145import android.view.Gravity;
146import android.view.IApplicationToken;
147import android.view.InputChannel;
148import android.view.InputDevice;
149import android.view.InputEvent;
150import android.view.InputEventReceiver;
Tiger Huang0dbd5372019-10-26 00:24:22 +0800151import android.view.InsetsFlags;
Tiger Huang332793b2019-10-29 23:21:27 +0800152import android.view.InsetsState.InternalInsetsType;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800153import android.view.MotionEvent;
154import android.view.PointerIcon;
155import android.view.Surface;
156import android.view.View;
Jorim Jaggi648e5882019-01-24 13:24:02 +0100157import android.view.ViewRootImpl;
Jorim Jaggi956ca412019-01-07 14:49:14 +0100158import android.view.WindowInsets;
Tiger Huang0dbd5372019-10-26 00:24:22 +0800159import android.view.WindowInsetsController.Appearance;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800160import android.view.WindowManager;
161import android.view.WindowManager.LayoutParams;
162import android.view.WindowManagerGlobal;
163import android.view.WindowManagerPolicyConstants;
164import android.view.accessibility.AccessibilityManager;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800165
Tiger Huang7c610aa2018-10-27 00:01:01 +0800166import com.android.internal.R;
167import com.android.internal.annotations.GuardedBy;
168import com.android.internal.annotations.VisibleForTesting;
Tiger Huang43b8fc22019-04-26 11:49:29 +0800169import com.android.internal.policy.ScreenDecorationsUtils;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800170import com.android.internal.util.ScreenshotHelper;
Adrian Roos11dfd272019-03-25 19:21:26 +0100171import com.android.internal.util.function.TriConsumer;
Jorim Jaggi956ca412019-01-07 14:49:14 +0100172import com.android.internal.view.AppearanceRegion;
Arthur Hung20479922019-02-27 17:13:22 +0800173import com.android.internal.widget.PointerLocationView;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800174import com.android.server.LocalServices;
175import com.android.server.UiThread;
176import com.android.server.policy.WindowManagerPolicy;
177import com.android.server.policy.WindowManagerPolicy.InputConsumer;
178import com.android.server.policy.WindowManagerPolicy.NavigationBarPosition;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800179import com.android.server.policy.WindowManagerPolicy.ScreenOnListener;
180import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800181import com.android.server.policy.WindowOrientationListener;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200182import com.android.server.protolog.common.ProtoLog;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800183import com.android.server.statusbar.StatusBarManagerInternal;
wilsonshih643bf132019-02-27 12:49:19 +0800184import com.android.server.wallpaper.WallpaperManagerInternal;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800185import com.android.server.wm.utils.InsetUtils;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800186
187import java.io.PrintWriter;
188
189/**
190 * The policy that provides the basic behaviors and states of a display to show UI.
191 */
192public class DisplayPolicy {
193 private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayPolicy" : TAG_WM;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800194 private static final boolean DEBUG = false;
195
196 private static final boolean ALTERNATE_CAR_MODE_NAV_SIZE = false;
197
198 // The panic gesture may become active only after the keyguard is dismissed and the immersive
199 // app shows again. If that doesn't happen for 30s we drop the gesture.
200 private static final long PANIC_GESTURE_EXPIRATION = 30000;
201
202 // Controls navigation bar opacity depending on which workspace stacks are currently
203 // visible.
204 // Nav bar is always opaque when either the freeform stack or docked stack is visible.
205 private static final int NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED = 0;
206 // Nav bar is always translucent when the freeform stack is visible, otherwise always opaque.
207 private static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1;
Adrian Roosfaba4062019-05-14 15:27:17 +0200208 // Nav bar is never forced opaque.
209 private static final int NAV_BAR_FORCE_TRANSPARENT = 2;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800210
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800211 /** Don't apply window animation (see {@link #selectAnimation}). */
212 static final int ANIMATION_NONE = -1;
213 /** Use the transit animation in style resource (see {@link #selectAnimation}). */
214 static final int ANIMATION_STYLEABLE = 0;
215
Tiger Huang7c610aa2018-10-27 00:01:01 +0800216 /**
217 * These are the system UI flags that, when changing, can cause the layout
218 * of the screen to change.
219 */
220 private static final int SYSTEM_UI_CHANGING_LAYOUT =
221 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
222 | View.SYSTEM_UI_FLAG_FULLSCREEN
223 | View.STATUS_BAR_TRANSLUCENT
224 | View.NAVIGATION_BAR_TRANSLUCENT
225 | View.STATUS_BAR_TRANSPARENT
226 | View.NAVIGATION_BAR_TRANSPARENT;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800227
228 private final WindowManagerService mService;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800229 private final Context mContext;
230 private final DisplayContent mDisplayContent;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800231 private final Object mLock;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800232 private final Handler mHandler;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800233
Winson Chungda20fec2019-04-10 12:19:59 -0700234 private Resources mCurrentUserResources;
235
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800236 private final boolean mCarDockEnablesAccelerometer;
237 private final boolean mDeskDockEnablesAccelerometer;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800238 private final AccessibilityManager mAccessibilityManager;
239 private final ImmersiveModeConfirmation mImmersiveModeConfirmation;
240 private final ScreenshotHelper mScreenshotHelper;
241
242 private final Object mServiceAcquireLock = new Object();
243 private StatusBarManagerInternal mStatusBarManagerInternal;
244
Adrian Roos11dfd272019-03-25 19:21:26 +0100245 @Px
246 private int mBottomGestureAdditionalInset;
247 @Px
248 private int mSideGestureInset;
Adrian Roos11dfd272019-03-25 19:21:26 +0100249
Jorim Jaggi956ca412019-01-07 14:49:14 +0100250 StatusBarManagerInternal getStatusBarManagerInternal() {
Tiger Huang7c610aa2018-10-27 00:01:01 +0800251 synchronized (mServiceAcquireLock) {
252 if (mStatusBarManagerInternal == null) {
253 mStatusBarManagerInternal =
254 LocalServices.getService(StatusBarManagerInternal.class);
255 }
256 return mStatusBarManagerInternal;
257 }
258 }
259
Tiger Huang7c610aa2018-10-27 00:01:01 +0800260 private final SystemGesturesPointerEventListener mSystemGestures;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800261
262 private volatile int mLidState = LID_ABSENT;
263 private volatile int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
264 private volatile boolean mHdmiPlugged;
265
Louis Changfc64c832018-12-04 11:38:26 +0800266 private volatile boolean mHasStatusBar;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800267 private volatile boolean mHasNavigationBar;
268 // Can the navigation bar ever move to the side?
269 private volatile boolean mNavigationBarCanMove;
Winson Chung36941632019-04-19 15:21:38 -0700270 private volatile boolean mNavigationBarLetsThroughTaps;
271 private volatile boolean mNavigationBarAlwaysShowOnSideGesture;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800272
273 // Written by vr manager thread, only read in this class.
274 private volatile boolean mPersistentVrModeEnabled;
275
276 private volatile boolean mAwake;
277 private volatile boolean mScreenOnEarly;
278 private volatile boolean mScreenOnFully;
279 private volatile ScreenOnListener mScreenOnListener;
280
281 private volatile boolean mKeyguardDrawComplete;
282 private volatile boolean mWindowManagerDrawComplete;
283
Tiger Huang7c610aa2018-10-27 00:01:01 +0800284 private final ArraySet<WindowState> mScreenDecorWindows = new ArraySet<>();
285 private WindowState mStatusBar = null;
286 private final int[] mStatusBarHeightForRotation = new int[4];
287 private WindowState mNavigationBar = null;
288 @NavigationBarPosition
289 private int mNavigationBarPosition = NAV_BAR_BOTTOM;
290 private int[] mNavigationBarHeightForRotationDefault = new int[4];
291 private int[] mNavigationBarWidthForRotationDefault = new int[4];
292 private int[] mNavigationBarHeightForRotationInCarMode = new int[4];
293 private int[] mNavigationBarWidthForRotationInCarMode = new int[4];
294
Matthew Nga7f24bc2019-04-09 17:06:41 -0700295 /** See {@link #getNavigationBarFrameHeight} */
296 private int[] mNavigationBarFrameHeightForRotationDefault = new int[4];
297
HEO SEUNG22d3ec22019-05-30 20:28:53 +0900298 private boolean mIsFreeformWindowOverlappingWithNavBar;
299
Riddle Hsud80ae9b2019-03-26 00:40:35 +0800300 private final StatusBarController mStatusBarController;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800301
Riddle Hsud80ae9b2019-03-26 00:40:35 +0800302 private final BarController mNavigationBarController;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800303
304 private final BarController.OnBarVisibilityChangedListener mNavBarVisibilityListener =
305 new BarController.OnBarVisibilityChangedListener() {
306 @Override
307 public void onBarVisibilityChanged(boolean visible) {
308 if (mAccessibilityManager == null) {
309 return;
310 }
311 mAccessibilityManager.notifyAccessibilityButtonVisibilityChanged(visible);
312 }
313 };
314
Tiger Huang7c610aa2018-10-27 00:01:01 +0800315 @GuardedBy("mHandler")
316 private SleepToken mDreamingSleepToken;
317
318 @GuardedBy("mHandler")
319 private SleepToken mWindowSleepToken;
320
321 private final Runnable mAcquireSleepTokenRunnable;
322 private final Runnable mReleaseSleepTokenRunnable;
323
324 // The windows we were told about in focusChanged.
325 private WindowState mFocusedWindow;
326 private WindowState mLastFocusedWindow;
327
328 IApplicationToken mFocusedApp;
329
330 int mLastSystemUiFlags;
331 // Bits that we are in the process of clearing, so we want to prevent
332 // them from being set by applications until everything has been updated
333 // to have them clear.
334 private int mResettingSystemUiFlags = 0;
335 // Bits that we are currently always keeping cleared.
336 private int mForceClearedSystemUiFlags = 0;
Jorim Jaggi956ca412019-01-07 14:49:14 +0100337 private int mLastAppearance;
338 private int mLastFullscreenAppearance;
339 private int mLastDockedAppearance;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800340 private final Rect mNonDockedStackBounds = new Rect();
341 private final Rect mDockedStackBounds = new Rect();
342 private final Rect mLastNonDockedStackBounds = new Rect();
343 private final Rect mLastDockedStackBounds = new Rect();
344
Jorim Jaggi956ca412019-01-07 14:49:14 +0100345 // What we last reported to system UI about whether the focused window is fullscreen/immersive.
346 private boolean mLastFocusIsFullscreen = false;
347 private boolean mLastFocusIsImmersive = false;
348
Tiger Huang7c610aa2018-10-27 00:01:01 +0800349 // If nonzero, a panic gesture was performed at that time in uptime millis and is still pending.
350 private long mPendingPanicGestureUptime;
351
352 private static final Rect sTmpDisplayCutoutSafeExceptMaybeBarsRect = new Rect();
353 private static final Rect sTmpRect = new Rect();
Tiger Huang7c610aa2018-10-27 00:01:01 +0800354 private static final Rect sTmpNavFrame = new Rect();
355 private static final Rect sTmpLastParentFrame = new Rect();
356
357 private WindowState mTopFullscreenOpaqueWindowState;
358 private WindowState mTopFullscreenOpaqueOrDimmingWindowState;
359 private WindowState mTopDockedOpaqueWindowState;
360 private WindowState mTopDockedOpaqueOrDimmingWindowState;
361 private boolean mTopIsFullscreen;
362 private boolean mForceStatusBar;
363 private boolean mForceStatusBarFromKeyguard;
364 private boolean mForceStatusBarTransparent;
365 private int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
366 private boolean mForcingShowNavBar;
367 private int mForcingShowNavBarLayer;
368 private boolean mForceShowSystemBars;
369
Brad Stenninge0573692019-03-11 13:52:46 -0700370 /**
371 * Force the display of system bars regardless of other settings.
372 */
373 private boolean mForceShowSystemBarsFromExternal;
374
Tiger Huang7c610aa2018-10-27 00:01:01 +0800375 private boolean mShowingDream;
376 private boolean mLastShowingDream;
377 private boolean mDreamingLockscreen;
378 private boolean mDreamingSleepTokenNeeded;
379 private boolean mWindowSleepTokenNeeded;
380 private boolean mLastWindowSleepTokenNeeded;
381 private boolean mAllowLockscreenWhenOn;
382
383 private InputConsumer mInputConsumer = null;
384
Arthur Hung20479922019-02-27 17:13:22 +0800385 private PointerLocationView mPointerLocationView;
386
Issei Suzukia5dbf522019-02-01 17:58:15 +0100387 /**
388 * The area covered by system windows which belong to another display. Forwarded insets is set
389 * in case this is a virtual display, this is displayed on another display that has insets, and
390 * the bounds of this display is overlapping with the insets of the host display (e.g. IME is
391 * displayed on the host display, and it covers a part of this virtual display.)
392 * The forwarded insets is used to compute display frames of this virtual display, which will
393 * be then used to layout windows in the virtual display.
394 */
395 @NonNull private Insets mForwardedInsets = Insets.NONE;
396
Ady Abrahamf3e05312019-05-13 18:04:59 -0700397 private RefreshRatePolicy mRefreshRatePolicy;
398
Tiger Huang7c610aa2018-10-27 00:01:01 +0800399 // -------- PolicyHandler --------
400 private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 1;
401 private static final int MSG_REQUEST_TRANSIENT_BARS = 2;
402 private static final int MSG_DISPOSE_INPUT_CONSUMER = 3;
Arthur Hung20479922019-02-27 17:13:22 +0800403 private static final int MSG_ENABLE_POINTER_LOCATION = 4;
404 private static final int MSG_DISABLE_POINTER_LOCATION = 5;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800405
406 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
407 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
408
409 private class PolicyHandler extends Handler {
410
411 PolicyHandler(Looper looper) {
412 super(looper);
413 }
414
415 @Override
416 public void handleMessage(Message msg) {
417 switch (msg.what) {
418 case MSG_UPDATE_DREAMING_SLEEP_TOKEN:
419 updateDreamingSleepToken(msg.arg1 != 0);
420 break;
421 case MSG_REQUEST_TRANSIENT_BARS:
422 WindowState targetBar = (msg.arg1 == MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS)
423 ? mStatusBar : mNavigationBar;
424 if (targetBar != null) {
425 requestTransientBars(targetBar);
426 }
427 break;
428 case MSG_DISPOSE_INPUT_CONSUMER:
429 disposeInputConsumer((InputConsumer) msg.obj);
430 break;
Arthur Hung20479922019-02-27 17:13:22 +0800431 case MSG_ENABLE_POINTER_LOCATION:
432 enablePointerLocation();
433 break;
434 case MSG_DISABLE_POINTER_LOCATION:
435 disablePointerLocation();
436 break;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800437 }
438 }
439 }
440
441 DisplayPolicy(WindowManagerService service, DisplayContent displayContent) {
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800442 mService = service;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800443 mContext = displayContent.isDefaultDisplay ? service.mContext
444 : service.mContext.createDisplayContext(displayContent.getDisplay());
445 mDisplayContent = displayContent;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800446 mLock = service.getWindowManagerLock();
Tiger Huang7c610aa2018-10-27 00:01:01 +0800447
Riddle Hsud80ae9b2019-03-26 00:40:35 +0800448 final int displayId = displayContent.getDisplayId();
449 mStatusBarController = new StatusBarController(displayId);
450 mNavigationBarController = new BarController("NavigationBar",
451 displayId,
452 View.NAVIGATION_BAR_TRANSIENT,
453 View.NAVIGATION_BAR_UNHIDE,
454 View.NAVIGATION_BAR_TRANSLUCENT,
455 StatusBarManager.WINDOW_NAVIGATION_BAR,
456 FLAG_TRANSLUCENT_NAVIGATION,
457 View.NAVIGATION_BAR_TRANSPARENT);
458
Tiger Huang7c610aa2018-10-27 00:01:01 +0800459 final Resources r = mContext.getResources();
460 mCarDockEnablesAccelerometer = r.getBoolean(R.bool.config_carDockEnablesAccelerometer);
461 mDeskDockEnablesAccelerometer = r.getBoolean(R.bool.config_deskDockEnablesAccelerometer);
Brad Stenninge0573692019-03-11 13:52:46 -0700462 mForceShowSystemBarsFromExternal = r.getBoolean(R.bool.config_forceShowSystemBars);
Tiger Huang7c610aa2018-10-27 00:01:01 +0800463
464 mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(
465 Context.ACCESSIBILITY_SERVICE);
466 if (!displayContent.isDefaultDisplay) {
467 mAwake = true;
468 mScreenOnEarly = true;
469 mScreenOnFully = true;
470 }
471
472 final Looper looper = UiThread.getHandler().getLooper();
473 mHandler = new PolicyHandler(looper);
474 mSystemGestures = new SystemGesturesPointerEventListener(mContext, mHandler,
475 new SystemGesturesPointerEventListener.Callbacks() {
476 @Override
477 public void onSwipeFromTop() {
478 if (mStatusBar != null) {
479 requestTransientBars(mStatusBar);
480 }
481 }
482
483 @Override
484 public void onSwipeFromBottom() {
Winson Chung36941632019-04-19 15:21:38 -0700485 if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_BOTTOM) {
Tiger Huang7c610aa2018-10-27 00:01:01 +0800486 requestTransientBars(mNavigationBar);
487 }
488 }
489
490 @Override
491 public void onSwipeFromRight() {
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200492 final Region excludedRegion = Region.obtain();
Jeff Chang3cf3e562019-06-18 11:51:25 +0800493 synchronized (mLock) {
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200494 mDisplayContent.calculateSystemGestureExclusion(
495 excludedRegion, null /* outUnrestricted */);
Jeff Chang3cf3e562019-06-18 11:51:25 +0800496 }
Winson Chung36941632019-04-19 15:21:38 -0700497 final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
498 || mNavigationBarPosition == NAV_BAR_RIGHT;
499 if (mNavigationBar != null && sideAllowed
500 && !mSystemGestures.currentGestureStartedInRegion(excludedRegion)) {
Tiger Huang7c610aa2018-10-27 00:01:01 +0800501 requestTransientBars(mNavigationBar);
502 }
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200503 excludedRegion.recycle();
Tiger Huang7c610aa2018-10-27 00:01:01 +0800504 }
505
506 @Override
507 public void onSwipeFromLeft() {
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200508 final Region excludedRegion = Region.obtain();
Jeff Chang3cf3e562019-06-18 11:51:25 +0800509 synchronized (mLock) {
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200510 mDisplayContent.calculateSystemGestureExclusion(
511 excludedRegion, null /* outUnrestricted */);
Jeff Chang3cf3e562019-06-18 11:51:25 +0800512 }
Winson Chung36941632019-04-19 15:21:38 -0700513 final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
514 || mNavigationBarPosition == NAV_BAR_LEFT;
515 if (mNavigationBar != null && sideAllowed
516 && !mSystemGestures.currentGestureStartedInRegion(excludedRegion)) {
Tiger Huang7c610aa2018-10-27 00:01:01 +0800517 requestTransientBars(mNavigationBar);
518 }
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200519 excludedRegion.recycle();
Tiger Huang7c610aa2018-10-27 00:01:01 +0800520 }
521
522 @Override
523 public void onFling(int duration) {
524 if (mService.mPowerManagerInternal != null) {
525 mService.mPowerManagerInternal.powerHint(
526 PowerHint.INTERACTION, duration);
527 }
528 }
529
530 @Override
531 public void onDebug() {
532 // no-op
533 }
534
535 private WindowOrientationListener getOrientationListener() {
536 final DisplayRotation rotation = mDisplayContent.getDisplayRotation();
537 return rotation != null ? rotation.getOrientationListener() : null;
538 }
539
540 @Override
541 public void onDown() {
542 final WindowOrientationListener listener = getOrientationListener();
543 if (listener != null) {
544 listener.onTouchStart();
545 }
546 }
547
548 @Override
549 public void onUpOrCancel() {
550 final WindowOrientationListener listener = getOrientationListener();
551 if (listener != null) {
552 listener.onTouchEnd();
553 }
554 }
555
556 @Override
557 public void onMouseHoverAtTop() {
558 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
559 Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
560 msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
561 mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
562 }
563
564 @Override
565 public void onMouseHoverAtBottom() {
566 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
567 Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
568 msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
569 mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
570 }
571
572 @Override
573 public void onMouseLeaveFromEdge() {
574 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
575 }
576 });
577 displayContent.registerPointerEventListener(mSystemGestures);
578 displayContent.mAppTransition.registerListenerLocked(
579 mStatusBarController.getAppTransitionListener());
580 mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext, looper,
581 mService.mVrModeEnabled);
582 mAcquireSleepTokenRunnable = () -> {
583 if (mWindowSleepToken != null) {
584 return;
585 }
Tiger Huang7c610aa2018-10-27 00:01:01 +0800586 mWindowSleepToken = service.mAtmInternal.acquireSleepToken(
587 "WindowSleepTokenOnDisplay" + displayId, displayId);
588 };
589 mReleaseSleepTokenRunnable = () -> {
590 if (mWindowSleepToken == null) {
591 return;
592 }
593 mWindowSleepToken.release();
594 mWindowSleepToken = null;
595 };
596
597 // TODO: Make it can take screenshot on external display
598 mScreenshotHelper = displayContent.isDefaultDisplay
599 ? new ScreenshotHelper(mContext) : null;
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800600
Tiger Huang7c610aa2018-10-27 00:01:01 +0800601 if (mDisplayContent.isDefaultDisplay) {
Louis Changfc64c832018-12-04 11:38:26 +0800602 mHasStatusBar = true;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800603 mHasNavigationBar = mContext.getResources().getBoolean(R.bool.config_showNavigationBar);
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800604
Tiger Huang7c610aa2018-10-27 00:01:01 +0800605 // Allow a system property to override this. Used by the emulator.
606 // See also hasNavigationBar().
607 String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
608 if ("1".equals(navBarOverride)) {
609 mHasNavigationBar = false;
610 } else if ("0".equals(navBarOverride)) {
611 mHasNavigationBar = true;
612 }
613 } else {
Louis Changfc64c832018-12-04 11:38:26 +0800614 mHasStatusBar = false;
Andrii Kuliandd989612019-02-21 12:13:28 -0800615 mHasNavigationBar = mDisplayContent.supportsSystemDecorations();
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800616 }
Ady Abrahamf3e05312019-05-13 18:04:59 -0700617
618 mRefreshRatePolicy = new RefreshRatePolicy(mService,
619 mDisplayContent.getDisplayInfo(),
620 mService.mHighRefreshRateBlacklist);
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800621 }
622
Charles Chen5bdd3e22018-12-18 17:51:56 +0800623 void systemReady() {
624 mSystemGestures.systemReady();
Arthur Hung20479922019-02-27 17:13:22 +0800625 if (mService.mPointerLocationEnabled) {
626 setPointerLocationEnabled(true);
627 }
Charles Chen5bdd3e22018-12-18 17:51:56 +0800628 }
629
630 private int getDisplayId() {
631 return mDisplayContent.getDisplayId();
632 }
633
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800634 public void setHdmiPlugged(boolean plugged) {
635 setHdmiPlugged(plugged, false /* force */);
636 }
637
638 public void setHdmiPlugged(boolean plugged, boolean force) {
639 if (force || mHdmiPlugged != plugged) {
640 mHdmiPlugged = plugged;
641 mService.updateRotation(true /* alwaysSendConfiguration */, true /* forceRelayout */);
642 final Intent intent = new Intent(ACTION_HDMI_PLUGGED);
643 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
644 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
Tiger Huang7c610aa2018-10-27 00:01:01 +0800645 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800646 }
647 }
648
649 boolean isHdmiPlugged() {
650 return mHdmiPlugged;
651 }
652
653 boolean isCarDockEnablesAccelerometer() {
654 return mCarDockEnablesAccelerometer;
655 }
656
657 boolean isDeskDockEnablesAccelerometer() {
658 return mDeskDockEnablesAccelerometer;
659 }
660
661 public void setPersistentVrModeEnabled(boolean persistentVrModeEnabled) {
662 mPersistentVrModeEnabled = persistentVrModeEnabled;
663 }
664
665 public boolean isPersistentVrModeEnabled() {
666 return mPersistentVrModeEnabled;
667 }
668
669 public void setDockMode(int dockMode) {
670 mDockMode = dockMode;
671 }
672
673 public int getDockMode() {
674 return mDockMode;
675 }
676
Brad Stenninge0573692019-03-11 13:52:46 -0700677 /**
678 * @see WindowManagerService.setForceShowSystemBars
679 */
680 void setForceShowSystemBars(boolean forceShowSystemBars) {
681 mForceShowSystemBarsFromExternal = forceShowSystemBars;
682 }
683
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800684 public boolean hasNavigationBar() {
685 return mHasNavigationBar;
686 }
687
Louis Changfc64c832018-12-04 11:38:26 +0800688 public boolean hasStatusBar() {
689 return mHasStatusBar;
690 }
691
Adrian Roos5f2c9a12019-07-03 18:31:46 +0200692 boolean hasSideGestures() {
693 return mHasNavigationBar && mSideGestureInset > 0;
694 }
695
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800696 public boolean navigationBarCanMove() {
697 return mNavigationBarCanMove;
698 }
699
700 public void setLidState(int lidState) {
701 mLidState = lidState;
702 }
703
704 public int getLidState() {
705 return mLidState;
706 }
707
708 public void setAwake(boolean awake) {
709 mAwake = awake;
710 }
711
712 public boolean isAwake() {
713 return mAwake;
714 }
715
716 public boolean isScreenOnEarly() {
717 return mScreenOnEarly;
718 }
719
720 public boolean isScreenOnFully() {
721 return mScreenOnFully;
722 }
723
724 public boolean isKeyguardDrawComplete() {
725 return mKeyguardDrawComplete;
726 }
727
728 public boolean isWindowManagerDrawComplete() {
729 return mWindowManagerDrawComplete;
730 }
731
732 public ScreenOnListener getScreenOnListener() {
733 return mScreenOnListener;
734 }
735
736 public void screenTurnedOn(ScreenOnListener screenOnListener) {
737 synchronized (mLock) {
738 mScreenOnEarly = true;
739 mScreenOnFully = false;
740 mKeyguardDrawComplete = false;
741 mWindowManagerDrawComplete = false;
742 mScreenOnListener = screenOnListener;
743 }
744 }
745
746 public void screenTurnedOff() {
747 synchronized (mLock) {
748 mScreenOnEarly = false;
749 mScreenOnFully = false;
750 mKeyguardDrawComplete = false;
751 mWindowManagerDrawComplete = false;
752 mScreenOnListener = null;
753 }
754 }
755
756 /** Return false if we are not awake yet or we have already informed of this event. */
757 public boolean finishKeyguardDrawn() {
758 synchronized (mLock) {
759 if (!mScreenOnEarly || mKeyguardDrawComplete) {
760 return false;
761 }
762
763 mKeyguardDrawComplete = true;
764 mWindowManagerDrawComplete = false;
765 }
766 return true;
767 }
768
769 /** Return false if screen is not turned on or we did already handle this case earlier. */
770 public boolean finishWindowsDrawn() {
771 synchronized (mLock) {
772 if (!mScreenOnEarly || mWindowManagerDrawComplete) {
773 return false;
774 }
775
776 mWindowManagerDrawComplete = true;
777 }
778 return true;
779 }
780
781 /** Return false if it is not ready to turn on. */
782 public boolean finishScreenTurningOn() {
783 synchronized (mLock) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200784 ProtoLog.d(WM_DEBUG_SCREEN_ON,
785 "finishScreenTurningOn: mAwake=%b, mScreenOnEarly=%b, "
786 + "mScreenOnFully=%b, mKeyguardDrawComplete=%b, "
787 + "mWindowManagerDrawComplete=%b",
788 mAwake, mScreenOnEarly, mScreenOnFully, mKeyguardDrawComplete,
789 mWindowManagerDrawComplete);
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800790
791 if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
792 || (mAwake && !mKeyguardDrawComplete)) {
793 return false;
794 }
795
Adrian Roosb125e0b2019-10-02 14:55:14 +0200796 ProtoLog.i(WM_DEBUG_SCREEN_ON, "Finished screen turning on...");
Riddle Hsu5ce4bb32018-07-18 16:11:30 +0800797 mScreenOnListener = null;
798 mScreenOnFully = true;
799 }
800 return true;
801 }
802
Jorim Jaggi4981f152019-03-26 18:58:45 +0100803 private boolean hasStatusBarServicePermission(int pid, int uid) {
804 return mContext.checkPermission(permission.STATUS_BAR_SERVICE, pid, uid)
805 == PackageManager.PERMISSION_GRANTED;
806 }
807
Tiger Huang7c610aa2018-10-27 00:01:01 +0800808 /**
809 * Sanitize the layout parameters coming from a client. Allows the policy
810 * to do things like ensure that windows of a specific type can't take
811 * input focus.
812 *
813 * @param attrs The window layout parameters to be modified. These values
814 * are modified in-place.
815 */
816 public void adjustWindowParamsLw(WindowState win, WindowManager.LayoutParams attrs,
Jorim Jaggi4981f152019-03-26 18:58:45 +0100817 int callingPid, int callingUid) {
Tiger Huang7c610aa2018-10-27 00:01:01 +0800818
819 final boolean isScreenDecor = (attrs.privateFlags & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0;
820 if (mScreenDecorWindows.contains(win)) {
821 if (!isScreenDecor) {
822 // No longer has the flag set, so remove from the set.
823 mScreenDecorWindows.remove(win);
824 }
Jorim Jaggi4981f152019-03-26 18:58:45 +0100825 } else if (isScreenDecor && hasStatusBarServicePermission(callingPid, callingUid)) {
Tiger Huang7c610aa2018-10-27 00:01:01 +0800826 mScreenDecorWindows.add(win);
827 }
828
829 switch (attrs.type) {
830 case TYPE_SYSTEM_OVERLAY:
831 case TYPE_SECURE_SYSTEM_OVERLAY:
832 // These types of windows can't receive input events.
833 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
834 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
835 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
836 break;
837 case TYPE_DREAM:
838 case TYPE_WALLPAPER:
839 // Dreams and wallpapers don't have an app window token and can thus not be
840 // letterboxed. Hence always let them extend under the cutout.
Arthur Hung20479922019-02-27 17:13:22 +0800841 attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800842 break;
843 case TYPE_STATUS_BAR:
844
845 // If the Keyguard is in a hidden state (occluded by another window), we force to
846 // remove the wallpaper and keyguard flag so that any change in-flight after setting
847 // the keyguard as occluded wouldn't set these flags again.
848 // See {@link #processKeyguardSetHiddenResultLw}.
849 if (mService.mPolicy.isKeyguardOccluded()) {
850 attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
851 attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
852 }
853 break;
854
855 case TYPE_SCREENSHOT:
856 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
857 break;
858
859 case TYPE_TOAST:
860 // While apps should use the dedicated toast APIs to add such windows
861 // it possible legacy apps to add the window directly. Therefore, we
862 // make windows added directly by the app behave as a toast as much
863 // as possible in terms of timeout and animation.
864 if (attrs.hideTimeoutMilliseconds < 0
865 || attrs.hideTimeoutMilliseconds > TOAST_WINDOW_TIMEOUT) {
866 attrs.hideTimeoutMilliseconds = TOAST_WINDOW_TIMEOUT;
867 }
Rhed Jao406d3a22018-11-30 19:28:58 +0800868 // Accessibility users may need longer timeout duration. This api compares
869 // original timeout with user's preference and return longer one. It returns
870 // original timeout if there's no preference.
871 attrs.hideTimeoutMilliseconds = mAccessibilityManager.getRecommendedTimeoutMillis(
872 (int) attrs.hideTimeoutMilliseconds,
873 AccessibilityManager.FLAG_CONTENT_TEXT);
Tiger Huang7c610aa2018-10-27 00:01:01 +0800874 attrs.windowAnimations = com.android.internal.R.style.Animation_Toast;
Jeff Changb10fac72019-04-09 17:28:30 +0800875 // Toast can show with below conditions when the screen is locked.
876 if (canToastShowWhenLocked(callingPid)) {
877 attrs.flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
878 }
Bernardo Rufino974de952019-10-22 11:53:42 +0100879 // Toasts can't be clickable
880 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800881 break;
882 }
883
884 if (attrs.type != TYPE_STATUS_BAR) {
885 // The status bar is the only window allowed to exhibit keyguard behavior.
886 attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
887 }
888 }
889
890 /**
Jeff Changb10fac72019-04-09 17:28:30 +0800891 * @return {@code true} if the calling activity initiate toast and is visible with
892 * {@link WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} flag.
893 */
894 boolean canToastShowWhenLocked(int callingPid) {
895 return mDisplayContent.forAllWindows(w -> {
896 return callingPid == w.mSession.mPid && w.isVisible() && w.canShowWhenLocked();
897 }, true /* traverseTopToBottom */);
898 }
899
900 /**
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800901 * Check if a window can be added to the system.
Tiger Huang7c610aa2018-10-27 00:01:01 +0800902 *
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800903 * Currently enforces that two window types are singletons per display:
Tiger Huang7c610aa2018-10-27 00:01:01 +0800904 * <ul>
905 * <li>{@link WindowManager.LayoutParams#TYPE_STATUS_BAR}</li>
906 * <li>{@link WindowManager.LayoutParams#TYPE_NAVIGATION_BAR}</li>
907 * </ul>
908 *
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800909 * @param attrs Information about the window to be added.
Tiger Huang7c610aa2018-10-27 00:01:01 +0800910 *
911 * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons,
912 * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
913 */
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800914 int validateAddingWindowLw(WindowManager.LayoutParams attrs) {
Tiger Huang7c610aa2018-10-27 00:01:01 +0800915 if ((attrs.privateFlags & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0) {
916 mContext.enforceCallingOrSelfPermission(
917 android.Manifest.permission.STATUS_BAR_SERVICE,
918 "DisplayPolicy");
Tiger Huang7c610aa2018-10-27 00:01:01 +0800919 }
920
921 switch (attrs.type) {
922 case TYPE_STATUS_BAR:
923 mContext.enforceCallingOrSelfPermission(
924 android.Manifest.permission.STATUS_BAR_SERVICE,
925 "DisplayPolicy");
926 if (mStatusBar != null) {
927 if (mStatusBar.isAlive()) {
928 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
929 }
930 }
Tiger Huang5f6cbca2019-07-18 19:00:01 +0800931 break;
932 case TYPE_NAVIGATION_BAR:
933 mContext.enforceCallingOrSelfPermission(
934 android.Manifest.permission.STATUS_BAR_SERVICE,
935 "DisplayPolicy");
936 if (mNavigationBar != null) {
937 if (mNavigationBar.isAlive()) {
938 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
939 }
940 }
941 break;
942 case TYPE_NAVIGATION_BAR_PANEL:
943 case TYPE_STATUS_BAR_PANEL:
944 case TYPE_STATUS_BAR_SUB_PANEL:
945 case TYPE_VOICE_INTERACTION_STARTING:
946 mContext.enforceCallingOrSelfPermission(
947 android.Manifest.permission.STATUS_BAR_SERVICE,
948 "DisplayPolicy");
949 break;
950 }
951 return ADD_OKAY;
952 }
953
954 /**
955 * Called when a window is being added to the system. Must not throw an exception.
956 *
957 * @param win The window being added.
958 * @param attrs Information about the window to be added.
959 */
960 void addWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
961 if ((attrs.privateFlags & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0) {
962 mScreenDecorWindows.add(win);
963 }
964
965 switch (attrs.type) {
966 case TYPE_STATUS_BAR:
Tiger Huang7c610aa2018-10-27 00:01:01 +0800967 mStatusBar = win;
968 mStatusBarController.setWindow(win);
969 if (mDisplayContent.isDefaultDisplay) {
970 mService.mPolicy.setKeyguardCandidateLw(win);
971 }
Adrian Roos11dfd272019-03-25 19:21:26 +0100972 final TriConsumer<DisplayFrames, WindowState, Rect> frameProvider =
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200973 (displayFrames, windowState, rect) -> {
974 rect.top = 0;
975 rect.bottom = getStatusBarHeight(displayFrames);
Adrian Roos11dfd272019-03-25 19:21:26 +0100976 };
Tiger Huang332793b2019-10-29 23:21:27 +0800977 mDisplayContent.setInsetProvider(ITYPE_STATUS_BAR, win, frameProvider);
978 mDisplayContent.setInsetProvider(ITYPE_TOP_GESTURES, win, frameProvider);
979 mDisplayContent.setInsetProvider(ITYPE_TOP_TAPPABLE_ELEMENT, win, frameProvider);
Tiger Huang7c610aa2018-10-27 00:01:01 +0800980 break;
981 case TYPE_NAVIGATION_BAR:
Tiger Huang7c610aa2018-10-27 00:01:01 +0800982 mNavigationBar = win;
983 mNavigationBarController.setWindow(win);
984 mNavigationBarController.setOnBarVisibilityChangedListener(
985 mNavBarVisibilityListener, true);
Tiger Huang332793b2019-10-29 23:21:27 +0800986 mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR,
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200987 win, null /* frameProvider */);
Tiger Huang332793b2019-10-29 23:21:27 +0800988 mDisplayContent.setInsetProvider(ITYPE_BOTTOM_GESTURES, win,
Adrian Roos11dfd272019-03-25 19:21:26 +0100989 (displayFrames, windowState, inOutFrame) -> {
990 inOutFrame.top -= mBottomGestureAdditionalInset;
991 });
Tiger Huang332793b2019-10-29 23:21:27 +0800992 mDisplayContent.setInsetProvider(ITYPE_LEFT_GESTURES, win,
Adrian Roos11dfd272019-03-25 19:21:26 +0100993 (displayFrames, windowState, inOutFrame) -> {
994 inOutFrame.left = 0;
995 inOutFrame.top = 0;
996 inOutFrame.bottom = displayFrames.mDisplayHeight;
997 inOutFrame.right = displayFrames.mUnrestricted.left + mSideGestureInset;
998 });
Tiger Huang332793b2019-10-29 23:21:27 +0800999 mDisplayContent.setInsetProvider(ITYPE_RIGHT_GESTURES, win,
Adrian Roos11dfd272019-03-25 19:21:26 +01001000 (displayFrames, windowState, inOutFrame) -> {
1001 inOutFrame.left = displayFrames.mUnrestricted.right - mSideGestureInset;
1002 inOutFrame.top = 0;
1003 inOutFrame.bottom = displayFrames.mDisplayHeight;
1004 inOutFrame.right = displayFrames.mDisplayWidth;
1005 });
Tiger Huang332793b2019-10-29 23:21:27 +08001006 mDisplayContent.setInsetProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT, win,
Adrian Roos11dfd272019-03-25 19:21:26 +01001007 (displayFrames, windowState, inOutFrame) -> {
1008 if ((windowState.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0
1009 || mNavigationBarLetsThroughTaps) {
1010 inOutFrame.setEmpty();
1011 }
1012 });
Tiger Huang7c610aa2018-10-27 00:01:01 +08001013 if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
1014 break;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001015 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001016 }
1017
1018 /**
1019 * Called when a window is being removed from a window manager. Must not
1020 * throw an exception -- clean up as much as possible.
1021 *
1022 * @param win The window being removed.
1023 */
Tiger Huang5f6cbca2019-07-18 19:00:01 +08001024 void removeWindowLw(WindowState win) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001025 if (mStatusBar == win) {
1026 mStatusBar = null;
1027 mStatusBarController.setWindow(null);
1028 if (mDisplayContent.isDefaultDisplay) {
1029 mService.mPolicy.setKeyguardCandidateLw(null);
1030 }
Tiger Huang332793b2019-10-29 23:21:27 +08001031 mDisplayContent.setInsetProvider(ITYPE_STATUS_BAR, null, null);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001032 } else if (mNavigationBar == win) {
1033 mNavigationBar = null;
1034 mNavigationBarController.setWindow(null);
Tiger Huang332793b2019-10-29 23:21:27 +08001035 mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, null, null);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001036 }
1037 if (mLastFocusedWindow == win) {
1038 mLastFocusedWindow = null;
1039 }
1040 mScreenDecorWindows.remove(win);
1041 }
1042
Jorim Jaggif96c90a2018-09-26 16:55:15 +02001043 private int getStatusBarHeight(DisplayFrames displayFrames) {
1044 return Math.max(mStatusBarHeightForRotation[displayFrames.mRotation],
1045 displayFrames.mDisplayCutoutSafe.top);
1046 }
1047
Jorim Jaggi28620472019-01-02 23:21:49 +01001048 WindowState getStatusBar() {
1049 return mStatusBar;
1050 }
1051
1052 WindowState getNavigationBar() {
1053 return mNavigationBar;
1054 }
1055
Tiger Huang7c610aa2018-10-27 00:01:01 +08001056 /**
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001057 * Control the animation to run when a window's state changes. Return a positive number to
1058 * force the animation to a specific resource ID, {@link #ANIMATION_STYLEABLE} to use the
1059 * style resource defining the animation, or {@link #ANIMATION_NONE} for no animation.
Tiger Huang7c610aa2018-10-27 00:01:01 +08001060 *
1061 * @param win The window that is changing.
1062 * @param transit What is happening to the window:
1063 * {@link com.android.server.policy.WindowManagerPolicy#TRANSIT_ENTER},
1064 * {@link com.android.server.policy.WindowManagerPolicy#TRANSIT_EXIT},
1065 * {@link com.android.server.policy.WindowManagerPolicy#TRANSIT_SHOW}, or
1066 * {@link com.android.server.policy.WindowManagerPolicy#TRANSIT_HIDE}.
1067 *
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001068 * @return Resource ID of the actual animation to use, or {@link #ANIMATION_NONE} for none.
Tiger Huang7c610aa2018-10-27 00:01:01 +08001069 */
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001070 int selectAnimation(WindowState win, int transit) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001071 if (DEBUG_ANIM) Slog.i(TAG, "selectAnimation in " + win
1072 + ": transit=" + transit);
1073 if (win == mStatusBar) {
1074 final boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
1075 final boolean expanded = win.getAttrs().height == MATCH_PARENT
1076 && win.getAttrs().width == MATCH_PARENT;
1077 if (isKeyguard || expanded) {
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001078 return ANIMATION_NONE;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001079 }
1080 if (transit == TRANSIT_EXIT
1081 || transit == TRANSIT_HIDE) {
1082 return R.anim.dock_top_exit;
1083 } else if (transit == TRANSIT_ENTER
1084 || transit == TRANSIT_SHOW) {
1085 return R.anim.dock_top_enter;
1086 }
1087 } else if (win == mNavigationBar) {
1088 if (win.getAttrs().windowAnimations != 0) {
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001089 return ANIMATION_STYLEABLE;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001090 }
1091 // This can be on either the bottom or the right or the left.
1092 if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
1093 if (transit == TRANSIT_EXIT
1094 || transit == TRANSIT_HIDE) {
1095 if (mService.mPolicy.isKeyguardShowingAndNotOccluded()) {
1096 return R.anim.dock_bottom_exit_keyguard;
1097 } else {
1098 return R.anim.dock_bottom_exit;
1099 }
1100 } else if (transit == TRANSIT_ENTER
1101 || transit == TRANSIT_SHOW) {
1102 return R.anim.dock_bottom_enter;
1103 }
1104 } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
1105 if (transit == TRANSIT_EXIT
1106 || transit == TRANSIT_HIDE) {
1107 return R.anim.dock_right_exit;
1108 } else if (transit == TRANSIT_ENTER
1109 || transit == TRANSIT_SHOW) {
1110 return R.anim.dock_right_enter;
1111 }
1112 } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
1113 if (transit == TRANSIT_EXIT
1114 || transit == TRANSIT_HIDE) {
1115 return R.anim.dock_left_exit;
1116 } else if (transit == TRANSIT_ENTER
1117 || transit == TRANSIT_SHOW) {
1118 return R.anim.dock_left_enter;
1119 }
1120 }
1121 } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) {
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001122 return selectDockedDividerAnimation(win, transit);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001123 }
1124
1125 if (transit == TRANSIT_PREVIEW_DONE) {
1126 if (win.hasAppShownWindows()) {
1127 if (DEBUG_ANIM) Slog.i(TAG, "**** STARTING EXIT");
1128 return R.anim.app_starting_exit;
1129 }
1130 } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
1131 && transit == TRANSIT_ENTER) {
1132 // Special case: we are animating in a dream, while the keyguard
1133 // is shown. We don't want an animation on the dream, because
1134 // we need it shown immediately with the keyguard animating away
1135 // to reveal it.
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001136 return ANIMATION_NONE;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001137 }
1138
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001139 return ANIMATION_STYLEABLE;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001140 }
1141
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001142 private int selectDockedDividerAnimation(WindowState win, int transit) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001143 int insets = mDisplayContent.getDockedDividerController().getContentInsets();
1144
1145 // If the divider is behind the navigation bar, don't animate.
1146 final Rect frame = win.getFrameLw();
1147 final boolean behindNavBar = mNavigationBar != null
1148 && ((mNavigationBarPosition == NAV_BAR_BOTTOM
1149 && frame.top + insets >= mNavigationBar.getFrameLw().top)
1150 || (mNavigationBarPosition == NAV_BAR_RIGHT
1151 && frame.left + insets >= mNavigationBar.getFrameLw().left)
1152 || (mNavigationBarPosition == NAV_BAR_LEFT
1153 && frame.right - insets <= mNavigationBar.getFrameLw().right));
1154 final boolean landscape = frame.height() > frame.width();
1155 final boolean offscreenLandscape = landscape && (frame.right - insets <= 0
1156 || frame.left + insets >= win.getDisplayFrameLw().right);
1157 final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0
1158 || frame.bottom + insets >= win.getDisplayFrameLw().bottom);
1159 final boolean offscreen = offscreenLandscape || offscreenPortrait;
1160 if (behindNavBar || offscreen) {
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001161 return ANIMATION_STYLEABLE;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001162 }
1163 if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
1164 return R.anim.fade_in;
1165 } else if (transit == TRANSIT_EXIT) {
1166 return R.anim.fade_out;
1167 } else {
Riddle Hsu2ca561b2019-10-08 21:58:58 +08001168 return ANIMATION_STYLEABLE;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001169 }
1170 }
1171
1172 /**
Tiger Huang7c610aa2018-10-27 00:01:01 +08001173 * Called when a new system UI visibility is being reported, allowing
1174 * the policy to adjust what is actually reported.
1175 * @param visibility The raw visibility reported by the status bar.
1176 * @return The new desired visibility.
1177 */
1178 public int adjustSystemUiVisibilityLw(int visibility) {
1179 mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
1180 mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
1181
1182 // Reset any bits in mForceClearingStatusBarVisibility that
1183 // are now clear.
1184 mResettingSystemUiFlags &= visibility;
1185 // Clear any bits in the new visibility that are currently being
1186 // force cleared, before reporting it.
1187 return visibility & ~mResettingSystemUiFlags
1188 & ~mForceClearedSystemUiFlags;
1189 }
1190
1191 /**
Brad Stenninge0573692019-03-11 13:52:46 -07001192 * @return true if the system bars are forced to stay visible
Tiger Huang7c610aa2018-10-27 00:01:01 +08001193 */
Brad Stenninge0573692019-03-11 13:52:46 -07001194 public boolean areSystemBarsForcedShownLw(WindowState windowState) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001195 return mForceShowSystemBars;
1196 }
1197
1198 // TODO: Should probably be moved into DisplayFrames.
1199 /**
1200 * Return the layout hints for a newly added window. These values are computed on the
1201 * most recent layout, so they are not guaranteed to be correct.
1202 *
1203 * @param attrs The LayoutParams of the window.
1204 * @param taskBounds The bounds of the task this window is on or {@code null} if no task is
1205 * associated with the window.
1206 * @param displayFrames display frames.
1207 * @param floatingStack Whether the window's stack is floating.
1208 * @param outFrame The frame of the window.
1209 * @param outContentInsets The areas covered by system windows, expressed as positive insets.
1210 * @param outStableInsets The areas covered by stable system windows irrespective of their
1211 * current visibility. Expressed as positive insets.
Tiger Huang7c610aa2018-10-27 00:01:01 +08001212 * @param outDisplayCutout The area that has been cut away from the display.
Brad Stenninge0573692019-03-11 13:52:46 -07001213 * @return Whether to always consume the system bars.
1214 * See {@link #areSystemBarsForcedShownLw(WindowState)}.
Tiger Huang7c610aa2018-10-27 00:01:01 +08001215 */
1216 public boolean getLayoutHintLw(LayoutParams attrs, Rect taskBounds,
1217 DisplayFrames displayFrames, boolean floatingStack, Rect outFrame,
1218 Rect outContentInsets, Rect outStableInsets,
Jorim Jaggif081f062019-10-24 16:24:54 +02001219 DisplayCutout.ParcelableWrapper outDisplayCutout) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001220 final int fl = PolicyControl.getWindowFlags(null, attrs);
1221 final int pfl = attrs.privateFlags;
1222 final int requestedSysUiVis = PolicyControl.getSystemUiVisibility(null, attrs);
1223 final int sysUiVis = requestedSysUiVis | getImpliedSysUiFlagsForLayout(attrs);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001224
1225 final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) != 0;
1226 final boolean layoutInScreenAndInsetDecor = layoutInScreen
1227 && (fl & FLAG_LAYOUT_INSET_DECOR) != 0;
1228 final boolean screenDecor = (pfl & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0;
1229
1230 if (layoutInScreenAndInsetDecor && !screenDecor) {
Jorim Jaggid6490572019-04-16 14:57:56 +02001231 if ((sysUiVis & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001232 outFrame.set(displayFrames.mUnrestricted);
1233 } else {
1234 outFrame.set(displayFrames.mRestricted);
1235 }
1236
1237 final Rect sf;
1238 if (floatingStack) {
1239 sf = null;
1240 } else {
1241 sf = displayFrames.mStable;
1242 }
1243
1244 final Rect cf;
1245 if (floatingStack) {
1246 cf = null;
1247 } else if ((sysUiVis & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
1248 if ((fl & FLAG_FULLSCREEN) != 0) {
1249 cf = displayFrames.mStableFullscreen;
1250 } else {
1251 cf = displayFrames.mStable;
1252 }
Jorim Jaggif081f062019-10-24 16:24:54 +02001253 } else if ((fl & FLAG_FULLSCREEN) != 0) {
1254 cf = displayFrames.mUnrestricted;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001255 } else {
1256 cf = displayFrames.mCurrent;
1257 }
1258
1259 if (taskBounds != null) {
1260 outFrame.intersect(taskBounds);
1261 }
1262 InsetUtils.insetsBetweenFrames(outFrame, cf, outContentInsets);
1263 InsetUtils.insetsBetweenFrames(outFrame, sf, outStableInsets);
1264 outDisplayCutout.set(displayFrames.mDisplayCutout.calculateRelativeTo(outFrame)
1265 .getDisplayCutout());
1266 return mForceShowSystemBars;
1267 } else {
1268 if (layoutInScreen) {
1269 outFrame.set(displayFrames.mUnrestricted);
1270 } else {
1271 outFrame.set(displayFrames.mStable);
1272 }
1273 if (taskBounds != null) {
1274 outFrame.intersect(taskBounds);
1275 }
1276
1277 outContentInsets.setEmpty();
1278 outStableInsets.setEmpty();
1279 outDisplayCutout.set(DisplayCutout.NO_CUTOUT);
1280 return mForceShowSystemBars;
1281 }
1282 }
1283
1284 private static int getImpliedSysUiFlagsForLayout(LayoutParams attrs) {
1285 int impliedFlags = 0;
Jorim Jaggia6aabac2019-03-11 14:23:16 -07001286 final boolean forceWindowDrawsBarBackgrounds =
1287 (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0
1288 && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001289 if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
Jorim Jaggia6aabac2019-03-11 14:23:16 -07001290 || forceWindowDrawsBarBackgrounds) {
Jorim Jaggid6490572019-04-16 14:57:56 +02001291 impliedFlags |= SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001292 impliedFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
1293 }
1294 return impliedFlags;
1295 }
1296
Tiger Huang7c610aa2018-10-27 00:01:01 +08001297 private final Runnable mClearHideNavigationFlag = new Runnable() {
1298 @Override
1299 public void run() {
1300 synchronized (mLock) {
1301 mForceClearedSystemUiFlags &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
1302 mDisplayContent.reevaluateStatusBarVisibility();
1303 }
1304 }
1305 };
1306
1307 /**
1308 * Input handler used while nav bar is hidden. Captures any touch on the screen,
1309 * to determine when the nav bar should be shown and prevent applications from
1310 * receiving those touches.
1311 */
1312 private final class HideNavInputEventReceiver extends InputEventReceiver {
1313 HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
1314 super(inputChannel, looper);
1315 }
1316
1317 @Override
1318 public void onInputEvent(InputEvent event) {
1319 try {
1320 if (event instanceof MotionEvent
1321 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
1322 final MotionEvent motionEvent = (MotionEvent) event;
1323 if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
1324 // When the user taps down, we re-show the nav bar.
1325 boolean changed = false;
1326 synchronized (mLock) {
1327 if (mInputConsumer == null) {
1328 return;
1329 }
1330 // Any user activity always causes us to show the
1331 // navigation controls, if they had been hidden.
1332 // We also clear the low profile and only content
1333 // flags so that tapping on the screen will atomically
1334 // restore all currently hidden screen decorations.
1335 int newVal = mResettingSystemUiFlags
1336 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
1337 | View.SYSTEM_UI_FLAG_LOW_PROFILE
1338 | View.SYSTEM_UI_FLAG_FULLSCREEN;
1339 if (mResettingSystemUiFlags != newVal) {
1340 mResettingSystemUiFlags = newVal;
1341 changed = true;
1342 }
1343 // We don't allow the system's nav bar to be hidden
1344 // again for 1 second, to prevent applications from
1345 // spamming us and keeping it from being shown.
1346 newVal = mForceClearedSystemUiFlags
1347 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
1348 if (mForceClearedSystemUiFlags != newVal) {
1349 mForceClearedSystemUiFlags = newVal;
1350 changed = true;
1351 mHandler.postDelayed(mClearHideNavigationFlag, 1000);
1352 }
1353 if (changed) {
1354 mDisplayContent.reevaluateStatusBarVisibility();
1355 }
1356 }
1357 }
1358 }
1359 } finally {
1360 finishInputEvent(event, false /* handled */);
1361 }
1362 }
1363 }
1364
1365 /**
1366 * Called when layout of the windows is about to start.
1367 *
1368 * @param displayFrames frames of the display we are doing layout on.
1369 * @param uiMode The current uiMode in configuration.
1370 */
1371 public void beginLayoutLw(DisplayFrames displayFrames, int uiMode) {
1372 displayFrames.onBeginLayout();
1373 mSystemGestures.screenWidth = displayFrames.mUnrestricted.width();
1374 mSystemGestures.screenHeight = displayFrames.mUnrestricted.height();
1375
1376 // For purposes of putting out fake window up to steal focus, we will
1377 // drive nav being hidden only by whether it is requested.
1378 final int sysui = mLastSystemUiFlags;
1379 boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
1380 boolean navTranslucent = (sysui
1381 & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
1382 boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
1383 boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
1384 boolean navAllowedHidden = immersive || immersiveSticky;
1385 navTranslucent &= !immersiveSticky; // transient trumps translucent
1386 boolean isKeyguardShowing = isStatusBarKeyguard()
1387 && !mService.mPolicy.isKeyguardOccluded();
Tiger Huang7c610aa2018-10-27 00:01:01 +08001388 boolean statusBarForcesShowingNavigation = !isKeyguardShowing && mStatusBar != null
1389 && (mStatusBar.getAttrs().privateFlags
1390 & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0;
1391
1392 // When the navigation bar isn't visible, we put up a fake input window to catch all
1393 // touch events. This way we can detect when the user presses anywhere to bring back the
1394 // nav bar and ensure the application doesn't see the event.
1395 if (navVisible || navAllowedHidden) {
1396 if (mInputConsumer != null) {
1397 mHandler.sendMessage(
1398 mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
1399 mInputConsumer = null;
1400 }
1401 } else if (mInputConsumer == null && mStatusBar != null && canHideNavigationBar()) {
1402 mInputConsumer = mService.createInputConsumer(mHandler.getLooper(),
1403 INPUT_CONSUMER_NAVIGATION,
1404 HideNavInputEventReceiver::new,
1405 displayFrames.mDisplayId);
1406 // As long as mInputConsumer is active, hover events are not dispatched to the app
1407 // and the pointer icon is likely to become stale. Hide it to avoid confusion.
1408 InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL);
1409 }
1410
1411 // For purposes of positioning and showing the nav bar, if we have decided that it can't
1412 // be hidden (because of the screen aspect ratio), then take that into account.
1413 navVisible |= !canHideNavigationBar();
1414
1415 boolean updateSysUiVisibility = layoutNavigationBar(displayFrames, uiMode, navVisible,
1416 navTranslucent, navAllowedHidden, statusBarForcesShowingNavigation);
1417 if (DEBUG_LAYOUT) Slog.i(TAG, "mDock rect:" + displayFrames.mDock);
1418 updateSysUiVisibility |= layoutStatusBar(displayFrames, sysui, isKeyguardShowing);
1419 if (updateSysUiVisibility) {
1420 updateSystemUiVisibilityLw();
1421 }
1422 layoutScreenDecorWindows(displayFrames);
1423
1424 if (displayFrames.mDisplayCutoutSafe.top > displayFrames.mUnrestricted.top) {
1425 // Make sure that the zone we're avoiding for the cutout is at least as tall as the
1426 // status bar; otherwise fullscreen apps will end up cutting halfway into the status
1427 // bar.
1428 displayFrames.mDisplayCutoutSafe.top = Math.max(displayFrames.mDisplayCutoutSafe.top,
1429 displayFrames.mStable.top);
1430 }
Issei Suzukia5dbf522019-02-01 17:58:15 +01001431
1432 // In case this is a virtual display, and the host display has insets that overlap this
1433 // virtual display, apply the insets of the overlapped area onto the current and content
1434 // frame of this virtual display. This let us layout windows in the virtual display as
1435 // expected when the window needs to avoid overlap with the system windows.
1436 // TODO: Generalize the forwarded insets, so that we can handle system windows other than
1437 // IME.
1438 displayFrames.mCurrent.inset(mForwardedInsets);
1439 displayFrames.mContent.inset(mForwardedInsets);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001440 }
1441
1442 private void layoutScreenDecorWindows(DisplayFrames displayFrames) {
1443 if (mScreenDecorWindows.isEmpty()) {
1444 return;
1445 }
1446
1447 sTmpRect.setEmpty();
Tiger Huang7c610aa2018-10-27 00:01:01 +08001448 final int displayId = displayFrames.mDisplayId;
1449 final Rect dockFrame = displayFrames.mDock;
1450 final int displayHeight = displayFrames.mDisplayHeight;
1451 final int displayWidth = displayFrames.mDisplayWidth;
1452
1453 for (int i = mScreenDecorWindows.size() - 1; i >= 0; --i) {
1454 final WindowState w = mScreenDecorWindows.valueAt(i);
1455 if (w.getDisplayId() != displayId || !w.isVisibleLw()) {
1456 // Skip if not on the same display or not visible.
1457 continue;
1458 }
1459
chaviw0d833762019-06-20 17:09:53 -07001460 w.getWindowFrames().setFrames(displayFrames.mUnrestricted /* parentFrame */,
1461 displayFrames.mUnrestricted /* displayFrame */,
chaviw0d833762019-06-20 17:09:53 -07001462 displayFrames.mUnrestricted /* contentFrame */,
1463 displayFrames.mUnrestricted /* visibleFrame */, sTmpRect /* decorFrame */,
Jorim Jaggif081f062019-10-24 16:24:54 +02001464 displayFrames.mUnrestricted /* stableFrame */);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001465 w.getWindowFrames().setDisplayCutout(displayFrames.mDisplayCutout);
1466 w.computeFrameLw();
1467 final Rect frame = w.getFrameLw();
1468
1469 if (frame.left <= 0 && frame.top <= 0) {
1470 // Docked at left or top.
1471 if (frame.bottom >= displayHeight) {
1472 // Docked left.
1473 dockFrame.left = Math.max(frame.right, dockFrame.left);
1474 } else if (frame.right >= displayWidth) {
1475 // Docked top.
1476 dockFrame.top = Math.max(frame.bottom, dockFrame.top);
1477 } else {
1478 Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w
1479 + " not docked on left or top of display. frame=" + frame
1480 + " displayWidth=" + displayWidth + " displayHeight=" + displayHeight);
1481 }
1482 } else if (frame.right >= displayWidth && frame.bottom >= displayHeight) {
1483 // Docked at right or bottom.
1484 if (frame.top <= 0) {
1485 // Docked right.
1486 dockFrame.right = Math.min(frame.left, dockFrame.right);
1487 } else if (frame.left <= 0) {
1488 // Docked bottom.
1489 dockFrame.bottom = Math.min(frame.top, dockFrame.bottom);
1490 } else {
1491 Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w
1492 + " not docked on right or bottom" + " of display. frame=" + frame
1493 + " displayWidth=" + displayWidth + " displayHeight=" + displayHeight);
1494 }
1495 } else {
1496 // Screen decor windows are required to be docked on one of the sides of the screen.
1497 Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w
1498 + " not docked on one of the sides of the display. frame=" + frame
1499 + " displayWidth=" + displayWidth + " displayHeight=" + displayHeight);
1500 }
1501 }
1502
1503 displayFrames.mRestricted.set(dockFrame);
1504 displayFrames.mCurrent.set(dockFrame);
1505 displayFrames.mVoiceContent.set(dockFrame);
1506 displayFrames.mSystem.set(dockFrame);
1507 displayFrames.mContent.set(dockFrame);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001508 }
1509
1510 private boolean layoutStatusBar(DisplayFrames displayFrames, int sysui,
1511 boolean isKeyguardShowing) {
1512 // decide where the status bar goes ahead of time
1513 if (mStatusBar == null) {
1514 return false;
1515 }
1516 // apply any navigation bar insets
1517 sTmpRect.setEmpty();
Jorim Jaggi4981f152019-03-26 18:58:45 +01001518 final WindowFrames windowFrames = mStatusBar.getWindowFrames();
1519 windowFrames.setFrames(displayFrames.mUnrestricted /* parentFrame */,
Tiger Huang7c610aa2018-10-27 00:01:01 +08001520 displayFrames.mUnrestricted /* displayFrame */,
Jorim Jaggif081f062019-10-24 16:24:54 +02001521 displayFrames.mStable /* contentFrame */,
Tiger Huang7c610aa2018-10-27 00:01:01 +08001522 displayFrames.mStable /* visibleFrame */, sTmpRect /* decorFrame */,
Jorim Jaggif081f062019-10-24 16:24:54 +02001523 displayFrames.mStable /* stableFrame */);
Jorim Jaggi4981f152019-03-26 18:58:45 +01001524 windowFrames.setDisplayCutout(displayFrames.mDisplayCutout);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001525
1526 // Let the status bar determine its size.
1527 mStatusBar.computeFrameLw();
1528
1529 // For layout, the status bar is always at the top with our fixed height.
1530 displayFrames.mStable.top = displayFrames.mUnrestricted.top
1531 + mStatusBarHeightForRotation[displayFrames.mRotation];
1532 // Make sure the status bar covers the entire cutout height
1533 displayFrames.mStable.top = Math.max(displayFrames.mStable.top,
1534 displayFrames.mDisplayCutoutSafe.top);
1535
1536 // Tell the bar controller where the collapsed status bar content is
1537 sTmpRect.set(mStatusBar.getContentFrameLw());
1538 sTmpRect.intersect(displayFrames.mDisplayCutoutSafe);
1539 sTmpRect.top = mStatusBar.getContentFrameLw().top; // Ignore top display cutout inset
1540 sTmpRect.bottom = displayFrames.mStable.top; // Use collapsed status bar size
1541 mStatusBarController.setContentFrame(sTmpRect);
1542
1543 boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
1544 boolean statusBarTranslucent = (sysui
1545 & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001546
1547 // If the status bar is hidden, we don't want to cause windows behind it to scroll.
1548 if (mStatusBar.isVisibleLw() && !statusBarTransient) {
1549 // Status bar may go away, so the screen area it occupies is available to apps but just
1550 // covering them when the status bar is visible.
1551 final Rect dockFrame = displayFrames.mDock;
1552 dockFrame.top = displayFrames.mStable.top;
1553 displayFrames.mContent.set(dockFrame);
1554 displayFrames.mVoiceContent.set(dockFrame);
1555 displayFrames.mCurrent.set(dockFrame);
1556
1557 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " + String.format(
1558 "dock=%s content=%s cur=%s", dockFrame.toString(),
1559 displayFrames.mContent.toString(), displayFrames.mCurrent.toString()));
1560
Jorim Jaggi4981f152019-03-26 18:58:45 +01001561 if (!statusBarTranslucent && !mStatusBarController.wasRecentlyTranslucent()
1562 && !mStatusBar.isAnimatingLw()) {
1563
Tiger Huang7c610aa2018-10-27 00:01:01 +08001564 // If the opaque status bar is currently requested to be visible, and not in the
1565 // process of animating on or off, then we can tell the app that it is covered by
1566 // it.
1567 displayFrames.mSystem.top = displayFrames.mStable.top;
1568 }
1569 }
1570 return mStatusBarController.checkHiddenLw();
1571 }
1572
1573 private boolean layoutNavigationBar(DisplayFrames displayFrames, int uiMode, boolean navVisible,
1574 boolean navTranslucent, boolean navAllowedHidden,
1575 boolean statusBarForcesShowingNavigation) {
1576 if (mNavigationBar == null) {
1577 return false;
1578 }
1579
1580 final Rect navigationFrame = sTmpNavFrame;
1581 boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
1582 // Force the navigation bar to its appropriate place and size. We need to do this directly,
1583 // instead of relying on it to bubble up from the nav bar, because this needs to change
1584 // atomically with screen rotations.
1585 final int rotation = displayFrames.mRotation;
1586 final int displayHeight = displayFrames.mDisplayHeight;
1587 final int displayWidth = displayFrames.mDisplayWidth;
1588 final Rect dockFrame = displayFrames.mDock;
1589 mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight, rotation);
1590
1591 final Rect cutoutSafeUnrestricted = sTmpRect;
1592 cutoutSafeUnrestricted.set(displayFrames.mUnrestricted);
1593 cutoutSafeUnrestricted.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
1594
1595 if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
1596 // It's a system nav bar or a portrait screen; nav bar goes on bottom.
1597 final int top = cutoutSafeUnrestricted.bottom
1598 - getNavigationBarHeight(rotation, uiMode);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001599 final int topNavBar = cutoutSafeUnrestricted.bottom
Matthew Nga7f24bc2019-04-09 17:06:41 -07001600 - getNavigationBarFrameHeight(rotation, uiMode);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001601 navigationFrame.set(0, topNavBar, displayWidth, displayFrames.mUnrestricted.bottom);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001602 displayFrames.mStable.bottom = displayFrames.mStableFullscreen.bottom = top;
1603 if (transientNavBarShowing) {
1604 mNavigationBarController.setBarShowingLw(true);
1605 } else if (navVisible) {
1606 mNavigationBarController.setBarShowingLw(true);
Jorim Jaggif081f062019-10-24 16:24:54 +02001607 dockFrame.bottom = displayFrames.mRestricted.bottom = top;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001608 } else {
1609 // We currently want to hide the navigation UI - unless we expanded the status bar.
1610 mNavigationBarController.setBarShowingLw(statusBarForcesShowingNavigation);
1611 }
1612 if (navVisible && !navTranslucent && !navAllowedHidden
1613 && !mNavigationBar.isAnimatingLw()
1614 && !mNavigationBarController.wasRecentlyTranslucent()) {
1615 // If the opaque nav bar is currently requested to be visible and not in the process
1616 // of animating on or off, then we can tell the app that it is covered by it.
1617 displayFrames.mSystem.bottom = top;
1618 }
1619 } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
1620 // Landscape screen; nav bar goes to the right.
1621 final int left = cutoutSafeUnrestricted.right
1622 - getNavigationBarWidth(rotation, uiMode);
Matthew Nga7f24bc2019-04-09 17:06:41 -07001623 navigationFrame.set(left, 0, displayFrames.mUnrestricted.right, displayHeight);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001624 displayFrames.mStable.right = displayFrames.mStableFullscreen.right = left;
1625 if (transientNavBarShowing) {
1626 mNavigationBarController.setBarShowingLw(true);
1627 } else if (navVisible) {
1628 mNavigationBarController.setBarShowingLw(true);
Jorim Jaggif081f062019-10-24 16:24:54 +02001629 dockFrame.right = displayFrames.mRestricted.right = left;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001630 } else {
1631 // We currently want to hide the navigation UI - unless we expanded the status bar.
1632 mNavigationBarController.setBarShowingLw(statusBarForcesShowingNavigation);
1633 }
1634 if (navVisible && !navTranslucent && !navAllowedHidden
1635 && !mNavigationBar.isAnimatingLw()
1636 && !mNavigationBarController.wasRecentlyTranslucent()) {
1637 // If the nav bar is currently requested to be visible, and not in the process of
1638 // animating on or off, then we can tell the app that it is covered by it.
1639 displayFrames.mSystem.right = left;
1640 }
1641 } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
1642 // Seascape screen; nav bar goes to the left.
1643 final int right = cutoutSafeUnrestricted.left
1644 + getNavigationBarWidth(rotation, uiMode);
Matthew Nga7f24bc2019-04-09 17:06:41 -07001645 navigationFrame.set(displayFrames.mUnrestricted.left, 0, right, displayHeight);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001646 displayFrames.mStable.left = displayFrames.mStableFullscreen.left = right;
1647 if (transientNavBarShowing) {
1648 mNavigationBarController.setBarShowingLw(true);
1649 } else if (navVisible) {
1650 mNavigationBarController.setBarShowingLw(true);
Jorim Jaggif081f062019-10-24 16:24:54 +02001651 dockFrame.left = displayFrames.mRestricted.left = right;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001652 } else {
1653 // We currently want to hide the navigation UI - unless we expanded the status bar.
1654 mNavigationBarController.setBarShowingLw(statusBarForcesShowingNavigation);
1655 }
1656 if (navVisible && !navTranslucent && !navAllowedHidden
1657 && !mNavigationBar.isAnimatingLw()
1658 && !mNavigationBarController.wasRecentlyTranslucent()) {
1659 // If the nav bar is currently requested to be visible, and not in the process of
1660 // animating on or off, then we can tell the app that it is covered by it.
1661 displayFrames.mSystem.left = right;
1662 }
1663 }
1664
1665 // Make sure the content and current rectangles are updated to account for the restrictions
1666 // from the navigation bar.
1667 displayFrames.mCurrent.set(dockFrame);
1668 displayFrames.mVoiceContent.set(dockFrame);
1669 displayFrames.mContent.set(dockFrame);
1670 // And compute the final frame.
1671 sTmpRect.setEmpty();
1672 mNavigationBar.getWindowFrames().setFrames(navigationFrame /* parentFrame */,
Jorim Jaggif081f062019-10-24 16:24:54 +02001673 navigationFrame /* displayFrame */,
Tiger Huang7c610aa2018-10-27 00:01:01 +08001674 displayFrames.mDisplayCutoutSafe /* contentFrame */,
1675 navigationFrame /* visibleFrame */, sTmpRect /* decorFrame */,
Jorim Jaggif081f062019-10-24 16:24:54 +02001676 navigationFrame /* stableFrame */);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001677 mNavigationBar.getWindowFrames().setDisplayCutout(displayFrames.mDisplayCutout);
1678 mNavigationBar.computeFrameLw();
1679 mNavigationBarController.setContentFrame(mNavigationBar.getContentFrameLw());
1680
1681 if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + navigationFrame);
1682 return mNavigationBarController.checkHiddenLw();
1683 }
1684
1685 private void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
Jorim Jaggif081f062019-10-24 16:24:54 +02001686 boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf,
Tiger Huang7c610aa2018-10-27 00:01:01 +08001687 DisplayFrames displayFrames) {
1688 if (!win.isInputMethodTarget() && attached.isInputMethodTarget()) {
1689 // Here's a special case: if the child window is not the 'dock window'
1690 // or input method target, and the window it is attached to is below
1691 // the dock window, then the frames we computed for the window it is
1692 // attached to can not be used because the dock is effectively part
1693 // of the underlying window and the attached window is floating on top
1694 // of the whole thing. So, we ignore the attached window and explicitly
1695 // compute the frames that would be appropriate without the dock.
1696 vf.set(displayFrames.mDock);
1697 cf.set(displayFrames.mDock);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001698 df.set(displayFrames.mDock);
1699 } else {
Jorim Jaggid6490572019-04-16 14:57:56 +02001700
Jorim Jaggif081f062019-10-24 16:24:54 +02001701 // In case we forced the window to draw behind the navigation bar, restrict df to
1702 // DF.Restricted to simulate old compat behavior.
Jorim Jaggia72b4cc2019-04-16 15:38:49 +02001703 Rect parentDisplayFrame = attached.getDisplayFrameLw();
Jorim Jaggid6490572019-04-16 14:57:56 +02001704 final WindowManager.LayoutParams attachedAttrs = attached.mAttrs;
1705 if ((attachedAttrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0
1706 && (attachedAttrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
1707 && (attachedAttrs.systemUiVisibility
1708 & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0) {
Jorim Jaggia72b4cc2019-04-16 15:38:49 +02001709 parentDisplayFrame = new Rect(parentDisplayFrame);
Jorim Jaggif081f062019-10-24 16:24:54 +02001710 parentDisplayFrame.intersect(displayFrames.mRestricted);
Jorim Jaggid6490572019-04-16 14:57:56 +02001711 }
1712
Tiger Huang7c610aa2018-10-27 00:01:01 +08001713 // The effective display frame of the attached window depends on whether it is taking
1714 // care of insetting its content. If not, we need to use the parent's content frame so
1715 // that the entire window is positioned within that content. Otherwise we can use the
Jorim Jaggif081f062019-10-24 16:24:54 +02001716 // parent display frame and let the attached window take care of positioning its content
Tiger Huang7c610aa2018-10-27 00:01:01 +08001717 // appropriately.
1718 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
1719 // Set the content frame of the attached window to the parent's decor frame
1720 // (same as content frame when IME isn't present) if specifically requested by
1721 // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
1722 // Otherwise, use the overscan frame.
1723 cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
Jorim Jaggif081f062019-10-24 16:24:54 +02001724 ? attached.getContentFrameLw() : parentDisplayFrame);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001725 } else {
1726 // If the window is resizing, then we want to base the content frame on our attached
1727 // content frame to resize...however, things can be tricky if the attached window is
1728 // NOT in resize mode, in which case its content frame will be larger.
1729 // Ungh. So to deal with that, make sure the content frame we end up using is not
1730 // covering the IM dock.
1731 cf.set(attached.getContentFrameLw());
1732 if (attached.isVoiceInteraction()) {
1733 cf.intersectUnchecked(displayFrames.mVoiceContent);
1734 } else if (win.isInputMethodTarget() || attached.isInputMethodTarget()) {
1735 cf.intersectUnchecked(displayFrames.mContent);
1736 }
1737 }
Jorim Jaggid6490572019-04-16 14:57:56 +02001738 df.set(insetDecors ? parentDisplayFrame : cf);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001739 vf.set(attached.getVisibleFrameLw());
1740 }
1741 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached window should be
1742 // positioned relative to its parent or the entire screen.
1743 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 ? attached.getFrameLw() : df);
1744 }
1745
1746 private void applyStableConstraints(int sysui, int fl, Rect r, DisplayFrames displayFrames) {
1747 if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) == 0) {
1748 return;
1749 }
1750 // If app is requesting a stable layout, don't let the content insets go below the stable
1751 // values.
1752 if ((fl & FLAG_FULLSCREEN) != 0) {
1753 r.intersectUnchecked(displayFrames.mStableFullscreen);
1754 } else {
1755 r.intersectUnchecked(displayFrames.mStable);
1756 }
1757 }
1758
1759 private boolean canReceiveInput(WindowState win) {
1760 boolean notFocusable =
1761 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
1762 boolean altFocusableIm =
1763 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
1764 boolean notFocusableForIm = notFocusable ^ altFocusableIm;
1765 return !notFocusableForIm;
1766 }
1767
1768 /**
1769 * Called for each window attached to the window manager as layout is proceeding. The
1770 * implementation of this function must take care of setting the window's frame, either here or
1771 * in finishLayout().
1772 *
1773 * @param win The window being positioned.
1774 * @param attached For sub-windows, the window it is attached to; this
1775 * window will already have had layoutWindow() called on it
1776 * so you can use its Rect. Otherwise null.
1777 * @param displayFrames The display frames.
1778 */
1779 public void layoutWindowLw(WindowState win, WindowState attached, DisplayFrames displayFrames) {
1780 // We've already done the navigation bar, status bar, and all screen decor windows. If the
1781 // status bar can receive input, we need to layout it again to accommodate for the IME
1782 // window.
1783 if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar
1784 || mScreenDecorWindows.contains(win)) {
1785 return;
1786 }
1787 final WindowManager.LayoutParams attrs = win.getAttrs();
Tiger Huang7c610aa2018-10-27 00:01:01 +08001788
1789 final int type = attrs.type;
1790 final int fl = PolicyControl.getWindowFlags(win, attrs);
1791 final int pfl = attrs.privateFlags;
1792 final int sim = attrs.softInputMode;
1793 final int requestedSysUiFl = PolicyControl.getSystemUiVisibility(null, attrs);
1794 final int sysUiFl = requestedSysUiFl | getImpliedSysUiFlagsForLayout(attrs);
1795
1796 final WindowFrames windowFrames = win.getWindowFrames();
1797
Tiger Huang7c610aa2018-10-27 00:01:01 +08001798 sTmpLastParentFrame.set(windowFrames.mParentFrame);
1799 final Rect pf = windowFrames.mParentFrame;
1800 final Rect df = windowFrames.mDisplayFrame;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001801 final Rect cf = windowFrames.mContentFrame;
1802 final Rect vf = windowFrames.mVisibleFrame;
1803 final Rect dcf = windowFrames.mDecorFrame;
1804 final Rect sf = windowFrames.mStableFrame;
1805 dcf.setEmpty();
1806 windowFrames.setParentFrameWasClippedByDisplayCutout(false);
1807 windowFrames.setDisplayCutout(displayFrames.mDisplayCutout);
1808
1809 final boolean hasNavBar = hasNavigationBar() && mNavigationBar != null
1810 && mNavigationBar.isVisibleLw();
1811
1812 final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
1813
1814 final boolean requestedFullscreen = (fl & FLAG_FULLSCREEN) != 0
1815 || (requestedSysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
1816
1817 final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) == FLAG_LAYOUT_IN_SCREEN;
1818 final boolean layoutInsetDecor = (fl & FLAG_LAYOUT_INSET_DECOR) == FLAG_LAYOUT_INSET_DECOR;
1819
1820 sf.set(displayFrames.mStable);
1821
1822 if (type == TYPE_INPUT_METHOD) {
1823 vf.set(displayFrames.mDock);
1824 cf.set(displayFrames.mDock);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001825 df.set(displayFrames.mDock);
1826 windowFrames.mParentFrame.set(displayFrames.mDock);
1827 // IM dock windows layout below the nav bar...
Jorim Jaggif081f062019-10-24 16:24:54 +02001828 pf.bottom = df.bottom = displayFrames.mUnrestricted.bottom;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001829 // ...with content insets above the nav bar
1830 cf.bottom = vf.bottom = displayFrames.mStable.bottom;
1831 if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
1832 // The status bar forces the navigation bar while it's visible. Make sure the IME
1833 // avoids the navigation bar in that case.
1834 if (mNavigationBarPosition == NAV_BAR_RIGHT) {
Jorim Jaggif081f062019-10-24 16:24:54 +02001835 pf.right = df.right = cf.right = vf.right =
Tiger Huang7c610aa2018-10-27 00:01:01 +08001836 displayFrames.mStable.right;
1837 } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
Jorim Jaggif081f062019-10-24 16:24:54 +02001838 pf.left = df.left = cf.left = vf.left = displayFrames.mStable.left;
Tiger Huang7c610aa2018-10-27 00:01:01 +08001839 }
1840 }
1841
Matthew Nga7f24bc2019-04-09 17:06:41 -07001842 // In case the navigation bar is on the bottom, we use the frame height instead of the
1843 // regular height for the insets we send to the IME as we need some space to show
1844 // additional buttons in SystemUI when the IME is up.
1845 if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
1846 final int rotation = displayFrames.mRotation;
1847 final int uimode = mService.mPolicy.getUiMode();
1848 final int navHeightOffset = getNavigationBarFrameHeight(rotation, uimode)
1849 - getNavigationBarHeight(rotation, uimode);
1850 if (navHeightOffset > 0) {
1851 cf.bottom -= navHeightOffset;
1852 sf.bottom -= navHeightOffset;
1853 vf.bottom -= navHeightOffset;
1854 dcf.bottom -= navHeightOffset;
1855 }
1856 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001857
1858 // IM dock windows always go to the bottom of the screen.
1859 attrs.gravity = Gravity.BOTTOM;
1860 } else if (type == TYPE_VOICE_INTERACTION) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001861 df.set(displayFrames.mUnrestricted);
1862 pf.set(displayFrames.mUnrestricted);
1863 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
1864 cf.set(displayFrames.mDock);
1865 } else {
1866 cf.set(displayFrames.mContent);
1867 }
1868 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
1869 vf.set(displayFrames.mCurrent);
1870 } else {
1871 vf.set(cf);
1872 }
1873 } else if (type == TYPE_WALLPAPER) {
Jorim Jaggif081f062019-10-24 16:24:54 +02001874 layoutWallpaper(displayFrames, pf, df, cf);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001875 } else if (win == mStatusBar) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001876 df.set(displayFrames.mUnrestricted);
1877 pf.set(displayFrames.mUnrestricted);
1878 cf.set(displayFrames.mStable);
1879 vf.set(displayFrames.mStable);
1880
1881 if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
Tiger Huang7fe7f682019-10-26 01:11:23 +08001882 // cf.bottom should not be below the stable bottom, or the content might be obscured
1883 // by the navigation bar.
1884 if (cf.bottom > displayFrames.mContent.bottom) {
1885 cf.bottom = displayFrames.mContent.bottom;
1886 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001887 } else {
Tiger Huang7fe7f682019-10-26 01:11:23 +08001888 if (cf.bottom > displayFrames.mDock.bottom) {
1889 cf.bottom = displayFrames.mDock.bottom;
1890 }
1891 if (vf.bottom > displayFrames.mContent.bottom) {
1892 vf.bottom = displayFrames.mContent.bottom;
1893 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001894 }
1895 } else {
1896 dcf.set(displayFrames.mSystem);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001897 final boolean isAppWindow =
1898 type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW;
1899 final boolean topAtRest =
1900 win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
Jorim Jaggia2e648e2019-10-25 15:06:53 +02001901 if (isAppWindow && !topAtRest) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001902 if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
1903 && (fl & FLAG_FULLSCREEN) == 0
1904 && (fl & FLAG_TRANSLUCENT_STATUS) == 0
1905 && (fl & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
Jorim Jaggia6aabac2019-03-11 14:23:16 -07001906 && (pfl & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) == 0) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001907 // Ensure policy decor includes status bar
1908 dcf.top = displayFrames.mStable.top;
1909 }
1910 if ((fl & FLAG_TRANSLUCENT_NAVIGATION) == 0
1911 && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
Jorim Jaggia6aabac2019-03-11 14:23:16 -07001912 && (fl & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
1913 && (pfl & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) == 0) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001914 // Ensure policy decor includes navigation bar
1915 dcf.bottom = displayFrames.mStable.bottom;
1916 dcf.right = displayFrames.mStable.right;
1917 }
1918 }
1919
1920 if (layoutInScreen && layoutInsetDecor) {
1921 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
1922 + "): IN_SCREEN, INSET_DECOR");
1923 // This is the case for a normal activity window: we want it to cover all of the
1924 // screen space, and it can take care of moving its contents to account for screen
1925 // decorations that intrude into that space.
1926 if (attached != null) {
1927 // If this window is attached to another, our display
1928 // frame is the same as the one we are attached to.
Jorim Jaggif081f062019-10-24 16:24:54 +02001929 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, cf, vf,
Tiger Huang7c610aa2018-10-27 00:01:01 +08001930 displayFrames);
1931 } else {
1932 if (type == TYPE_STATUS_BAR_PANEL || type == TYPE_STATUS_BAR_SUB_PANEL) {
1933 // Status bar panels are the only windows who can go on top of the status
1934 // bar. They are protected by the STATUS_BAR_SERVICE permission, so they
1935 // have the same privileges as the status bar itself.
1936 //
1937 // However, they should still dodge the navigation bar if it exists.
1938
Jorim Jaggif081f062019-10-24 16:24:54 +02001939 pf.left = df.left = hasNavBar
Tiger Huang7c610aa2018-10-27 00:01:01 +08001940 ? displayFrames.mDock.left : displayFrames.mUnrestricted.left;
Jorim Jaggif081f062019-10-24 16:24:54 +02001941 pf.top = df.top = displayFrames.mUnrestricted.top;
1942 pf.right = df.right = hasNavBar
Tiger Huang7c610aa2018-10-27 00:01:01 +08001943 ? displayFrames.mRestricted.right
1944 : displayFrames.mUnrestricted.right;
Jorim Jaggif081f062019-10-24 16:24:54 +02001945 pf.bottom = df.bottom = hasNavBar
Tiger Huang7c610aa2018-10-27 00:01:01 +08001946 ? displayFrames.mRestricted.bottom
1947 : displayFrames.mUnrestricted.bottom;
1948
1949 if (DEBUG_LAYOUT) Slog.v(TAG, "Laying out status bar window: " + pf);
Jorim Jaggid6490572019-04-16 14:57:56 +02001950 } else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
Tiger Huang7c610aa2018-10-27 00:01:01 +08001951 && (type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW
Charles Chen64172bb2019-04-22 17:30:29 +08001952 || type == TYPE_VOLUME_OVERLAY
1953 || type == TYPE_KEYGUARD_DIALOG)) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001954 // Asking for layout as if the nav bar is hidden, lets the application
1955 // extend into the unrestricted overscan screen area. We only do this for
1956 // application windows and certain system windows to ensure no window that
1957 // can be above the nav bar can do this.
Jorim Jaggif081f062019-10-24 16:24:54 +02001958 df.set(displayFrames.mUnrestricted);
1959 pf.set(displayFrames.mUnrestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001960 } else {
Jorim Jaggif081f062019-10-24 16:24:54 +02001961 df.set(displayFrames.mRestricted);
1962 pf.set(displayFrames.mRestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08001963 }
1964
1965 if ((fl & FLAG_FULLSCREEN) == 0) {
1966 if (win.isVoiceInteraction()) {
1967 cf.set(displayFrames.mVoiceContent);
1968 } else {
Jorim Jaggi648e5882019-01-24 13:24:02 +01001969 // IME Insets are handled on the client for ADJUST_RESIZE in the new
1970 // insets world
1971 if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_NONE
1972 || adjust != SOFT_INPUT_ADJUST_RESIZE) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001973 cf.set(displayFrames.mDock);
1974 } else {
1975 cf.set(displayFrames.mContent);
1976 }
1977 }
1978 } else {
1979 // Full screen windows are always given a layout that is as if the status
1980 // bar and other transient decors are gone. This is to avoid bad states when
1981 // moving from a window that is not hiding the status bar to one that is.
1982 cf.set(displayFrames.mRestricted);
1983 }
1984 applyStableConstraints(sysUiFl, fl, cf, displayFrames);
1985 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
1986 vf.set(displayFrames.mCurrent);
1987 } else {
1988 vf.set(cf);
1989 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08001990 }
1991 } else if (layoutInScreen || (sysUiFl
1992 & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
Jorim Jaggid6490572019-04-16 14:57:56 +02001993 | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08001994 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
1995 + "): IN_SCREEN");
1996 // A window that has requested to fill the entire screen just
1997 // gets everything, period.
1998 if (type == TYPE_STATUS_BAR_PANEL || type == TYPE_STATUS_BAR_SUB_PANEL) {
1999 cf.set(displayFrames.mUnrestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002000 df.set(displayFrames.mUnrestricted);
2001 pf.set(displayFrames.mUnrestricted);
2002 if (hasNavBar) {
Jorim Jaggif081f062019-10-24 16:24:54 +02002003 pf.left = df.left = cf.left = displayFrames.mDock.left;
2004 pf.right = df.right = cf.right = displayFrames.mRestricted.right;
2005 pf.bottom = df.bottom = cf.bottom =
Tiger Huang7c610aa2018-10-27 00:01:01 +08002006 displayFrames.mRestricted.bottom;
2007 }
2008 if (DEBUG_LAYOUT) Slog.v(TAG, "Laying out IN_SCREEN status bar window: " + pf);
2009 } else if (type == TYPE_NAVIGATION_BAR || type == TYPE_NAVIGATION_BAR_PANEL) {
2010 // The navigation bar has Real Ultimate Power.
Tiger Huang7c610aa2018-10-27 00:01:01 +08002011 df.set(displayFrames.mUnrestricted);
2012 pf.set(displayFrames.mUnrestricted);
2013 if (DEBUG_LAYOUT) Slog.v(TAG, "Laying out navigation bar window: " + pf);
2014 } else if ((type == TYPE_SECURE_SYSTEM_OVERLAY || type == TYPE_SCREENSHOT)
2015 && ((fl & FLAG_FULLSCREEN) != 0)) {
2016 // Fullscreen secure system overlays get what they ask for. Screenshot region
2017 // selection overlay should also expand to full screen.
Jorim Jaggif081f062019-10-24 16:24:54 +02002018 cf.set(displayFrames.mUnrestricted);
2019 df.set(displayFrames.mUnrestricted);
2020 pf.set(displayFrames.mUnrestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002021 } else if (type == TYPE_BOOT_PROGRESS) {
2022 // Boot progress screen always covers entire display.
Jorim Jaggif081f062019-10-24 16:24:54 +02002023 cf.set(displayFrames.mUnrestricted);
2024 df.set(displayFrames.mUnrestricted);
2025 pf.set(displayFrames.mUnrestricted);
Jorim Jaggid6490572019-04-16 14:57:56 +02002026 } else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
Tiger Huang7c610aa2018-10-27 00:01:01 +08002027 && (type == TYPE_STATUS_BAR
2028 || type == TYPE_TOAST
2029 || type == TYPE_DOCK_DIVIDER
2030 || type == TYPE_VOICE_INTERACTION_STARTING
2031 || (type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW))) {
2032 // Asking for layout as if the nav bar is hidden, lets the
2033 // application extend into the unrestricted screen area. We
2034 // only do this for application windows (or toasts) to ensure no window that
2035 // can be above the nav bar can do this.
2036 // XXX This assumes that an app asking for this will also
2037 // ask for layout in only content. We can't currently figure out
2038 // what the screen would be if only laying out to hide the nav bar.
2039 cf.set(displayFrames.mUnrestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002040 df.set(displayFrames.mUnrestricted);
2041 pf.set(displayFrames.mUnrestricted);
2042 } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002043 df.set(displayFrames.mRestricted);
2044 pf.set(displayFrames.mRestricted);
Jorim Jaggi648e5882019-01-24 13:24:02 +01002045
2046 // IME Insets are handled on the client for ADJUST_RESIZE in the new insets
2047 // world
2048 if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_NONE
2049 || adjust != SOFT_INPUT_ADJUST_RESIZE) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002050 cf.set(displayFrames.mDock);
2051 } else {
2052 cf.set(displayFrames.mContent);
2053 }
2054 } else {
2055 cf.set(displayFrames.mRestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002056 df.set(displayFrames.mRestricted);
2057 pf.set(displayFrames.mRestricted);
2058 }
2059
2060 applyStableConstraints(sysUiFl, fl, cf, displayFrames);
2061
2062 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
2063 vf.set(displayFrames.mCurrent);
2064 } else {
2065 vf.set(cf);
2066 }
2067 } else if (attached != null) {
2068 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
2069 + "): attached to " + attached);
2070 // A child window should be placed inside of the same visible
2071 // frame that its parent had.
Jorim Jaggif081f062019-10-24 16:24:54 +02002072 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, cf, vf,
Tiger Huang7c610aa2018-10-27 00:01:01 +08002073 displayFrames);
2074 } else {
2075 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
2076 + "): normal window");
2077 // Otherwise, a normal window must be placed inside the content
2078 // of all screen decorations.
2079 if (type == TYPE_STATUS_BAR_PANEL) {
2080 // Status bar panels can go on
2081 // top of the status bar. They are protected by the STATUS_BAR_SERVICE
2082 // permission, so they have the same privileges as the status bar itself.
2083 cf.set(displayFrames.mRestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002084 df.set(displayFrames.mRestricted);
2085 pf.set(displayFrames.mRestricted);
Vishnu Nair9ccb1d22019-03-20 16:32:44 +00002086 } else if (type == TYPE_TOAST || type == TYPE_SYSTEM_ALERT) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002087 // These dialogs are stable to interim decor changes.
2088 cf.set(displayFrames.mStable);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002089 df.set(displayFrames.mStable);
2090 pf.set(displayFrames.mStable);
2091 } else {
2092 pf.set(displayFrames.mContent);
2093 if (win.isVoiceInteraction()) {
2094 cf.set(displayFrames.mVoiceContent);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002095 df.set(displayFrames.mVoiceContent);
2096 } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
2097 cf.set(displayFrames.mDock);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002098 df.set(displayFrames.mDock);
2099 } else {
2100 cf.set(displayFrames.mContent);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002101 df.set(displayFrames.mContent);
2102 }
2103 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
2104 vf.set(displayFrames.mCurrent);
2105 } else {
2106 vf.set(cf);
2107 }
2108 }
2109 }
2110 }
2111
2112 final int cutoutMode = attrs.layoutInDisplayCutoutMode;
2113 final boolean attachedInParent = attached != null && !layoutInScreen;
2114 final boolean requestedHideNavigation =
2115 (requestedSysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
2116
2117 // TYPE_BASE_APPLICATION windows are never considered floating here because they don't get
2118 // cropped / shifted to the displayFrame in WindowState.
2119 final boolean floatingInScreenWindow = !attrs.isFullscreen() && layoutInScreen
2120 && type != TYPE_BASE_APPLICATION;
2121
2122 // Ensure that windows with a DEFAULT or NEVER display cutout mode are laid out in
2123 // the cutout safe zone.
Arthur Hung20479922019-02-27 17:13:22 +08002124 if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002125 final Rect displayCutoutSafeExceptMaybeBars = sTmpDisplayCutoutSafeExceptMaybeBarsRect;
2126 displayCutoutSafeExceptMaybeBars.set(displayFrames.mDisplayCutoutSafe);
2127 if (layoutInScreen && layoutInsetDecor && !requestedFullscreen
2128 && cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT) {
2129 // At the top we have the status bar, so apps that are
2130 // LAYOUT_IN_SCREEN | LAYOUT_INSET_DECOR but not FULLSCREEN
2131 // already expect that there's an inset there and we don't need to exclude
2132 // the window from that area.
2133 displayCutoutSafeExceptMaybeBars.top = Integer.MIN_VALUE;
2134 }
2135 if (layoutInScreen && layoutInsetDecor && !requestedHideNavigation
2136 && cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT) {
2137 // Same for the navigation bar.
2138 switch (mNavigationBarPosition) {
2139 case NAV_BAR_BOTTOM:
2140 displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
2141 break;
2142 case NAV_BAR_RIGHT:
2143 displayCutoutSafeExceptMaybeBars.right = Integer.MAX_VALUE;
2144 break;
2145 case NAV_BAR_LEFT:
2146 displayCutoutSafeExceptMaybeBars.left = Integer.MIN_VALUE;
2147 break;
2148 }
2149 }
2150 if (type == TYPE_INPUT_METHOD && mNavigationBarPosition == NAV_BAR_BOTTOM) {
2151 // The IME can always extend under the bottom cutout if the navbar is there.
2152 displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
2153 }
2154 // Windows that are attached to a parent and laid out in said parent already avoid
2155 // the cutout according to that parent and don't need to be further constrained.
2156 // Floating IN_SCREEN windows get what they ask for and lay out in the full screen.
2157 // They will later be cropped or shifted using the displayFrame in WindowState,
2158 // which prevents overlap with the DisplayCutout.
2159 if (!attachedInParent && !floatingInScreenWindow) {
2160 sTmpRect.set(pf);
2161 pf.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
2162 windowFrames.setParentFrameWasClippedByDisplayCutout(!sTmpRect.equals(pf));
2163 }
2164 // Make sure that NO_LIMITS windows clipped to the display don't extend under the
2165 // cutout.
2166 df.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
2167 }
2168
2169 // Content should never appear in the cutout.
2170 cf.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
2171
2172 // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
2173 // Also, we don't allow windows in multi-window mode to extend out of the screen.
2174 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && type != TYPE_SYSTEM_ERROR
Evan Rosky4fb1e912019-03-06 13:54:43 -08002175 && !win.inMultiWindowMode()) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002176 df.left = df.top = -10000;
2177 df.right = df.bottom = 10000;
2178 if (type != TYPE_WALLPAPER) {
Jorim Jaggif081f062019-10-24 16:24:54 +02002179 cf.left = cf.top = vf.left = vf.top = -10000;
2180 cf.right = cf.bottom = vf.right = vf.bottom = 10000;
Tiger Huang7c610aa2018-10-27 00:01:01 +08002181 }
2182 }
2183
2184 if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
2185 + ": sim=#" + Integer.toHexString(sim)
2186 + " attach=" + attached + " type=" + type
2187 + String.format(" flags=0x%08x", fl)
2188 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
Tiger Huang7c610aa2018-10-27 00:01:01 +08002189 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
2190 + " dcf=" + dcf.toShortString()
Jorim Jaggif081f062019-10-24 16:24:54 +02002191 + " sf=" + sf.toShortString());
Tiger Huang7c610aa2018-10-27 00:01:01 +08002192
2193 if (!sTmpLastParentFrame.equals(pf)) {
2194 windowFrames.setContentChanged(true);
2195 }
2196
2197 win.computeFrameLw();
2198 // Dock windows carve out the bottom of the screen, so normal windows
2199 // can't appear underneath them.
2200 if (type == TYPE_INPUT_METHOD && win.isVisibleLw()
2201 && !win.getGivenInsetsPendingLw()) {
2202 offsetInputMethodWindowLw(win, displayFrames);
2203 }
2204 if (type == TYPE_VOICE_INTERACTION && win.isVisibleLw()
2205 && !win.getGivenInsetsPendingLw()) {
2206 offsetVoiceInputWindowLw(win, displayFrames);
2207 }
2208 }
2209
Jorim Jaggif081f062019-10-24 16:24:54 +02002210 private void layoutWallpaper(DisplayFrames displayFrames, Rect pf, Rect df, Rect cf) {
2211 // The wallpaper has Real Ultimate Power
2212 df.set(displayFrames.mUnrestricted);
2213 pf.set(displayFrames.mUnrestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002214 cf.set(displayFrames.mUnrestricted);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002215 }
2216
2217 private void offsetInputMethodWindowLw(WindowState win, DisplayFrames displayFrames) {
2218 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
2219 top += win.getGivenContentInsetsLw().top;
2220 displayFrames.mContent.bottom = Math.min(displayFrames.mContent.bottom, top);
2221 displayFrames.mVoiceContent.bottom = Math.min(displayFrames.mVoiceContent.bottom, top);
2222 top = win.getVisibleFrameLw().top;
2223 top += win.getGivenVisibleInsetsLw().top;
2224 displayFrames.mCurrent.bottom = Math.min(displayFrames.mCurrent.bottom, top);
2225 if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
2226 + displayFrames.mDock.bottom + " mContentBottom="
2227 + displayFrames.mContent.bottom + " mCurBottom=" + displayFrames.mCurrent.bottom);
2228 }
2229
2230 private void offsetVoiceInputWindowLw(WindowState win, DisplayFrames displayFrames) {
2231 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
2232 top += win.getGivenContentInsetsLw().top;
2233 displayFrames.mVoiceContent.bottom = Math.min(displayFrames.mVoiceContent.bottom, top);
2234 }
2235
Riddle Hsuccf09402019-08-13 00:33:06 +08002236 WindowState getTopFullscreenOpaqueWindow() {
2237 return mTopFullscreenOpaqueWindowState;
2238 }
2239
2240 boolean isTopLayoutFullscreen() {
2241 return mTopIsFullscreen;
2242 }
2243
Tiger Huang7c610aa2018-10-27 00:01:01 +08002244 /**
2245 * Called following layout of all windows before each window has policy applied.
2246 */
2247 public void beginPostLayoutPolicyLw() {
2248 mTopFullscreenOpaqueWindowState = null;
2249 mTopFullscreenOpaqueOrDimmingWindowState = null;
2250 mTopDockedOpaqueWindowState = null;
2251 mTopDockedOpaqueOrDimmingWindowState = null;
2252 mForceStatusBar = false;
2253 mForceStatusBarFromKeyguard = false;
2254 mForceStatusBarTransparent = false;
2255 mForcingShowNavBar = false;
2256 mForcingShowNavBarLayer = -1;
2257
2258 mAllowLockscreenWhenOn = false;
2259 mShowingDream = false;
2260 mWindowSleepTokenNeeded = false;
HEO SEUNG22d3ec22019-05-30 20:28:53 +09002261 mIsFreeformWindowOverlappingWithNavBar = false;
Tiger Huang7c610aa2018-10-27 00:01:01 +08002262 }
2263
2264 /**
2265 * Called following layout of all window to apply policy to each window.
2266 *
2267 * @param win The window being positioned.
2268 * @param attrs The LayoutParams of the window.
2269 * @param attached For sub-windows, the window it is attached to. Otherwise null.
2270 */
2271 public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
2272 WindowState attached, WindowState imeTarget) {
2273 final boolean affectsSystemUi = win.canAffectSystemUiFlags();
2274 if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": affectsSystemUi=" + affectsSystemUi);
2275 mService.mPolicy.applyKeyguardPolicyLw(win, imeTarget);
2276 final int fl = PolicyControl.getWindowFlags(win, attrs);
2277 if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi
2278 && attrs.type == TYPE_INPUT_METHOD) {
2279 mForcingShowNavBar = true;
2280 mForcingShowNavBarLayer = win.getSurfaceLayer();
2281 }
2282 if (attrs.type == TYPE_STATUS_BAR) {
2283 if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
2284 mForceStatusBarFromKeyguard = true;
2285 }
2286 if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
2287 mForceStatusBarTransparent = true;
2288 }
2289 }
2290
2291 boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
2292 && attrs.type < FIRST_SYSTEM_WINDOW;
2293 final int windowingMode = win.getWindowingMode();
2294 final boolean inFullScreenOrSplitScreenSecondaryWindowingMode =
2295 windowingMode == WINDOWING_MODE_FULLSCREEN
2296 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
2297 if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi) {
2298 if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
2299 mForceStatusBar = true;
2300 }
2301 if (attrs.type == TYPE_DREAM) {
2302 // If the lockscreen was showing when the dream started then wait
2303 // for the dream to draw before hiding the lockscreen.
2304 if (!mDreamingLockscreen
2305 || (win.isVisibleLw() && win.hasDrawnLw())) {
2306 mShowingDream = true;
2307 appWindow = true;
2308 }
2309 }
2310
2311 // For app windows that are not attached, we decide if all windows in the app they
2312 // represent should be hidden or if we should hide the lockscreen. For attached app
2313 // windows we defer the decision to the window it is attached to.
2314 if (appWindow && attached == null) {
2315 if (attrs.isFullscreen() && inFullScreenOrSplitScreenSecondaryWindowingMode) {
2316 if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
2317 mTopFullscreenOpaqueWindowState = win;
2318 if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
2319 mTopFullscreenOpaqueOrDimmingWindowState = win;
2320 }
2321 if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
2322 mAllowLockscreenWhenOn = true;
2323 }
2324 }
2325 }
2326 }
2327
2328 // Voice interaction overrides both top fullscreen and top docked.
Jorim Jaggi50150152019-03-27 23:08:58 +01002329 if (affectsSystemUi && attrs.type == TYPE_VOICE_INTERACTION) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002330 if (mTopFullscreenOpaqueWindowState == null) {
2331 mTopFullscreenOpaqueWindowState = win;
2332 if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
2333 mTopFullscreenOpaqueOrDimmingWindowState = win;
2334 }
2335 }
2336 if (mTopDockedOpaqueWindowState == null) {
2337 mTopDockedOpaqueWindowState = win;
2338 if (mTopDockedOpaqueOrDimmingWindowState == null) {
2339 mTopDockedOpaqueOrDimmingWindowState = win;
2340 }
2341 }
2342 }
2343
2344 // Keep track of the window if it's dimming but not necessarily fullscreen.
2345 if (mTopFullscreenOpaqueOrDimmingWindowState == null && affectsSystemUi
2346 && win.isDimming() && inFullScreenOrSplitScreenSecondaryWindowingMode) {
2347 mTopFullscreenOpaqueOrDimmingWindowState = win;
2348 }
2349
2350 // We need to keep track of the top "fullscreen" opaque window for the docked stack
2351 // separately, because both the "real fullscreen" opaque window and the one for the docked
2352 // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
2353 if (mTopDockedOpaqueWindowState == null && affectsSystemUi && appWindow && attached == null
2354 && attrs.isFullscreen() && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
2355 mTopDockedOpaqueWindowState = win;
2356 if (mTopDockedOpaqueOrDimmingWindowState == null) {
2357 mTopDockedOpaqueOrDimmingWindowState = win;
2358 }
2359 }
2360
HEO SEUNG22d3ec22019-05-30 20:28:53 +09002361 // Check if the freeform window overlaps with the navigation bar area.
2362 final WindowState navBarWin = hasNavigationBar() ? mNavigationBar : null;
2363 if (!mIsFreeformWindowOverlappingWithNavBar && win.inFreeformWindowingMode()
2364 && isOverlappingWithNavBar(win, navBarWin)) {
2365 mIsFreeformWindowOverlappingWithNavBar = true;
2366 }
2367
Tiger Huang7c610aa2018-10-27 00:01:01 +08002368 // Also keep track of any windows that are dimming but not necessarily fullscreen in the
2369 // docked stack.
2370 if (mTopDockedOpaqueOrDimmingWindowState == null && affectsSystemUi && win.isDimming()
2371 && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
2372 mTopDockedOpaqueOrDimmingWindowState = win;
2373 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002374 }
2375
2376 /**
2377 * Called following layout of all windows and after policy has been applied
2378 * to each window. If in this function you do
2379 * something that may have modified the animation state of another window,
2380 * be sure to return non-zero in order to perform another pass through layout.
2381 *
2382 * @return Return any bit set of
2383 * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_LAYOUT},
2384 * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_CONFIG},
2385 * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_WALLPAPER}, or
2386 * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_ANIM}.
2387 */
2388 public int finishPostLayoutPolicyLw() {
2389 int changes = 0;
2390 boolean topIsFullscreen = false;
2391
2392 // If we are not currently showing a dream then remember the current
2393 // lockscreen state. We will use this to determine whether the dream
2394 // started while the lockscreen was showing and remember this state
2395 // while the dream is showing.
2396 if (!mShowingDream) {
2397 mDreamingLockscreen = mService.mPolicy.isKeyguardShowingAndNotOccluded();
2398 if (mDreamingSleepTokenNeeded) {
2399 mDreamingSleepTokenNeeded = false;
2400 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
2401 }
2402 } else {
2403 if (!mDreamingSleepTokenNeeded) {
2404 mDreamingSleepTokenNeeded = true;
2405 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget();
2406 }
2407 }
2408
2409 if (mStatusBar != null) {
2410 if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
2411 + " forcefkg=" + mForceStatusBarFromKeyguard
2412 + " top=" + mTopFullscreenOpaqueWindowState);
2413 boolean shouldBeTransparent = mForceStatusBarTransparent
2414 && !mForceStatusBar
2415 && !mForceStatusBarFromKeyguard;
2416 if (!shouldBeTransparent) {
2417 mStatusBarController.setShowTransparent(false /* transparent */);
2418 } else if (!mStatusBar.isVisibleLw()) {
2419 mStatusBarController.setShowTransparent(true /* transparent */);
2420 }
2421
2422 boolean statusBarForcesShowingNavigation =
2423 (mStatusBar.getAttrs().privateFlags
2424 & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0;
2425 boolean topAppHidesStatusBar = topAppHidesStatusBar();
2426 if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
2427 || statusBarForcesShowingNavigation) {
2428 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
2429 if (mStatusBarController.setBarShowingLw(true)) {
2430 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2431 }
2432 // Maintain fullscreen layout until incoming animation is complete.
2433 topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
2434 // Transient status bar is not allowed if status bar is on lockscreen or status bar
2435 // is expecting the navigation keys from the user.
2436 if ((mForceStatusBarFromKeyguard || statusBarForcesShowingNavigation)
2437 && mStatusBarController.isTransientShowing()) {
2438 mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
2439 mLastSystemUiFlags, mLastSystemUiFlags);
2440 }
2441 } else if (mTopFullscreenOpaqueWindowState != null) {
2442 topIsFullscreen = topAppHidesStatusBar;
2443 // The subtle difference between the window for mTopFullscreenOpaqueWindowState
2444 // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
2445 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the
2446 // case though.
2447 if (mStatusBarController.isTransientShowing()) {
2448 if (mStatusBarController.setBarShowingLw(true)) {
2449 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2450 }
2451 } else if (topIsFullscreen
Tiger Huang7c610aa2018-10-27 00:01:01 +08002452 && !mDisplayContent.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
2453 if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
2454 if (mStatusBarController.setBarShowingLw(false)) {
2455 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2456 } else {
2457 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
2458 }
2459 } else {
2460 if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
2461 if (mStatusBarController.setBarShowingLw(true)) {
2462 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2463 }
2464 topAppHidesStatusBar = false;
2465 }
2466 }
2467 mStatusBarController.setTopAppHidesStatusBar(topAppHidesStatusBar);
2468 }
2469
2470 if (mTopIsFullscreen != topIsFullscreen) {
2471 if (!topIsFullscreen) {
2472 // Force another layout when status bar becomes fully shown.
2473 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2474 }
2475 mTopIsFullscreen = topIsFullscreen;
2476 }
2477
2478 if ((updateSystemUiVisibilityLw() & SYSTEM_UI_CHANGING_LAYOUT) != 0) {
2479 // If the navigation bar has been hidden or shown, we need to do another
2480 // layout pass to update that window.
2481 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2482 }
2483
2484 if (mShowingDream != mLastShowingDream) {
2485 mLastShowingDream = mShowingDream;
2486 mService.notifyShowingDreamChanged();
2487 }
2488
2489 updateWindowSleepToken();
2490
2491 mService.mPolicy.setAllowLockscreenWhenOn(getDisplayId(), mAllowLockscreenWhenOn);
2492 return changes;
2493 }
2494
2495 private void updateWindowSleepToken() {
2496 if (mWindowSleepTokenNeeded && !mLastWindowSleepTokenNeeded) {
2497 mHandler.removeCallbacks(mReleaseSleepTokenRunnable);
2498 mHandler.post(mAcquireSleepTokenRunnable);
2499 } else if (!mWindowSleepTokenNeeded && mLastWindowSleepTokenNeeded) {
2500 mHandler.removeCallbacks(mAcquireSleepTokenRunnable);
2501 mHandler.post(mReleaseSleepTokenRunnable);
2502 }
2503 mLastWindowSleepTokenNeeded = mWindowSleepTokenNeeded;
2504 }
2505
2506 /**
2507 * @return Whether the top app should hide the statusbar based on the top fullscreen opaque
2508 * window.
2509 */
2510 private boolean topAppHidesStatusBar() {
hyok.kim332ccfc2019-07-02 15:39:43 +09002511 if (mTopFullscreenOpaqueWindowState == null || mForceShowSystemBars) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002512 return false;
2513 }
2514 final int fl = PolicyControl.getWindowFlags(null,
2515 mTopFullscreenOpaqueWindowState.getAttrs());
Adam Pardyl8c2d19c2019-09-16 17:15:38 +02002516 if (WindowManagerDebugConfig.DEBUG) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002517 Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw());
2518 Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
2519 + " lp.flags=0x" + Integer.toHexString(fl));
2520 }
2521 return (fl & LayoutParams.FLAG_FULLSCREEN) != 0
2522 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
2523 }
2524
2525 /**
Winson Chungda20fec2019-04-10 12:19:59 -07002526 * Called when the user is switched.
2527 */
2528 public void switchUser() {
2529 updateCurrentUserResources();
2530 }
2531
2532 /**
Tiger Huang7c610aa2018-10-27 00:01:01 +08002533 * Called when the resource overlays change.
2534 */
2535 public void onOverlayChangedLw() {
Winson Chungda20fec2019-04-10 12:19:59 -07002536 updateCurrentUserResources();
Tiger Huang7c610aa2018-10-27 00:01:01 +08002537 onConfigurationChanged();
Jeff Changb0a061e2019-03-11 11:39:54 +08002538 mSystemGestures.onConfigurationChanged();
Tiger Huang7c610aa2018-10-27 00:01:01 +08002539 }
2540
2541 /**
2542 * Called when the configuration has changed, and it's safe to load new values from resources.
2543 */
2544 public void onConfigurationChanged() {
2545 final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation();
2546
Winson Chungda20fec2019-04-10 12:19:59 -07002547 final Resources res = getCurrentUserResources();
Tiger Huang7c610aa2018-10-27 00:01:01 +08002548 final int portraitRotation = displayRotation.getPortraitRotation();
2549 final int upsideDownRotation = displayRotation.getUpsideDownRotation();
2550 final int landscapeRotation = displayRotation.getLandscapeRotation();
2551 final int seascapeRotation = displayRotation.getSeascapeRotation();
Matthew Nga7f24bc2019-04-09 17:06:41 -07002552 final int uiMode = mService.mPolicy.getUiMode();
Tiger Huang7c610aa2018-10-27 00:01:01 +08002553
Louis Changfc64c832018-12-04 11:38:26 +08002554 if (hasStatusBar()) {
2555 mStatusBarHeightForRotation[portraitRotation] =
2556 mStatusBarHeightForRotation[upsideDownRotation] =
2557 res.getDimensionPixelSize(R.dimen.status_bar_height_portrait);
2558 mStatusBarHeightForRotation[landscapeRotation] =
2559 mStatusBarHeightForRotation[seascapeRotation] =
2560 res.getDimensionPixelSize(R.dimen.status_bar_height_landscape);
2561 } else {
2562 mStatusBarHeightForRotation[portraitRotation] =
2563 mStatusBarHeightForRotation[upsideDownRotation] =
2564 mStatusBarHeightForRotation[landscapeRotation] =
2565 mStatusBarHeightForRotation[seascapeRotation] = 0;
2566 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002567
2568 // Height of the navigation bar when presented horizontally at bottom
2569 mNavigationBarHeightForRotationDefault[portraitRotation] =
2570 mNavigationBarHeightForRotationDefault[upsideDownRotation] =
2571 res.getDimensionPixelSize(R.dimen.navigation_bar_height);
2572 mNavigationBarHeightForRotationDefault[landscapeRotation] =
2573 mNavigationBarHeightForRotationDefault[seascapeRotation] =
2574 res.getDimensionPixelSize(R.dimen.navigation_bar_height_landscape);
2575
Matthew Nga7f24bc2019-04-09 17:06:41 -07002576 // Height of the navigation bar frame when presented horizontally at bottom
2577 mNavigationBarFrameHeightForRotationDefault[portraitRotation] =
2578 mNavigationBarFrameHeightForRotationDefault[upsideDownRotation] =
2579 res.getDimensionPixelSize(R.dimen.navigation_bar_frame_height);
2580 mNavigationBarFrameHeightForRotationDefault[landscapeRotation] =
2581 mNavigationBarFrameHeightForRotationDefault[seascapeRotation] =
2582 res.getDimensionPixelSize(R.dimen.navigation_bar_frame_height_landscape);
2583
Tiger Huang7c610aa2018-10-27 00:01:01 +08002584 // Width of the navigation bar when presented vertically along one side
2585 mNavigationBarWidthForRotationDefault[portraitRotation] =
2586 mNavigationBarWidthForRotationDefault[upsideDownRotation] =
2587 mNavigationBarWidthForRotationDefault[landscapeRotation] =
2588 mNavigationBarWidthForRotationDefault[seascapeRotation] =
2589 res.getDimensionPixelSize(R.dimen.navigation_bar_width);
2590
2591 if (ALTERNATE_CAR_MODE_NAV_SIZE) {
2592 // Height of the navigation bar when presented horizontally at bottom
2593 mNavigationBarHeightForRotationInCarMode[portraitRotation] =
2594 mNavigationBarHeightForRotationInCarMode[upsideDownRotation] =
2595 res.getDimensionPixelSize(R.dimen.navigation_bar_height_car_mode);
2596 mNavigationBarHeightForRotationInCarMode[landscapeRotation] =
2597 mNavigationBarHeightForRotationInCarMode[seascapeRotation] =
2598 res.getDimensionPixelSize(R.dimen.navigation_bar_height_landscape_car_mode);
2599
2600 // Width of the navigation bar when presented vertically along one side
2601 mNavigationBarWidthForRotationInCarMode[portraitRotation] =
2602 mNavigationBarWidthForRotationInCarMode[upsideDownRotation] =
2603 mNavigationBarWidthForRotationInCarMode[landscapeRotation] =
2604 mNavigationBarWidthForRotationInCarMode[seascapeRotation] =
2605 res.getDimensionPixelSize(R.dimen.navigation_bar_width_car_mode);
2606 }
2607
Winson Chung4723b4e2019-03-25 16:49:36 -07002608 mNavBarOpacityMode = res.getInteger(R.integer.config_navBarOpacityMode);
Adrian Roos11dfd272019-03-25 19:21:26 +01002609 mSideGestureInset = res.getDimensionPixelSize(R.dimen.config_backGestureInset);
2610 mNavigationBarLetsThroughTaps = res.getBoolean(R.bool.config_navBarTapThrough);
Winson Chung36941632019-04-19 15:21:38 -07002611 mNavigationBarAlwaysShowOnSideGesture =
2612 res.getBoolean(R.bool.config_navBarAlwaysShowOnSideEdgeGesture);
Winson Chung4723b4e2019-03-25 16:49:36 -07002613
Matthew Nga7f24bc2019-04-09 17:06:41 -07002614 // This should calculate how much above the frame we accept gestures.
Sunny Goyalb5e5bcb2019-05-22 14:28:44 -07002615 mBottomGestureAdditionalInset =
Matthew Nga7f24bc2019-04-09 17:06:41 -07002616 res.getDimensionPixelSize(R.dimen.navigation_bar_gesture_height)
Sunny Goyalb5e5bcb2019-05-22 14:28:44 -07002617 - getNavigationBarFrameHeight(portraitRotation, uiMode);
Adrian Roos11dfd272019-03-25 19:21:26 +01002618
Winson Chung4723b4e2019-03-25 16:49:36 -07002619 updateConfigurationAndScreenSizeDependentBehaviors();
2620 }
2621
2622 void updateConfigurationAndScreenSizeDependentBehaviors() {
Winson Chungda20fec2019-04-10 12:19:59 -07002623 final Resources res = getCurrentUserResources();
Winson Chung4723b4e2019-03-25 16:49:36 -07002624 mNavigationBarCanMove =
2625 mDisplayContent.mBaseDisplayWidth != mDisplayContent.mBaseDisplayHeight
2626 && res.getBoolean(R.bool.config_navBarCanMove);
Riddle Hsuccf09402019-08-13 00:33:06 +08002627 mDisplayContent.getDisplayRotation().updateUserDependentConfiguration(res);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002628 }
2629
Winson Chungda20fec2019-04-10 12:19:59 -07002630 /**
2631 * Updates the current user's resources to pick up any changes for the current user (including
2632 * overlay paths)
2633 */
2634 private void updateCurrentUserResources() {
2635 final int userId = mService.mAmInternal.getCurrentUserId();
2636 final Context uiContext = getSystemUiContext();
Winson Chung203e1522019-05-02 15:42:22 -07002637
2638 if (userId == UserHandle.USER_SYSTEM) {
2639 // Skip the (expensive) recreation of resources for the system user below and just
2640 // use the resources from the system ui context
2641 mCurrentUserResources = uiContext.getResources();
2642 return;
2643 }
2644
2645 // For non-system users, ensure that the resources are loaded from the current
2646 // user's package info (see ContextImpl.createDisplayContext)
Winson Chungda20fec2019-04-10 12:19:59 -07002647 final LoadedApk pi = ActivityThread.currentActivityThread().getPackageInfo(
2648 uiContext.getPackageName(), null, 0, userId);
Winson Chungda20fec2019-04-10 12:19:59 -07002649 mCurrentUserResources = ResourcesManager.getInstance().getResources(null,
2650 pi.getResDir(),
2651 null /* splitResDirs */,
2652 pi.getOverlayDirs(),
2653 pi.getApplicationInfo().sharedLibraryFiles,
2654 mDisplayContent.getDisplayId(),
2655 null /* overrideConfig */,
2656 uiContext.getResources().getCompatibilityInfo(),
2657 null /* classLoader */);
2658 }
2659
Tiger Huang7c610aa2018-10-27 00:01:01 +08002660 @VisibleForTesting
Winson Chungda20fec2019-04-10 12:19:59 -07002661 Resources getCurrentUserResources() {
2662 if (mCurrentUserResources == null) {
2663 updateCurrentUserResources();
2664 }
2665 return mCurrentUserResources;
2666 }
2667
2668 @VisibleForTesting
2669 Context getContext() {
2670 return mContext;
2671 }
2672
2673 private Context getSystemUiContext() {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002674 final Context uiContext = ActivityThread.currentActivityThread().getSystemUiContext();
2675 return mDisplayContent.isDefaultDisplay
2676 ? uiContext : uiContext.createDisplayContext(mDisplayContent.getDisplay());
2677 }
2678
2679 private int getNavigationBarWidth(int rotation, int uiMode) {
2680 if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2681 return mNavigationBarWidthForRotationInCarMode[rotation];
2682 } else {
2683 return mNavigationBarWidthForRotationDefault[rotation];
2684 }
2685 }
2686
Charles Chen3dedec32019-01-24 22:19:37 +08002687 void notifyDisplayReady() {
wilsonshih643bf132019-02-27 12:49:19 +08002688 mHandler.post(() -> {
2689 final int displayId = getDisplayId();
2690 getStatusBarManagerInternal().onDisplayReady(displayId);
Felipe Leme34a861a2019-08-05 16:00:12 -07002691 final WallpaperManagerInternal wpMgr = LocalServices
2692 .getService(WallpaperManagerInternal.class);
2693 if (wpMgr != null) {
2694 wpMgr.onDisplayReady(displayId);
2695 }
wilsonshih643bf132019-02-27 12:49:19 +08002696 });
Charles Chen3dedec32019-01-24 22:19:37 +08002697 }
2698
Tiger Huang7c610aa2018-10-27 00:01:01 +08002699 /**
2700 * Return the display width available after excluding any screen
2701 * decorations that could never be removed in Honeycomb. That is, system bar or
2702 * button bar.
2703 */
2704 public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
2705 DisplayCutout displayCutout) {
2706 int width = fullWidth;
2707 if (hasNavigationBar()) {
Tiger Huang3d2b8982019-01-29 22:56:48 +08002708 final int navBarPosition = navigationBarPosition(fullWidth, fullHeight, rotation);
2709 if (navBarPosition == NAV_BAR_LEFT || navBarPosition == NAV_BAR_RIGHT) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002710 width -= getNavigationBarWidth(rotation, uiMode);
2711 }
2712 }
2713 if (displayCutout != null) {
2714 width -= displayCutout.getSafeInsetLeft() + displayCutout.getSafeInsetRight();
2715 }
2716 return width;
2717 }
2718
2719 private int getNavigationBarHeight(int rotation, int uiMode) {
2720 if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2721 return mNavigationBarHeightForRotationInCarMode[rotation];
2722 } else {
2723 return mNavigationBarHeightForRotationDefault[rotation];
2724 }
2725 }
2726
2727 /**
Matthew Nga7f24bc2019-04-09 17:06:41 -07002728 * Get the Navigation Bar Frame height. This dimension is the height of the navigation bar that
2729 * is used for spacing to show additional buttons on the navigation bar (such as the ime
2730 * switcher when ime is visible) while {@link #getNavigationBarHeight} is used for the visible
2731 * height that we send to the app as content insets that can be smaller.
2732 * <p>
2733 * In car mode it will return the same height as {@link #getNavigationBarHeight}
2734 *
2735 * @param rotation specifies rotation to return dimension from
2736 * @param uiMode to determine if in car mode
2737 * @return navigation bar frame height
2738 */
2739 private int getNavigationBarFrameHeight(int rotation, int uiMode) {
2740 if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2741 return mNavigationBarHeightForRotationInCarMode[rotation];
2742 } else {
2743 return mNavigationBarFrameHeightForRotationDefault[rotation];
2744 }
2745 }
2746
2747 /**
Tiger Huang7c610aa2018-10-27 00:01:01 +08002748 * Return the display height available after excluding any screen
2749 * decorations that could never be removed in Honeycomb. That is, system bar or
2750 * button bar.
2751 */
2752 public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
2753 DisplayCutout displayCutout) {
2754 int height = fullHeight;
2755 if (hasNavigationBar()) {
Tiger Huang3d2b8982019-01-29 22:56:48 +08002756 final int navBarPosition = navigationBarPosition(fullWidth, fullHeight, rotation);
2757 if (navBarPosition == NAV_BAR_BOTTOM) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08002758 height -= getNavigationBarHeight(rotation, uiMode);
2759 }
2760 }
2761 if (displayCutout != null) {
2762 height -= displayCutout.getSafeInsetTop() + displayCutout.getSafeInsetBottom();
2763 }
2764 return height;
2765 }
2766
2767 /**
2768 * Return the available screen width that we should report for the
2769 * configuration. This must be no larger than
2770 * {@link #getNonDecorDisplayWidth(int, int, int, int, DisplayCutout)}; it may be smaller
2771 * than that to account for more transient decoration like a status bar.
2772 */
2773 public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
2774 DisplayCutout displayCutout) {
2775 return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode, displayCutout);
2776 }
2777
2778 /**
2779 * Return the available screen height that we should report for the
2780 * configuration. This must be no larger than
2781 * {@link #getNonDecorDisplayHeight(int, int, int, int, DisplayCutout)}; it may be smaller
2782 * than that to account for more transient decoration like a status bar.
2783 */
2784 public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
2785 DisplayCutout displayCutout) {
2786 // There is a separate status bar at the top of the display. We don't count that as part
2787 // of the fixed decor, since it can hide; however, for purposes of configurations,
2788 // we do want to exclude it since applications can't generally use that part
2789 // of the screen.
2790 int statusBarHeight = mStatusBarHeightForRotation[rotation];
2791 if (displayCutout != null) {
2792 // If there is a cutout, it may already have accounted for some part of the status
2793 // bar height.
2794 statusBarHeight = Math.max(0, statusBarHeight - displayCutout.getSafeInsetTop());
2795 }
2796 return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayCutout)
2797 - statusBarHeight;
2798 }
2799
Tiger Huang43b8fc22019-04-26 11:49:29 +08002800 /**
2801 * Return corner radius in pixels that should be used on windows in order to cover the display.
2802 * The radius is only valid for built-in displays since the one who configures window corner
2803 * radius cannot know the corner radius of non-built-in display.
2804 */
2805 float getWindowCornerRadius() {
2806 return mDisplayContent.getDisplay().getType() == TYPE_BUILT_IN
2807 ? ScreenDecorationsUtils.getWindowCornerRadius(mContext.getResources()) : 0f;
2808 }
2809
Tiger Huang7c610aa2018-10-27 00:01:01 +08002810 boolean isShowingDreamLw() {
2811 return mShowingDream;
2812 }
2813
2814 /**
Riddle Hsu61987bc2019-04-03 13:08:47 +08002815 * Calculates the stable insets if we already have the non-decor insets.
2816 *
2817 * @param inOutInsets The known non-decor insets. It will be modified to stable insets.
2818 * @param rotation The current display rotation.
2819 */
2820 void convertNonDecorInsetsToStableInsets(Rect inOutInsets, int rotation) {
2821 inOutInsets.top = Math.max(inOutInsets.top, mStatusBarHeightForRotation[rotation]);
2822 }
2823
2824 /**
Tiger Huang7c610aa2018-10-27 00:01:01 +08002825 * Calculates the stable insets without running a layout.
2826 *
2827 * @param displayRotation the current display rotation
2828 * @param displayWidth the current display width
2829 * @param displayHeight the current display height
2830 * @param displayCutout the current display cutout
2831 * @param outInsets the insets to return
2832 */
2833 public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
2834 DisplayCutout displayCutout, Rect outInsets) {
2835 outInsets.setEmpty();
2836
2837 // Navigation bar and status bar.
2838 getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, displayCutout, outInsets);
Riddle Hsu61987bc2019-04-03 13:08:47 +08002839 convertNonDecorInsetsToStableInsets(outInsets, displayRotation);
Tiger Huang7c610aa2018-10-27 00:01:01 +08002840 }
2841
2842 /**
2843 * Calculates the insets for the areas that could never be removed in Honeycomb, i.e. system
2844 * bar or button bar. See {@link #getNonDecorDisplayWidth}.
2845 *
2846 * @param displayRotation the current display rotation
2847 * @param displayWidth the current display width
2848 * @param displayHeight the current display height
2849 * @param displayCutout the current display cutout
2850 * @param outInsets the insets to return
2851 */
2852 public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
2853 DisplayCutout displayCutout, Rect outInsets) {
2854 outInsets.setEmpty();
2855
2856 // Only navigation bar
2857 if (hasNavigationBar()) {
2858 final int uiMode = mService.mPolicy.getUiMode();
2859 int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
2860 if (position == NAV_BAR_BOTTOM) {
2861 outInsets.bottom = getNavigationBarHeight(displayRotation, uiMode);
2862 } else if (position == NAV_BAR_RIGHT) {
2863 outInsets.right = getNavigationBarWidth(displayRotation, uiMode);
2864 } else if (position == NAV_BAR_LEFT) {
2865 outInsets.left = getNavigationBarWidth(displayRotation, uiMode);
2866 }
2867 }
2868
2869 if (displayCutout != null) {
2870 outInsets.left += displayCutout.getSafeInsetLeft();
2871 outInsets.top += displayCutout.getSafeInsetTop();
2872 outInsets.right += displayCutout.getSafeInsetRight();
2873 outInsets.bottom += displayCutout.getSafeInsetBottom();
2874 }
2875 }
2876
Issei Suzukia5dbf522019-02-01 17:58:15 +01002877 /**
2878 * @see IWindowManager#setForwardedInsets
2879 */
2880 public void setForwardedInsets(@NonNull Insets forwardedInsets) {
2881 mForwardedInsets = forwardedInsets;
2882 }
2883
2884 @NonNull
2885 public Insets getForwardedInsets() {
2886 return mForwardedInsets;
2887 }
2888
Tiger Huang7c610aa2018-10-27 00:01:01 +08002889 @NavigationBarPosition
2890 int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
2891 if (navigationBarCanMove() && displayWidth > displayHeight) {
2892 if (displayRotation == Surface.ROTATION_270) {
2893 return NAV_BAR_LEFT;
2894 } else if (displayRotation == Surface.ROTATION_90) {
2895 return NAV_BAR_RIGHT;
2896 }
2897 }
2898 return NAV_BAR_BOTTOM;
2899 }
2900
2901 /**
2902 * @return The side of the screen where navigation bar is positioned.
2903 * @see WindowManagerPolicyConstants#NAV_BAR_LEFT
2904 * @see WindowManagerPolicyConstants#NAV_BAR_RIGHT
2905 * @see WindowManagerPolicyConstants#NAV_BAR_BOTTOM
2906 */
2907 @NavigationBarPosition
2908 public int getNavBarPosition() {
2909 return mNavigationBarPosition;
2910 }
2911
2912 /**
2913 * A new window has been focused.
2914 */
2915 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
2916 mFocusedWindow = newFocus;
2917 mLastFocusedWindow = lastFocus;
Issei Suzuki9f840c72018-12-07 15:09:30 -08002918 if (mDisplayContent.isDefaultDisplay) {
2919 mService.mPolicy.onDefaultDisplayFocusChangedLw(newFocus);
2920 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002921 if ((updateSystemUiVisibilityLw() & SYSTEM_UI_CHANGING_LAYOUT) != 0) {
2922 // If the navigation bar has been hidden or shown, we need to do another
2923 // layout pass to update that window.
2924 return FINISH_LAYOUT_REDO_LAYOUT;
2925 }
2926 return 0;
2927 }
2928
2929 /**
2930 * Return true if it is okay to perform animations for an app transition
2931 * that is about to occur. You may return false for this if, for example,
2932 * the dream window is currently displayed so the switch should happen
2933 * immediately.
2934 */
2935 public boolean allowAppAnimationsLw() {
2936 return !mShowingDream;
2937 }
2938
2939 private void updateDreamingSleepToken(boolean acquire) {
2940 if (acquire) {
2941 final int displayId = getDisplayId();
2942 if (mDreamingSleepToken == null) {
2943 mDreamingSleepToken = mService.mAtmInternal.acquireSleepToken(
2944 "DreamOnDisplay" + displayId, displayId);
2945 }
2946 } else {
2947 if (mDreamingSleepToken != null) {
2948 mDreamingSleepToken.release();
2949 mDreamingSleepToken = null;
2950 }
2951 }
2952 }
2953
2954 private void requestTransientBars(WindowState swipeTarget) {
2955 synchronized (mLock) {
2956 if (!mService.mPolicy.isUserSetupComplete()) {
2957 // Swipe-up for navigation bar is disabled during setup
2958 return;
2959 }
Jorim Jaggi956ca412019-01-07 14:49:14 +01002960 if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
2961 if (swipeTarget == mNavigationBar
Tiger Huang332793b2019-10-29 23:21:27 +08002962 && !getInsetsPolicy().isHidden(ITYPE_NAVIGATION_BAR)) {
Jorim Jaggi956ca412019-01-07 14:49:14 +01002963 // Don't show status bar when swiping on already visible navigation bar
Tiger Huang7c610aa2018-10-27 00:01:01 +08002964 return;
2965 }
Jorim Jaggi956ca412019-01-07 14:49:14 +01002966 final InsetsControlTarget controlTarget =
2967 swipeTarget.getControllableInsetProvider().getControlTarget();
2968 if (controlTarget == null) {
2969 return;
2970 }
2971 if (controlTarget.canShowTransient()) {
2972 mDisplayContent.getInsetsPolicy().showTransient(IntArray.wrap(
Tiger Huang332793b2019-10-29 23:21:27 +08002973 new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
Jorim Jaggi956ca412019-01-07 14:49:14 +01002974 } else {
2975 controlTarget.showInsets(WindowInsets.Type.systemBars(), false);
2976 }
2977 } else {
2978 boolean sb = mStatusBarController.checkShowTransientBarLw();
2979 boolean nb = mNavigationBarController.checkShowTransientBarLw()
2980 && !isNavBarEmpty(mLastSystemUiFlags);
2981 if (sb || nb) {
2982 // Don't show status bar when swiping on already visible navigation bar
2983 if (!nb && swipeTarget == mNavigationBar) {
2984 if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
2985 return;
2986 }
2987 if (sb) mStatusBarController.showTransient();
2988 if (nb) mNavigationBarController.showTransient();
2989 updateSystemUiVisibilityLw();
2990 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08002991 mImmersiveModeConfirmation.confirmCurrentPrompt();
Tiger Huang7c610aa2018-10-27 00:01:01 +08002992 }
2993 }
2994 }
2995
2996 private void disposeInputConsumer(InputConsumer inputConsumer) {
2997 if (inputConsumer != null) {
2998 inputConsumer.dismiss();
2999 }
3000 }
3001
3002 private boolean isStatusBarKeyguard() {
3003 return mStatusBar != null
3004 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
3005 }
3006
3007 private boolean isKeyguardOccluded() {
3008 // TODO (b/113840485): Handle per display keyguard.
3009 return mService.mPolicy.isKeyguardOccluded();
3010 }
3011
Jorim Jaggi956ca412019-01-07 14:49:14 +01003012 InsetsPolicy getInsetsPolicy() {
3013 return mDisplayContent.getInsetsPolicy();
3014 }
3015
Tiger Huang7c610aa2018-10-27 00:01:01 +08003016 void resetSystemUiVisibilityLw() {
3017 mLastSystemUiFlags = 0;
3018 updateSystemUiVisibilityLw();
3019 }
3020
3021 private int updateSystemUiVisibilityLw() {
3022 // If there is no window focused, there will be nobody to handle the events
3023 // anyway, so just hang on in whatever state we're in until things settle down.
3024 WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
3025 : mTopFullscreenOpaqueWindowState;
3026 if (winCandidate == null) {
3027 return 0;
3028 }
3029
3030 // The immersive mode confirmation should never affect the system bar visibility, otherwise
3031 // it will unhide the navigation bar and hide itself.
3032 if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
3033
3034 // The immersive mode confirmation took the focus from mLastFocusedWindow which was
3035 // controlling the system ui visibility. So if mLastFocusedWindow can still receive
3036 // keys, we let it keep controlling the visibility.
3037 final boolean lastFocusCanReceiveKeys =
3038 (mLastFocusedWindow != null && mLastFocusedWindow.canReceiveKeys());
3039 winCandidate = isStatusBarKeyguard() ? mStatusBar
3040 : lastFocusCanReceiveKeys ? mLastFocusedWindow
3041 : mTopFullscreenOpaqueWindowState;
3042 if (winCandidate == null) {
3043 return 0;
3044 }
3045 }
3046 final WindowState win = winCandidate;
3047 if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && isKeyguardOccluded()) {
3048 // We are updating at a point where the keyguard has gotten
3049 // focus, but we were last in a state where the top window is
3050 // hiding it. This is probably because the keyguard as been
3051 // shown while the top window was displayed, so we want to ignore
3052 // it here because this is just a very transient change and it
3053 // will quickly lose focus once it correctly gets hidden.
3054 return 0;
3055 }
3056
Jorim Jaggi28620472019-01-02 23:21:49 +01003057 mDisplayContent.getInsetsPolicy().updateBarControlTarget(win);
Jorim Jaggib6030952018-10-23 18:31:52 +02003058
Tiger Huang7c610aa2018-10-27 00:01:01 +08003059 int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
3060 & ~mResettingSystemUiFlags
3061 & ~mForceClearedSystemUiFlags;
3062 if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
3063 tmpVisibility
3064 &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
3065 }
3066
Jorim Jaggi956ca412019-01-07 14:49:14 +01003067 final int fullscreenAppearance = updateLightStatusBarAppearanceLw(0 /* vis */,
3068 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
3069 final int dockedAppearance = updateLightStatusBarAppearanceLw(0 /* vis */,
3070 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003071 mService.getStackBounds(
Tiger Huang7c610aa2018-10-27 00:01:01 +08003072 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, mDockedStackBounds);
Jorim Jaggi956ca412019-01-07 14:49:14 +01003073 final boolean inSplitScreen = !mDockedStackBounds.isEmpty();
3074 mService.getStackBounds(inSplitScreen ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
3075 : WINDOWING_MODE_FULLSCREEN,
Tiger Huangd5f0b9a2019-10-10 10:34:57 +02003076 ACTIVITY_TYPE_UNDEFINED, mNonDockedStackBounds);
Tarandeep Singhe439dec2019-04-22 12:28:43 -07003077 final Pair<Integer, Boolean> result =
3078 updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
3079 final int visibility = result.first;
Tiger Huang0dbd5372019-10-26 00:24:22 +08003080 final int appearance = win.mAttrs.insetsFlags.appearance
3081 | InsetsFlags.getAppearance(visibility);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003082 final int diff = visibility ^ mLastSystemUiFlags;
Jorim Jaggi956ca412019-01-07 14:49:14 +01003083 final InsetsPolicy insetsPolicy = getInsetsPolicy();
3084 final boolean isFullscreen = (visibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
3085 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)) != 0
3086 || (PolicyControl.getWindowFlags(win, win.mAttrs) & FLAG_FULLSCREEN) != 0
Tiger Huang332793b2019-10-29 23:21:27 +08003087 || (mStatusBar != null && insetsPolicy.isHidden(ITYPE_STATUS_BAR))
Jorim Jaggi956ca412019-01-07 14:49:14 +01003088 || (mNavigationBar != null && insetsPolicy.isHidden(
Tiger Huang332793b2019-10-29 23:21:27 +08003089 ITYPE_NAVIGATION_BAR));
Jorim Jaggi956ca412019-01-07 14:49:14 +01003090 final int behavior = win.mAttrs.insetsFlags.behavior;
3091 final boolean isImmersive = (visibility & (View.SYSTEM_UI_FLAG_IMMERSIVE
3092 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)) != 0
3093 || behavior == BEHAVIOR_SHOW_BARS_BY_SWIPE
3094 || behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
Tiger Huang0dbd5372019-10-26 00:24:22 +08003095 if (diff == 0
Jorim Jaggi956ca412019-01-07 14:49:14 +01003096 && mLastAppearance == appearance
3097 && mLastFullscreenAppearance == fullscreenAppearance
3098 && mLastDockedAppearance == dockedAppearance
3099 && mLastFocusIsFullscreen == isFullscreen
3100 && mLastFocusIsImmersive == isImmersive
Tiger Huang7c610aa2018-10-27 00:01:01 +08003101 && mFocusedApp == win.getAppToken()
3102 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
3103 && mLastDockedStackBounds.equals(mDockedStackBounds)) {
3104 return 0;
3105 }
Tiger Huang0dbd5372019-10-26 00:24:22 +08003106
3107 // Obtains which types should show transient and which types should abort transient.
3108 // If there is no transient state change, this pair will contain two empty arrays.
3109 final Pair<int[], int[]> transientState = getTransientState(visibility, mLastSystemUiFlags);
3110
Tiger Huang7c610aa2018-10-27 00:01:01 +08003111 mLastSystemUiFlags = visibility;
Jorim Jaggi956ca412019-01-07 14:49:14 +01003112 mLastAppearance = appearance;
3113 mLastFullscreenAppearance = fullscreenAppearance;
3114 mLastDockedAppearance = dockedAppearance;
3115 mLastFocusIsFullscreen = isFullscreen;
3116 mLastFocusIsImmersive = isImmersive;
Tiger Huang7c610aa2018-10-27 00:01:01 +08003117 mFocusedApp = win.getAppToken();
Riddle Hsu4d6a63f2019-03-29 19:14:43 +08003118 mLastNonDockedStackBounds.set(mNonDockedStackBounds);
3119 mLastDockedStackBounds.set(mDockedStackBounds);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003120 final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
3121 final Rect dockedStackBounds = new Rect(mDockedStackBounds);
Jorim Jaggi956ca412019-01-07 14:49:14 +01003122 final AppearanceRegion[] appearanceRegions = inSplitScreen
3123 ? new AppearanceRegion[]{
3124 new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds),
3125 new AppearanceRegion(dockedAppearance, dockedStackBounds)}
3126 : new AppearanceRegion[]{
3127 new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds)};
Tarandeep Singhe439dec2019-04-22 12:28:43 -07003128 final boolean isNavbarColorManagedByIme = result.second;
Tiger Huang7c610aa2018-10-27 00:01:01 +08003129 mHandler.post(() -> {
3130 StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
3131 if (statusBar != null) {
3132 final int displayId = getDisplayId();
Tiger Huang0dbd5372019-10-26 00:24:22 +08003133 statusBar.setDisableFlags(displayId, visibility & StatusBarManager.DISABLE_MASK,
3134 win.toString());
3135 if (transientState.first.length > 0) {
3136 statusBar.showTransient(displayId, transientState.first);
Jorim Jaggi956ca412019-01-07 14:49:14 +01003137 }
Tiger Huang0dbd5372019-10-26 00:24:22 +08003138 if (transientState.second.length > 0) {
3139 statusBar.abortTransient(displayId, transientState.second);
3140 }
3141 statusBar.onSystemBarAppearanceChanged(displayId, appearance,
3142 appearanceRegions, isNavbarColorManagedByIme);
Jorim Jaggi956ca412019-01-07 14:49:14 +01003143 statusBar.topAppWindowChanged(displayId, isFullscreen, isImmersive);
3144
3145 // TODO(b/118118435): Remove this after removing system UI visibilities.
Tiger Huang1d739fb2019-10-22 21:05:16 +08003146 mDisplayContent.statusBarVisibilityChanged(
3147 visibility & ~(View.STATUS_BAR_UNHIDE | View.NAVIGATION_BAR_UNHIDE));
Tiger Huang7c610aa2018-10-27 00:01:01 +08003148 }
3149 });
3150 return diff;
3151 }
3152
Tiger Huang0dbd5372019-10-26 00:24:22 +08003153 private static Pair<int[], int[]> getTransientState(int vis, int oldVis) {
3154 final IntArray typesToShow = new IntArray(0);
3155 final IntArray typesToAbort = new IntArray(0);
Tiger Huang332793b2019-10-29 23:21:27 +08003156 updateTransientState(vis, oldVis, View.STATUS_BAR_TRANSIENT, ITYPE_STATUS_BAR, typesToShow,
Tiger Huang0dbd5372019-10-26 00:24:22 +08003157 typesToAbort);
3158 updateTransientState(vis, oldVis, View.NAVIGATION_BAR_TRANSIENT,
Tiger Huang332793b2019-10-29 23:21:27 +08003159 ITYPE_NAVIGATION_BAR, typesToShow, typesToAbort);
Tiger Huang0dbd5372019-10-26 00:24:22 +08003160 return Pair.create(typesToShow.toArray(), typesToAbort.toArray());
Tiger Huang7c610aa2018-10-27 00:01:01 +08003161 }
3162
Tiger Huang0dbd5372019-10-26 00:24:22 +08003163 private static void updateTransientState(int vis, int oldVis, int transientFlag,
Tiger Huang332793b2019-10-29 23:21:27 +08003164 @InternalInsetsType int type, IntArray typesToShow, IntArray typesToAbort) {
Tiger Huang0dbd5372019-10-26 00:24:22 +08003165 final boolean wasTransient = (oldVis & transientFlag) != 0;
3166 final boolean isTransient = (vis & transientFlag) != 0;
3167 if (!wasTransient && isTransient) {
3168 typesToShow.add(type);
3169 } else if (wasTransient && !isTransient) {
3170 typesToAbort.add(type);
3171 }
3172 }
3173
3174 private int updateLightStatusBarAppearanceLw(@Appearance int appearance, WindowState opaque,
Jorim Jaggi956ca412019-01-07 14:49:14 +01003175 WindowState opaqueOrDimming) {
3176 final boolean onKeyguard = isStatusBarKeyguard() && !isKeyguardOccluded();
3177 final WindowState statusColorWin = onKeyguard ? mStatusBar : opaqueOrDimming;
3178 if (statusColorWin != null && (statusColorWin == opaque || onKeyguard)) {
3179 // If the top fullscreen-or-dimming window is also the top fullscreen, respect
3180 // its light flag.
Tiger Huang332793b2019-10-29 23:21:27 +08003181 appearance &= ~APPEARANCE_LIGHT_STATUS_BARS;
Tiger Huang0dbd5372019-10-26 00:24:22 +08003182 final int legacyAppearance = InsetsFlags.getAppearance(
3183 PolicyControl.getSystemUiVisibility(statusColorWin, null));
3184 appearance |= (statusColorWin.mAttrs.insetsFlags.appearance | legacyAppearance)
Tiger Huang332793b2019-10-29 23:21:27 +08003185 & APPEARANCE_LIGHT_STATUS_BARS;
Jorim Jaggi956ca412019-01-07 14:49:14 +01003186 } else if (statusColorWin != null && statusColorWin.isDimming()) {
3187 // Otherwise if it's dimming, clear the light flag.
Tiger Huang332793b2019-10-29 23:21:27 +08003188 appearance &= ~APPEARANCE_LIGHT_STATUS_BARS;
Jorim Jaggi956ca412019-01-07 14:49:14 +01003189 }
3190 return appearance;
3191 }
3192
Tiger Huang7c610aa2018-10-27 00:01:01 +08003193 @VisibleForTesting
3194 @Nullable
3195 static WindowState chooseNavigationColorWindowLw(WindowState opaque,
3196 WindowState opaqueOrDimming, WindowState imeWindow,
3197 @NavigationBarPosition int navBarPosition) {
3198 // If the IME window is visible and FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS is set, then IME
3199 // window can be navigation color window.
3200 final boolean imeWindowCanNavColorWindow = imeWindow != null
3201 && imeWindow.isVisibleLw()
3202 && navBarPosition == NAV_BAR_BOTTOM
3203 && (PolicyControl.getWindowFlags(imeWindow, null)
3204 & WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
3205
3206 if (opaque != null && opaqueOrDimming == opaque) {
3207 // If the top fullscreen-or-dimming window is also the top fullscreen, respect it
3208 // unless IME window is also eligible, since currently the IME window is always show
3209 // above the opaque fullscreen app window, regardless of the IME target window.
3210 // TODO(b/31559891): Maybe we need to revisit this condition once b/31559891 is fixed.
3211 return imeWindowCanNavColorWindow ? imeWindow : opaque;
3212 }
3213
3214 if (opaqueOrDimming == null || !opaqueOrDimming.isDimming()) {
3215 // No dimming window is involved. Determine the result only with the IME window.
3216 return imeWindowCanNavColorWindow ? imeWindow : null;
3217 }
3218
3219 if (!imeWindowCanNavColorWindow) {
3220 // No IME window is involved. Determine the result only with opaqueOrDimming.
3221 return opaqueOrDimming;
3222 }
3223
3224 // The IME window and the dimming window are competing. Check if the dimming window can be
3225 // IME target or not.
3226 if (LayoutParams.mayUseInputMethod(PolicyControl.getWindowFlags(opaqueOrDimming, null))) {
3227 // The IME window is above the dimming window.
3228 return imeWindow;
3229 } else {
3230 // The dimming window is above the IME window.
3231 return opaqueOrDimming;
3232 }
3233 }
3234
3235 @VisibleForTesting
3236 static int updateLightNavigationBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming,
3237 WindowState imeWindow, WindowState navColorWin) {
3238
3239 if (navColorWin != null) {
3240 if (navColorWin == imeWindow || navColorWin == opaque) {
3241 // Respect the light flag.
3242 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
3243 vis |= PolicyControl.getSystemUiVisibility(navColorWin, null)
3244 & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
3245 } else if (navColorWin == opaqueOrDimming && navColorWin.isDimming()) {
3246 // Clear the light flag for dimming window.
3247 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
3248 }
3249 }
3250 return vis;
3251 }
3252
Tarandeep Singhe439dec2019-04-22 12:28:43 -07003253 private Pair<Integer, Boolean> updateSystemBarsLw(WindowState win, int oldVis, int vis) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08003254 final boolean dockedStackVisible =
3255 mDisplayContent.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
3256 final boolean freeformStackVisible =
3257 mDisplayContent.isStackVisible(WINDOWING_MODE_FREEFORM);
3258 final boolean resizing = mDisplayContent.getDockedDividerController().isResizing();
3259
3260 // We need to force system bars when the docked stack is visible, when the freeform stack
hyok.kim332ccfc2019-07-02 15:39:43 +09003261 // is focused but also when we are resizing for the transitions when docked stack
Tiger Huang7c610aa2018-10-27 00:01:01 +08003262 // visibility changes.
hyok.kim332ccfc2019-07-02 15:39:43 +09003263 mForceShowSystemBars = dockedStackVisible || win.inFreeformWindowingMode() || resizing
Brad Stenninge0573692019-03-11 13:52:46 -07003264 || mForceShowSystemBarsFromExternal;
Tiger Huang7c610aa2018-10-27 00:01:01 +08003265 final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
3266
3267 // apply translucent bar vis flags
3268 WindowState fullscreenTransWin = isStatusBarKeyguard() && !isKeyguardOccluded()
3269 ? mStatusBar
3270 : mTopFullscreenOpaqueWindowState;
3271 vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
3272 vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
Adrian Roosfaba4062019-05-14 15:27:17 +02003273 int dockedVis = mStatusBarController.applyTranslucentFlagLw(
Tiger Huang7c610aa2018-10-27 00:01:01 +08003274 mTopDockedOpaqueWindowState, 0, 0);
Adrian Roosfaba4062019-05-14 15:27:17 +02003275 dockedVis = mNavigationBarController.applyTranslucentFlagLw(
3276 mTopDockedOpaqueWindowState, dockedVis, 0);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003277
3278 final boolean fullscreenDrawsStatusBarBackground =
3279 drawsStatusBarBackground(vis, mTopFullscreenOpaqueWindowState);
3280 final boolean dockedDrawsStatusBarBackground =
3281 drawsStatusBarBackground(dockedVis, mTopDockedOpaqueWindowState);
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003282 final boolean fullscreenDrawsNavBarBackground =
3283 drawsNavigationBarBackground(vis, mTopFullscreenOpaqueWindowState);
Adrian Roosfaba4062019-05-14 15:27:17 +02003284 final boolean dockedDrawsNavigationBarBackground =
3285 drawsNavigationBarBackground(dockedVis, mTopDockedOpaqueWindowState);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003286
3287 // prevent status bar interaction from clearing certain flags
3288 int type = win.getAttrs().type;
3289 boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
3290 if (statusBarHasFocus && !isStatusBarKeyguard()) {
3291 int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
3292 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
3293 | View.SYSTEM_UI_FLAG_IMMERSIVE
3294 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
3295 | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
3296 if (isKeyguardOccluded()) {
3297 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
3298 }
3299 vis = (vis & ~flags) | (oldVis & flags);
3300 }
3301
3302 if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
3303 vis |= View.STATUS_BAR_TRANSPARENT;
3304 vis &= ~View.STATUS_BAR_TRANSLUCENT;
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003305 } else if (forceOpaqueStatusBar) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08003306 vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
3307 }
3308
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003309 vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing,
Adrian Roosfaba4062019-05-14 15:27:17 +02003310 fullscreenDrawsNavBarBackground, dockedDrawsNavigationBarBackground);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003311
3312 // update status bar
3313 boolean immersiveSticky =
3314 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
3315 final boolean hideStatusBarWM =
3316 mTopFullscreenOpaqueWindowState != null
3317 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
3318 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
3319 final boolean hideStatusBarSysui =
3320 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
3321 final boolean hideNavBarSysui =
3322 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
3323
3324 final boolean transientStatusBarAllowed = mStatusBar != null
3325 && (statusBarHasFocus || (!mForceShowSystemBars
3326 && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
3327
3328 final boolean transientNavBarAllowed = mNavigationBar != null
3329 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
3330
3331 final long now = SystemClock.uptimeMillis();
3332 final boolean pendingPanic = mPendingPanicGestureUptime != 0
3333 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
3334 final DisplayPolicy defaultDisplayPolicy =
3335 mService.getDefaultDisplayContentLocked().getDisplayPolicy();
3336 if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard()
3337 // TODO (b/111955725): Show keyguard presentation on all external displays
3338 && defaultDisplayPolicy.isKeyguardDrawComplete()) {
3339 // The user performed the panic gesture recently, we're about to hide the bars,
3340 // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
3341 mPendingPanicGestureUptime = 0;
3342 mStatusBarController.showTransient();
3343 if (!isNavBarEmpty(vis)) {
3344 mNavigationBarController.showTransient();
3345 }
3346 }
3347
3348 final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
3349 && !transientStatusBarAllowed && hideStatusBarSysui;
3350 final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
3351 && !transientNavBarAllowed;
3352 if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
3353 // clear the clearable flags instead
3354 clearClearableFlagsLw();
3355 vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
3356 }
3357
3358 final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
3359 immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
3360 final boolean navAllowedHidden = immersive || immersiveSticky;
3361
3362 if (hideNavBarSysui && !navAllowedHidden
3363 && mService.mPolicy.getWindowLayerLw(win)
3364 > mService.mPolicy.getWindowLayerFromTypeLw(TYPE_INPUT_CONSUMER)) {
3365 // We can't hide the navbar from this window otherwise the input consumer would not get
3366 // the input events.
3367 vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
3368 }
3369
3370 vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
3371
3372 // update navigation bar
3373 boolean oldImmersiveMode = isImmersiveMode(oldVis);
3374 boolean newImmersiveMode = isImmersiveMode(vis);
3375 if (oldImmersiveMode != newImmersiveMode) {
3376 final String pkg = win.getOwningPackage();
3377 mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
3378 mService.mPolicy.isUserSetupComplete(),
3379 isNavBarEmpty(win.getSystemUiVisibility()));
3380 }
3381
3382 vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
3383
3384 final WindowState navColorWin = chooseNavigationColorWindowLw(
3385 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState,
3386 mDisplayContent.mInputMethodWindow, mNavigationBarPosition);
3387 vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState,
3388 mTopFullscreenOpaqueOrDimmingWindowState,
3389 mDisplayContent.mInputMethodWindow, navColorWin);
Tarandeep Singhe439dec2019-04-22 12:28:43 -07003390 // Navbar color is controlled by the IME.
3391 final boolean isManagedByIme =
3392 navColorWin != null && navColorWin == mDisplayContent.mInputMethodWindow;
Tiger Huang7c610aa2018-10-27 00:01:01 +08003393
Tarandeep Singhe439dec2019-04-22 12:28:43 -07003394 return Pair.create(vis, isManagedByIme);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003395 }
3396
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003397 private boolean drawsBarBackground(int vis, WindowState win, BarController controller,
3398 int translucentFlag) {
3399 if (!controller.isTransparentAllowed(win)) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08003400 return false;
3401 }
3402 if (win == null) {
3403 return true;
3404 }
3405
3406 final boolean drawsSystemBars =
3407 (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
3408 final boolean forceDrawsSystemBars =
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003409 (win.getAttrs().privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
Tiger Huang7c610aa2018-10-27 00:01:01 +08003410
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003411 return forceDrawsSystemBars || drawsSystemBars && (vis & translucentFlag) == 0;
3412 }
3413
3414 private boolean drawsStatusBarBackground(int vis, WindowState win) {
3415 return drawsBarBackground(vis, win, mStatusBarController, FLAG_TRANSLUCENT_STATUS);
3416 }
3417
3418 private boolean drawsNavigationBarBackground(int vis, WindowState win) {
3419 return drawsBarBackground(vis, win, mNavigationBarController, FLAG_TRANSLUCENT_NAVIGATION);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003420 }
3421
3422 /**
3423 * @return the current visibility flags with the nav-bar opacity related flags toggled based
3424 * on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
3425 */
3426 private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003427 boolean freeformStackVisible, boolean isDockedDividerResizing,
Adrian Roosfaba4062019-05-14 15:27:17 +02003428 boolean fullscreenDrawsBackground, boolean dockedDrawsNavigationBarBackground) {
3429 if (mNavBarOpacityMode == NAV_BAR_FORCE_TRANSPARENT) {
3430 if (fullscreenDrawsBackground && dockedDrawsNavigationBarBackground) {
3431 visibility = setNavBarTransparentFlag(visibility);
3432 } else if (dockedStackVisible) {
3433 visibility = setNavBarOpaqueFlag(visibility);
3434 }
3435 } else if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
Tiger Huang7c610aa2018-10-27 00:01:01 +08003436 if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
HEO SEUNG22d3ec22019-05-30 20:28:53 +09003437 if (mIsFreeformWindowOverlappingWithNavBar) {
3438 visibility = setNavBarTranslucentFlag(visibility);
3439 } else {
3440 visibility = setNavBarOpaqueFlag(visibility);
3441 }
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003442 } else if (fullscreenDrawsBackground) {
3443 visibility = setNavBarTransparentFlag(visibility);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003444 }
3445 } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
3446 if (isDockedDividerResizing) {
3447 visibility = setNavBarOpaqueFlag(visibility);
3448 } else if (freeformStackVisible) {
3449 visibility = setNavBarTranslucentFlag(visibility);
3450 } else {
3451 visibility = setNavBarOpaqueFlag(visibility);
3452 }
3453 }
3454
Tiger Huang7c610aa2018-10-27 00:01:01 +08003455 return visibility;
3456 }
3457
3458 private int setNavBarOpaqueFlag(int visibility) {
3459 return visibility & ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
3460 }
3461
3462 private int setNavBarTranslucentFlag(int visibility) {
3463 visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
3464 return visibility | View.NAVIGATION_BAR_TRANSLUCENT;
3465 }
3466
Jorim Jaggia6aabac2019-03-11 14:23:16 -07003467 private int setNavBarTransparentFlag(int visibility) {
3468 visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
3469 return visibility | View.NAVIGATION_BAR_TRANSPARENT;
3470 }
3471
Tiger Huang7c610aa2018-10-27 00:01:01 +08003472 private void clearClearableFlagsLw() {
3473 int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
3474 if (newVal != mResettingSystemUiFlags) {
3475 mResettingSystemUiFlags = newVal;
3476 mDisplayContent.reevaluateStatusBarVisibility();
3477 }
3478 }
3479
3480 private boolean isImmersiveMode(int vis) {
3481 final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
3482 return mNavigationBar != null
3483 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
3484 && (vis & flags) != 0
3485 && canHideNavigationBar();
3486 }
3487
3488 /**
3489 * @return whether the navigation bar can be hidden, e.g. the device has a navigation bar
3490 */
3491 private boolean canHideNavigationBar() {
3492 return hasNavigationBar();
3493 }
3494
3495 private static boolean isNavBarEmpty(int systemUiFlags) {
3496 final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
3497 | View.STATUS_BAR_DISABLE_BACK
3498 | View.STATUS_BAR_DISABLE_RECENT);
3499
3500 return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
3501 }
3502
Tiger Huang7c610aa2018-10-27 00:01:01 +08003503 private final Runnable mHiddenNavPanic = new Runnable() {
3504 @Override
3505 public void run() {
3506 synchronized (mLock) {
3507 if (!mService.mPolicy.isUserSetupComplete()) {
3508 // Swipe-up for navigation bar is disabled during setup
3509 return;
3510 }
3511 mPendingPanicGestureUptime = SystemClock.uptimeMillis();
3512 if (!isNavBarEmpty(mLastSystemUiFlags)) {
3513 mNavigationBarController.showTransient();
Jorim Jaggi956ca412019-01-07 14:49:14 +01003514 mDisplayContent.getInsetsPolicy().showTransient(IntArray.wrap(
Tiger Huang332793b2019-10-29 23:21:27 +08003515 new int[] {ITYPE_NAVIGATION_BAR}));
Tiger Huang7c610aa2018-10-27 00:01:01 +08003516 }
3517 }
3518 }
3519 };
3520
3521 void onPowerKeyDown(boolean isScreenOn) {
3522 // Detect user pressing the power button in panic when an application has
3523 // taken over the whole screen.
3524 boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(isScreenOn,
3525 SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags),
3526 isNavBarEmpty(mLastSystemUiFlags));
3527 if (panic) {
3528 mHandler.post(mHiddenNavPanic);
3529 }
3530 }
3531
3532 void onVrStateChangedLw(boolean enabled) {
3533 mImmersiveModeConfirmation.onVrStateChangedLw(enabled);
3534 }
3535
3536 /**
3537 * Called when the state of lock task mode changes. This should be used to disable immersive
3538 * mode confirmation.
3539 *
3540 * @param lockTaskState the new lock task mode state. One of
3541 * {@link ActivityManager#LOCK_TASK_MODE_NONE},
3542 * {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
3543 * {@link ActivityManager#LOCK_TASK_MODE_PINNED}.
3544 */
3545 public void onLockTaskStateChangedLw(int lockTaskState) {
3546 mImmersiveModeConfirmation.onLockTaskModeChangedLw(lockTaskState);
3547 }
3548
3549 /**
3550 * Request a screenshot be taken.
3551 *
3552 * @param screenshotType The type of screenshot, for example either
3553 * {@link WindowManager#TAKE_SCREENSHOT_FULLSCREEN} or
3554 * {@link WindowManager#TAKE_SCREENSHOT_SELECTED_REGION}
3555 */
3556 public void takeScreenshot(int screenshotType) {
3557 if (mScreenshotHelper != null) {
3558 mScreenshotHelper.takeScreenshot(screenshotType,
3559 mStatusBar != null && mStatusBar.isVisibleLw(),
James O'Learyfa5bb7a2019-09-05 13:43:29 -04003560 mNavigationBar != null && mNavigationBar.isVisibleLw(),
3561 mHandler, null /* completionConsumer */);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003562 }
3563 }
3564
Ady Abrahamf3e05312019-05-13 18:04:59 -07003565 RefreshRatePolicy getRefreshRatePolicy() {
3566 return mRefreshRatePolicy;
3567 }
3568
Riddle Hsu5ce4bb32018-07-18 16:11:30 +08003569 void dump(String prefix, PrintWriter pw) {
Riddle Hsuccf09402019-08-13 00:33:06 +08003570 pw.print(prefix); pw.println("DisplayPolicy");
Tiger Huang7c610aa2018-10-27 00:01:01 +08003571 prefix += " ";
3572 pw.print(prefix);
3573 pw.print("mCarDockEnablesAccelerometer="); pw.print(mCarDockEnablesAccelerometer);
3574 pw.print(" mDeskDockEnablesAccelerometer=");
3575 pw.println(mDeskDockEnablesAccelerometer);
3576 pw.print(prefix); pw.print("mDockMode="); pw.print(Intent.dockStateToString(mDockMode));
3577 pw.print(" mLidState="); pw.println(WindowManagerFuncs.lidStateToString(mLidState));
3578 pw.print(prefix); pw.print("mAwake="); pw.print(mAwake);
3579 pw.print(" mScreenOnEarly="); pw.print(mScreenOnEarly);
3580 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
3581 pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
3582 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
3583 pw.print(prefix); pw.print("mHdmiPlugged="); pw.println(mHdmiPlugged);
3584 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
3585 || mForceClearedSystemUiFlags != 0) {
3586 pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
3587 pw.print(Integer.toHexString(mLastSystemUiFlags));
3588 pw.print(" mResettingSystemUiFlags=0x");
3589 pw.print(Integer.toHexString(mResettingSystemUiFlags));
3590 pw.print(" mForceClearedSystemUiFlags=0x");
3591 pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
3592 }
Tiger Huang7c610aa2018-10-27 00:01:01 +08003593 pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
3594 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
3595 pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
3596 if (mStatusBar != null) {
3597 pw.print(prefix); pw.print("mStatusBar="); pw.print(mStatusBar);
3598 pw.print(" isStatusBarKeyguard="); pw.println(isStatusBarKeyguard());
3599 }
3600 if (mNavigationBar != null) {
3601 pw.print(prefix); pw.print("mNavigationBar="); pw.println(mNavigationBar);
Winson Chung4723b4e2019-03-25 16:49:36 -07003602 pw.print(prefix); pw.print("mNavBarOpacityMode="); pw.println(mNavBarOpacityMode);
3603 pw.print(prefix); pw.print("mNavigationBarCanMove="); pw.println(mNavigationBarCanMove);
3604 pw.print(prefix); pw.print("mNavigationBarPosition=");
3605 pw.println(mNavigationBarPosition);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003606 }
3607 if (mFocusedWindow != null) {
3608 pw.print(prefix); pw.print("mFocusedWindow="); pw.println(mFocusedWindow);
3609 }
3610 if (mFocusedApp != null) {
3611 pw.print(prefix); pw.print("mFocusedApp="); pw.println(mFocusedApp);
3612 }
3613 if (mTopFullscreenOpaqueWindowState != null) {
3614 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
3615 pw.println(mTopFullscreenOpaqueWindowState);
3616 }
3617 if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
3618 pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
3619 pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
3620 }
3621 if (mForcingShowNavBar) {
3622 pw.print(prefix); pw.print("mForcingShowNavBar="); pw.println(mForcingShowNavBar);
3623 pw.print(prefix); pw.print("mForcingShowNavBarLayer=");
3624 pw.println(mForcingShowNavBarLayer);
3625 }
Riddle Hsuccf09402019-08-13 00:33:06 +08003626 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.println(mTopIsFullscreen);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003627 pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
3628 pw.print(" mForceStatusBarFromKeyguard="); pw.println(mForceStatusBarFromKeyguard);
Riddle Hsuccf09402019-08-13 00:33:06 +08003629 pw.print(prefix); pw.print("mForceShowSystemBarsFromExternal=");
3630 pw.print(mForceShowSystemBarsFromExternal);
3631 pw.print(" mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn);
Tiger Huang7c610aa2018-10-27 00:01:01 +08003632 mStatusBarController.dump(pw, prefix);
3633 mNavigationBarController.dump(pw, prefix);
3634
3635 pw.print(prefix); pw.println("Looper state:");
3636 mHandler.getLooper().dump(new PrintWriterPrinter(pw), prefix + " ");
Riddle Hsu5ce4bb32018-07-18 16:11:30 +08003637 }
Arthur Hung20479922019-02-27 17:13:22 +08003638
3639 private boolean supportsPointerLocation() {
3640 return mDisplayContent.isDefaultDisplay || !mDisplayContent.isPrivate();
3641 }
3642
3643 void setPointerLocationEnabled(boolean pointerLocationEnabled) {
3644 if (!supportsPointerLocation()) {
3645 return;
3646 }
3647
3648 mHandler.sendEmptyMessage(pointerLocationEnabled
3649 ? MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
3650 }
3651
3652 private void enablePointerLocation() {
3653 if (mPointerLocationView != null) {
3654 return;
3655 }
3656
3657 mPointerLocationView = new PointerLocationView(mContext);
3658 mPointerLocationView.setPrintCoords(false);
3659 final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
3660 WindowManager.LayoutParams.MATCH_PARENT,
3661 WindowManager.LayoutParams.MATCH_PARENT);
3662 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
3663 lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
3664 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
3665 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
3666 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
3667 lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
3668 if (ActivityManager.isHighEndGfx()) {
3669 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
3670 lp.privateFlags |=
3671 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
3672 }
3673 lp.format = PixelFormat.TRANSLUCENT;
3674 lp.setTitle("PointerLocation - display " + getDisplayId());
3675 lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
3676 final WindowManager wm = mContext.getSystemService(WindowManager.class);
3677 wm.addView(mPointerLocationView, lp);
3678 mDisplayContent.registerPointerEventListener(mPointerLocationView);
3679 }
3680
3681 private void disablePointerLocation() {
3682 if (mPointerLocationView == null) {
3683 return;
3684 }
3685
3686 mDisplayContent.unregisterPointerEventListener(mPointerLocationView);
3687 final WindowManager wm = mContext.getSystemService(WindowManager.class);
3688 wm.removeView(mPointerLocationView);
3689 mPointerLocationView = null;
3690 }
HEO SEUNG22d3ec22019-05-30 20:28:53 +09003691
Arthur Hungfbc8f412019-08-01 19:57:54 +08003692 /**
3693 * Check if the window could be excluded from checking if the display has content.
3694 *
3695 * @param w WindowState to check if should be excluded.
3696 * @return True if the window type is PointerLocation which is excluded.
3697 */
3698 boolean isWindowExcludedFromContent(WindowState w) {
3699 if (w != null && mPointerLocationView != null) {
3700 return w.mClient == mPointerLocationView.getWindowToken();
3701 }
3702
3703 return false;
3704 }
3705
HEO SEUNG22d3ec22019-05-30 20:28:53 +09003706 @VisibleForTesting
3707 static boolean isOverlappingWithNavBar(WindowState targetWindow, WindowState navBarWindow) {
3708 if (navBarWindow == null || !navBarWindow.isVisibleLw()
Garfield Tane8d84ab2019-10-11 09:49:40 -07003709 || targetWindow.mActivityRecord == null || !targetWindow.isVisibleLw()) {
HEO SEUNG22d3ec22019-05-30 20:28:53 +09003710 return false;
3711 }
3712
3713 return Rect.intersects(targetWindow.getFrameLw(), navBarWindow.getFrameLw());
3714 }
Riddle Hsu5ce4bb32018-07-18 16:11:30 +08003715}