1/*
2 * Copyright (C) 2006 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.policy;
18
19import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
20import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
21import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
22import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
23import static android.app.ActivityManager.StackId.HOME_STACK_ID;
24import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
25import static android.app.AppOpsManager.OP_TOAST_WINDOW;
26import static android.content.Context.CONTEXT_RESTRICTED;
27import static android.content.Context.DISPLAY_SERVICE;
28import static android.content.Context.WINDOW_SERVICE;
29import static android.content.pm.PackageManager.FEATURE_LEANBACK;
30import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
31import static android.content.pm.PackageManager.FEATURE_WATCH;
32import static android.content.pm.PackageManager.PERMISSION_GRANTED;
33import static android.content.res.Configuration.EMPTY;
34import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
35import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
36import static android.os.Build.VERSION_CODES.M;
37import static android.os.Build.VERSION_CODES.O;
38import static android.view.Display.DEFAULT_DISPLAY;
39import static android.view.Display.STATE_OFF;
40import static android.view.WindowManager.DOCKED_LEFT;
41import static android.view.WindowManager.DOCKED_RIGHT;
42import static android.view.WindowManager.DOCKED_TOP;
43import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
44import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
45import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
46import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
47import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
48import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
49import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
50import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
51import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR;
52import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
53import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN;
54import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
55import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
56import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
57import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
58import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
59import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
60import static android.view.WindowManager.LayoutParams.LAST_SYSTEM_WINDOW;
61import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
62import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN;
63import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
64import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
65import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
66import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
67import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
68import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
69import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
70import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
71import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
72import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
73import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
74import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
75import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
76import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
77import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
78import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
79import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
80import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
81import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
82import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
83import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
84import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
85import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
86import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
87import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
88import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
89import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
90import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
91import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
92import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
93import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
94import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
95import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR;
96import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
97import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
98import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
99import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
100import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
101import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
102import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
103import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
104import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
105import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
106import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING;
107import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
108import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
109import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
110import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
111import static android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION;
112import static android.view.WindowManagerGlobal.ADD_OKAY;
113import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED;
114import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
115import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
116import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
117import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
118import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
119import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
120
121import android.annotation.Nullable;
122import android.app.ActivityManager;
123import android.app.ActivityManager.StackId;
124import android.app.ActivityManagerInternal;
125import android.app.ActivityManagerInternal.SleepToken;
126import android.app.ActivityThread;
127import android.app.AppOpsManager;
128import android.app.IUiModeManager;
129import android.app.ProgressDialog;
130import android.app.SearchManager;
131import android.app.StatusBarManager;
132import android.app.UiModeManager;
133import android.content.ActivityNotFoundException;
134import android.content.BroadcastReceiver;
135import android.content.ComponentName;
136import android.content.ContentResolver;
137import android.content.Context;
138import android.content.Intent;
139import android.content.IntentFilter;
140import android.content.ServiceConnection;
141import android.content.pm.ActivityInfo;
142import android.content.pm.ApplicationInfo;
143import android.content.pm.PackageManager;
144import android.content.pm.ResolveInfo;
145import android.content.res.CompatibilityInfo;
146import android.content.res.Configuration;
147import android.content.res.Resources;
148import android.content.res.TypedArray;
149import android.database.ContentObserver;
150import android.graphics.PixelFormat;
151import android.graphics.Rect;
152import android.graphics.drawable.Drawable;
153import android.hardware.display.DisplayManager;
154import android.hardware.hdmi.HdmiControlManager;
155import android.hardware.hdmi.HdmiPlaybackClient;
156import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback;
157import android.hardware.input.InputManager;
158import android.hardware.input.InputManagerInternal;
159import android.hardware.power.V1_0.PowerHint;
160import android.media.AudioAttributes;
161import android.media.AudioManager;
162import android.media.AudioSystem;
163import android.media.IAudioService;
164import android.media.session.MediaSessionLegacyHelper;
165import android.os.Binder;
166import android.os.Build;
167import android.os.Bundle;
168import android.os.FactoryTest;
169import android.os.Handler;
170import android.os.IBinder;
171import android.os.IDeviceIdleController;
172import android.os.Looper;
173import android.os.Message;
174import android.os.Messenger;
175import android.os.PowerManager;
176import android.os.PowerManagerInternal;
177import android.os.Process;
178import android.os.RemoteException;
179import android.os.ServiceManager;
180import android.os.SystemClock;
181import android.os.SystemProperties;
182import android.os.UEventObserver;
183import android.os.UserHandle;
184import android.os.VibrationEffect;
185import android.os.Vibrator;
186import android.provider.MediaStore;
187import android.provider.Settings;
188import android.service.dreams.DreamManagerInternal;
189import android.service.dreams.DreamService;
190import android.service.dreams.IDreamManager;
191import android.service.vr.IPersistentVrStateCallbacks;
192import android.speech.RecognizerIntent;
193import android.telecom.TelecomManager;
194import android.util.DisplayMetrics;
195import android.util.EventLog;
196import android.util.Log;
197import android.util.LongSparseArray;
198import android.util.MutableBoolean;
199import android.util.Slog;
200import android.util.SparseArray;
201import android.view.Display;
202import android.view.Gravity;
203import android.view.HapticFeedbackConstants;
204import android.view.IApplicationToken;
205import android.view.IWindowManager;
206import android.view.InputChannel;
207import android.view.InputDevice;
208import android.view.InputEvent;
209import android.view.InputEventReceiver;
210import android.view.KeyCharacterMap;
211import android.view.KeyCharacterMap.FallbackAction;
212import android.view.KeyEvent;
213import android.view.MotionEvent;
214import android.view.PointerIcon;
215import android.view.Surface;
216import android.view.View;
217import android.view.ViewConfiguration;
218import android.view.WindowManager;
219import android.view.WindowManager.LayoutParams;
220import android.view.WindowManagerGlobal;
221import android.view.WindowManagerInternal;
222import android.view.WindowManagerInternal.AppTransitionListener;
223import android.view.WindowManagerPolicy;
224import android.view.accessibility.AccessibilityEvent;
225import android.view.accessibility.AccessibilityManager;
226import android.view.animation.Animation;
227import android.view.animation.AnimationSet;
228import android.view.animation.AnimationUtils;
229import android.view.autofill.AutofillManagerInternal;
230import android.view.inputmethod.InputMethodManagerInternal;
231
232import com.android.internal.R;
233import com.android.internal.annotations.GuardedBy;
234import com.android.internal.logging.MetricsLogger;
235import com.android.internal.policy.IKeyguardDismissCallback;
236import com.android.internal.policy.IShortcutService;
237import com.android.internal.policy.PhoneWindow;
238import com.android.internal.statusbar.IStatusBarService;
239import com.android.internal.util.ScreenShapeHelper;
240import com.android.internal.widget.PointerLocationView;
241import com.android.server.GestureLauncherService;
242import com.android.server.LocalServices;
243import com.android.server.SystemServiceManager;
244import com.android.server.policy.keyguard.KeyguardServiceDelegate;
245import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener;
246import com.android.server.policy.keyguard.KeyguardStateMonitor.StateCallback;
247import com.android.server.statusbar.StatusBarManagerInternal;
248import com.android.server.vr.VrManagerInternal;
249import com.android.server.wm.AppTransition;
250
251import java.io.File;
252import java.io.FileReader;
253import java.io.IOException;
254import java.io.PrintWriter;
255import java.util.List;
256
257/**
258 * WindowManagerPolicy implementation for the Android phone UI.  This
259 * introduces a new method suffix, Lp, for an internal lock of the
260 * PhoneWindowManager.  This is used to protect some internal state, and
261 * can be acquired with either the Lw and Li lock held, so has the restrictions
262 * of both of those when held.
263 */
264public class PhoneWindowManager implements WindowManagerPolicy {
265    static final String TAG = "WindowManager";
266    static final boolean DEBUG = false;
267    static final boolean localLOGV = false;
268    static final boolean DEBUG_INPUT = false;
269    static final boolean DEBUG_KEYGUARD = false;
270    static final boolean DEBUG_LAYOUT = false;
271    static final boolean DEBUG_SPLASH_SCREEN = false;
272    static final boolean DEBUG_WAKEUP = false;
273    static final boolean SHOW_SPLASH_SCREENS = true;
274
275    // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
276    // No longer recommended for desk docks;
277    static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
278
279    // Whether to allow devices placed in vr headset viewers to have an alternative Home intent.
280    static final boolean ENABLE_VR_HEADSET_HOME_CAPTURE = true;
281
282    static final boolean ALTERNATE_CAR_MODE_NAV_SIZE = false;
283
284    static final int SHORT_PRESS_POWER_NOTHING = 0;
285    static final int SHORT_PRESS_POWER_GO_TO_SLEEP = 1;
286    static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2;
287    static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3;
288    static final int SHORT_PRESS_POWER_GO_HOME = 4;
289    static final int SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME = 5;
290
291    static final int LONG_PRESS_POWER_NOTHING = 0;
292    static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
293    static final int LONG_PRESS_POWER_SHUT_OFF = 2;
294    static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
295
296    static final int LONG_PRESS_BACK_NOTHING = 0;
297    static final int LONG_PRESS_BACK_GO_TO_VOICE_ASSIST = 1;
298
299    static final int MULTI_PRESS_POWER_NOTHING = 0;
300    static final int MULTI_PRESS_POWER_THEATER_MODE = 1;
301    static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2;
302
303    // Number of presses needed before we induce panic press behavior on the back button
304    static final int PANIC_PRESS_BACK_COUNT = 4;
305    static final int PANIC_PRESS_BACK_NOTHING = 0;
306    static final int PANIC_PRESS_BACK_HOME = 1;
307
308    // These need to match the documentation/constant in
309    // core/res/res/values/config.xml
310    static final int LONG_PRESS_HOME_NOTHING = 0;
311    static final int LONG_PRESS_HOME_ALL_APPS = 1;
312    static final int LONG_PRESS_HOME_ASSIST = 2;
313    static final int LAST_LONG_PRESS_HOME_BEHAVIOR = LONG_PRESS_HOME_ASSIST;
314
315    static final int DOUBLE_TAP_HOME_NOTHING = 0;
316    static final int DOUBLE_TAP_HOME_RECENT_SYSTEM_UI = 1;
317
318    static final int SHORT_PRESS_WINDOW_NOTHING = 0;
319    static final int SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE = 1;
320
321    static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP = 0;
322    static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME = 1;
323
324    static final int PENDING_KEY_NULL = -1;
325
326    // Controls navigation bar opacity depending on which workspace stacks are currently
327    // visible.
328    // Nav bar is always opaque when either the freeform stack or docked stack is visible.
329    static final int NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED = 0;
330    // Nav bar is always translucent when the freeform stack is visible, otherwise always opaque.
331    static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1;
332
333    static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
334    static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
335    static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
336    static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
337    static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";
338    static public final String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot";
339
340    /**
341     * These are the system UI flags that, when changing, can cause the layout
342     * of the screen to change.
343     */
344    static final int SYSTEM_UI_CHANGING_LAYOUT =
345              View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
346            | View.SYSTEM_UI_FLAG_FULLSCREEN
347            | View.STATUS_BAR_TRANSLUCENT
348            | View.NAVIGATION_BAR_TRANSLUCENT
349            | View.STATUS_BAR_TRANSPARENT
350            | View.NAVIGATION_BAR_TRANSPARENT;
351
352    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
353            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
354            .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
355            .build();
356
357    // The panic gesture may become active only after the keyguard is dismissed and the immersive
358    // app shows again. If that doesn't happen for 30s we drop the gesture.
359    private static final long PANIC_GESTURE_EXPIRATION = 30000;
360
361    private static final String SYSUI_PACKAGE = "com.android.systemui";
362    private static final String SYSUI_SCREENSHOT_SERVICE =
363            "com.android.systemui.screenshot.TakeScreenshotService";
364    private static final String SYSUI_SCREENSHOT_ERROR_RECEIVER =
365            "com.android.systemui.screenshot.ScreenshotServiceErrorReceiver";
366
367    /**
368     * Keyguard stuff
369     */
370    private boolean mKeyguardDrawnOnce;
371
372    /* Table of Application Launch keys.  Maps from key codes to intent categories.
373     *
374     * These are special keys that are used to launch particular kinds of applications,
375     * such as a web browser.  HID defines nearly a hundred of them in the Consumer (0x0C)
376     * usage page.  We don't support quite that many yet...
377     */
378    static SparseArray<String> sApplicationLaunchKeyCategories;
379    static {
380        sApplicationLaunchKeyCategories = new SparseArray<String>();
381        sApplicationLaunchKeyCategories.append(
382                KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER);
383        sApplicationLaunchKeyCategories.append(
384                KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL);
385        sApplicationLaunchKeyCategories.append(
386                KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS);
387        sApplicationLaunchKeyCategories.append(
388                KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR);
389        sApplicationLaunchKeyCategories.append(
390                KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC);
391        sApplicationLaunchKeyCategories.append(
392                KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
393    }
394
395    /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
396    static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;
397
398    /** Amount of time (in milliseconds) a toast window can be shown. */
399    public static final int TOAST_WINDOW_TIMEOUT = 3500; // 3.5 seconds
400
401    /**
402     * Lock protecting internal state.  Must not call out into window
403     * manager with lock held.  (This lock will be acquired in places
404     * where the window manager is calling in with its own lock held.)
405     */
406    private final Object mLock = new Object();
407
408    Context mContext;
409    IWindowManager mWindowManager;
410    WindowManagerFuncs mWindowManagerFuncs;
411    WindowManagerInternal mWindowManagerInternal;
412    PowerManager mPowerManager;
413    ActivityManagerInternal mActivityManagerInternal;
414    AutofillManagerInternal mAutofillManagerInternal;
415    InputManagerInternal mInputManagerInternal;
416    InputMethodManagerInternal mInputMethodManagerInternal;
417    DreamManagerInternal mDreamManagerInternal;
418    PowerManagerInternal mPowerManagerInternal;
419    IStatusBarService mStatusBarService;
420    StatusBarManagerInternal mStatusBarManagerInternal;
421    boolean mPreloadedRecentApps;
422    final Object mServiceAquireLock = new Object();
423    Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
424    SearchManager mSearchManager;
425    AccessibilityManager mAccessibilityManager;
426    BurnInProtectionHelper mBurnInProtectionHelper;
427    AppOpsManager mAppOpsManager;
428    private boolean mHasFeatureWatch;
429    private boolean mHasFeatureLeanback;
430
431    // Assigned on main thread, accessed on UI thread
432    volatile VrManagerInternal mVrManagerInternal;
433
434    // Vibrator pattern for haptic feedback of a long press.
435    long[] mLongPressVibePattern;
436
437    // Vibrator pattern for a short vibration when tapping on a day/month/year date of a Calendar.
438    long[] mCalendarDateVibePattern;
439
440    // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
441    long[] mSafeModeEnabledVibePattern;
442
443    /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
444    boolean mEnableShiftMenuBugReports = false;
445
446    /** Controller that supports enabling an AccessibilityService by holding down the volume keys */
447    private AccessibilityShortcutController mAccessibilityShortcutController;
448
449    boolean mSafeMode;
450    WindowState mStatusBar = null;
451    int mStatusBarHeight;
452    WindowState mNavigationBar = null;
453    boolean mHasNavigationBar = false;
454    boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?
455    int mNavigationBarPosition = NAV_BAR_BOTTOM;
456    int[] mNavigationBarHeightForRotationDefault = new int[4];
457    int[] mNavigationBarWidthForRotationDefault = new int[4];
458    int[] mNavigationBarHeightForRotationInCarMode = new int[4];
459    int[] mNavigationBarWidthForRotationInCarMode = new int[4];
460
461    private LongSparseArray<IShortcutService> mShortcutKeyServices = new LongSparseArray<>();
462
463    // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
464    // This is for car dock and this is updated from resource.
465    private boolean mEnableCarDockHomeCapture = true;
466
467    boolean mBootMessageNeedsHiding;
468    KeyguardServiceDelegate mKeyguardDelegate;
469    private boolean mKeyguardBound;
470    final Runnable mWindowManagerDrawCallback = new Runnable() {
471        @Override
472        public void run() {
473            if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!");
474            mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);
475        }
476    };
477    final DrawnListener mKeyguardDrawnCallback = new DrawnListener() {
478        @Override
479        public void onDrawn() {
480            if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn.");
481            mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
482        }
483    };
484
485    GlobalActions mGlobalActions;
486    Handler mHandler;
487    WindowState mLastInputMethodWindow = null;
488    WindowState mLastInputMethodTargetWindow = null;
489
490    // FIXME This state is shared between the input reader and handler thread.
491    // Technically it's broken and buggy but it has been like this for many years
492    // and we have not yet seen any problems.  Someday we'll rewrite this logic
493    // so that only one thread is involved in handling input policy.  Unfortunately
494    // it's on a critical path for power management so we can't just post the work to the
495    // handler thread.  We'll need to resolve this someday by teaching the input dispatcher
496    // to hold wakelocks during dispatch and eliminating the critical path.
497    volatile boolean mPowerKeyHandled;
498    volatile boolean mBackKeyHandled;
499    volatile boolean mBeganFromNonInteractive;
500    volatile int mPowerKeyPressCounter;
501    volatile int mBackKeyPressCounter;
502    volatile boolean mEndCallKeyHandled;
503    volatile boolean mCameraGestureTriggeredDuringGoingToSleep;
504    volatile boolean mGoingToSleep;
505    volatile boolean mRequestedOrGoingToSleep;
506    volatile boolean mRecentsVisible;
507    volatile boolean mPictureInPictureVisible;
508    // Written by vr manager thread, only read in this class.
509    volatile private boolean mPersistentVrModeEnabled;
510    volatile private boolean mDismissImeOnBackKeyPressed;
511
512    // Used to hold the last user key used to wake the device.  This helps us prevent up events
513    // from being passed to the foregrounded app without a corresponding down event
514    volatile int mPendingWakeKey = PENDING_KEY_NULL;
515
516    int mRecentAppsHeldModifiers;
517    boolean mLanguageSwitchKeyPressed;
518
519    int mLidState = LID_ABSENT;
520    int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT;
521    boolean mHaveBuiltInKeyboard;
522
523    boolean mSystemReady;
524    boolean mSystemBooted;
525    boolean mHdmiPlugged;
526    HdmiControl mHdmiControl;
527    IUiModeManager mUiModeManager;
528    int mUiMode;
529    int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
530    int mLidOpenRotation;
531    int mCarDockRotation;
532    int mDeskDockRotation;
533    int mUndockedHdmiRotation;
534    int mDemoHdmiRotation;
535    boolean mDemoHdmiRotationLock;
536    int mDemoRotation;
537    boolean mDemoRotationLock;
538
539    boolean mWakeGestureEnabledSetting;
540    MyWakeGestureListener mWakeGestureListener;
541
542    // Default display does not rotate, apps that require non-default orientation will have to
543    // have the orientation emulated.
544    private boolean mForceDefaultOrientation = false;
545
546    int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
547    int mUserRotation = Surface.ROTATION_0;
548    boolean mAccelerometerDefault;
549
550    boolean mSupportAutoRotation;
551    int mAllowAllRotations = -1;
552    boolean mCarDockEnablesAccelerometer;
553    boolean mDeskDockEnablesAccelerometer;
554    int mLidKeyboardAccessibility;
555    int mLidNavigationAccessibility;
556    boolean mLidControlsScreenLock;
557    boolean mLidControlsSleep;
558    int mShortPressOnPowerBehavior;
559    int mLongPressOnPowerBehavior;
560    int mDoublePressOnPowerBehavior;
561    int mTriplePressOnPowerBehavior;
562    int mLongPressOnBackBehavior;
563    int mPanicPressOnBackBehavior;
564    int mShortPressOnSleepBehavior;
565    int mShortPressWindowBehavior;
566    volatile boolean mAwake;
567    boolean mScreenOnEarly;
568    boolean mScreenOnFully;
569    ScreenOnListener mScreenOnListener;
570    boolean mKeyguardDrawComplete;
571    boolean mWindowManagerDrawComplete;
572    boolean mOrientationSensorEnabled = false;
573    int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
574    boolean mHasSoftInput = false;
575    boolean mTranslucentDecorEnabled = true;
576    boolean mUseTvRouting;
577
578    private boolean mHandleVolumeKeysInWM;
579
580    int mPointerLocationMode = 0; // guarded by mLock
581
582    // The last window we were told about in focusChanged.
583    WindowState mFocusedWindow;
584    IApplicationToken mFocusedApp;
585
586    PointerLocationView mPointerLocationView;
587
588    // The current size of the screen; really; extends into the overscan area of
589    // the screen and doesn't account for any system elements like the status bar.
590    int mOverscanScreenLeft, mOverscanScreenTop;
591    int mOverscanScreenWidth, mOverscanScreenHeight;
592    // The current visible size of the screen; really; (ir)regardless of whether the status
593    // bar can be hidden but not extending into the overscan area.
594    int mUnrestrictedScreenLeft, mUnrestrictedScreenTop;
595    int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight;
596    // Like mOverscanScreen*, but allowed to move into the overscan region where appropriate.
597    int mRestrictedOverscanScreenLeft, mRestrictedOverscanScreenTop;
598    int mRestrictedOverscanScreenWidth, mRestrictedOverscanScreenHeight;
599    // The current size of the screen; these may be different than (0,0)-(dw,dh)
600    // if the status bar can't be hidden; in that case it effectively carves out
601    // that area of the display from all other windows.
602    int mRestrictedScreenLeft, mRestrictedScreenTop;
603    int mRestrictedScreenWidth, mRestrictedScreenHeight;
604    // During layout, the current screen borders accounting for any currently
605    // visible system UI elements.
606    int mSystemLeft, mSystemTop, mSystemRight, mSystemBottom;
607    // For applications requesting stable content insets, these are them.
608    int mStableLeft, mStableTop, mStableRight, mStableBottom;
609    // For applications requesting stable content insets but have also set the
610    // fullscreen window flag, these are the stable dimensions without the status bar.
611    int mStableFullscreenLeft, mStableFullscreenTop;
612    int mStableFullscreenRight, mStableFullscreenBottom;
613    // During layout, the current screen borders with all outer decoration
614    // (status bar, input method dock) accounted for.
615    int mCurLeft, mCurTop, mCurRight, mCurBottom;
616    // During layout, the frame in which content should be displayed
617    // to the user, accounting for all screen decoration except for any
618    // space they deem as available for other content.  This is usually
619    // the same as mCur*, but may be larger if the screen decor has supplied
620    // content insets.
621    int mContentLeft, mContentTop, mContentRight, mContentBottom;
622    // During layout, the frame in which voice content should be displayed
623    // to the user, accounting for all screen decoration except for any
624    // space they deem as available for other content.
625    int mVoiceContentLeft, mVoiceContentTop, mVoiceContentRight, mVoiceContentBottom;
626    // During layout, the current screen borders along which input method
627    // windows are placed.
628    int mDockLeft, mDockTop, mDockRight, mDockBottom;
629    // During layout, the layer at which the doc window is placed.
630    int mDockLayer;
631    // During layout, this is the layer of the status bar.
632    int mStatusBarLayer;
633    int mLastSystemUiFlags;
634    // Bits that we are in the process of clearing, so we want to prevent
635    // them from being set by applications until everything has been updated
636    // to have them clear.
637    int mResettingSystemUiFlags = 0;
638    // Bits that we are currently always keeping cleared.
639    int mForceClearedSystemUiFlags = 0;
640    int mLastFullscreenStackSysUiFlags;
641    int mLastDockedStackSysUiFlags;
642    final Rect mNonDockedStackBounds = new Rect();
643    final Rect mDockedStackBounds = new Rect();
644    final Rect mLastNonDockedStackBounds = new Rect();
645    final Rect mLastDockedStackBounds = new Rect();
646
647    // What we last reported to system UI about whether the compatibility
648    // menu needs to be displayed.
649    boolean mLastFocusNeedsMenu = false;
650    // If nonzero, a panic gesture was performed at that time in uptime millis and is still pending.
651    private long mPendingPanicGestureUptime;
652
653    InputConsumer mInputConsumer = null;
654
655    static final Rect mTmpParentFrame = new Rect();
656    static final Rect mTmpDisplayFrame = new Rect();
657    static final Rect mTmpOverscanFrame = new Rect();
658    static final Rect mTmpContentFrame = new Rect();
659    static final Rect mTmpVisibleFrame = new Rect();
660    static final Rect mTmpDecorFrame = new Rect();
661    static final Rect mTmpStableFrame = new Rect();
662    static final Rect mTmpNavigationFrame = new Rect();
663    static final Rect mTmpOutsetFrame = new Rect();
664    private static final Rect mTmpRect = new Rect();
665
666    WindowState mTopFullscreenOpaqueWindowState;
667    WindowState mTopFullscreenOpaqueOrDimmingWindowState;
668    WindowState mTopDockedOpaqueWindowState;
669    WindowState mTopDockedOpaqueOrDimmingWindowState;
670    boolean mTopIsFullscreen;
671    boolean mForceStatusBar;
672    boolean mForceStatusBarFromKeyguard;
673    private boolean mForceStatusBarTransparent;
674    int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
675    boolean mForcingShowNavBar;
676    int mForcingShowNavBarLayer;
677
678    private boolean mPendingKeyguardOccluded;
679    private boolean mKeyguardOccludedChanged;
680
681    boolean mShowingDream;
682    private boolean mLastShowingDream;
683    boolean mDreamingLockscreen;
684    boolean mDreamingSleepTokenNeeded;
685    private boolean mWindowSleepTokenNeeded;
686    private boolean mLastWindowSleepTokenNeeded;
687
688    @GuardedBy("mHandler")
689    private SleepToken mWindowSleepToken;
690
691    SleepToken mDreamingSleepToken;
692    SleepToken mScreenOffSleepToken;
693    volatile boolean mKeyguardOccluded;
694    boolean mHomePressed;
695    boolean mHomeConsumed;
696    boolean mHomeDoubleTapPending;
697    Intent mHomeIntent;
698    Intent mCarDockIntent;
699    Intent mDeskDockIntent;
700    Intent mVrHeadsetHomeIntent;
701    boolean mSearchKeyShortcutPending;
702    boolean mConsumeSearchKeyUp;
703    boolean mAssistKeyLongPressed;
704    boolean mPendingMetaAction;
705    boolean mPendingCapsLockToggle;
706    int mMetaState;
707    int mInitialMetaState;
708    boolean mForceShowSystemBars;
709
710    // support for activating the lock screen while the screen is on
711    boolean mAllowLockscreenWhenOn;
712    int mLockScreenTimeout;
713    boolean mLockScreenTimerActive;
714
715    // Behavior of ENDCALL Button.  (See Settings.System.END_BUTTON_BEHAVIOR.)
716    int mEndcallBehavior;
717
718    // Behavior of POWER button while in-call and screen on.
719    // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
720    int mIncallPowerBehavior;
721
722    // Behavior of Back button while in-call and screen on
723    int mIncallBackBehavior;
724
725    Display mDisplay;
726
727    private int mDisplayRotation;
728
729    int mLandscapeRotation = 0;  // default landscape rotation
730    int mSeascapeRotation = 0;   // "other" landscape rotation, 180 degrees from mLandscapeRotation
731    int mPortraitRotation = 0;   // default portrait rotation
732    int mUpsideDownRotation = 0; // "other" portrait rotation
733
734    int mOverscanLeft = 0;
735    int mOverscanTop = 0;
736    int mOverscanRight = 0;
737    int mOverscanBottom = 0;
738
739    // What we do when the user long presses on home
740    private int mLongPressOnHomeBehavior;
741
742    // What we do when the user double-taps on home
743    private int mDoubleTapOnHomeBehavior;
744
745    // Allowed theater mode wake actions
746    private boolean mAllowTheaterModeWakeFromKey;
747    private boolean mAllowTheaterModeWakeFromPowerKey;
748    private boolean mAllowTheaterModeWakeFromMotion;
749    private boolean mAllowTheaterModeWakeFromMotionWhenNotDreaming;
750    private boolean mAllowTheaterModeWakeFromCameraLens;
751    private boolean mAllowTheaterModeWakeFromLidSwitch;
752    private boolean mAllowTheaterModeWakeFromWakeGesture;
753
754    // Whether to support long press from power button in non-interactive mode
755    private boolean mSupportLongPressPowerWhenNonInteractive;
756
757    // Whether to go to sleep entering theater mode from power button
758    private boolean mGoToSleepOnButtonPressTheaterMode;
759
760    // Screenshot trigger states
761    // Time to volume and power must be pressed within this interval of each other.
762    private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
763    // Increase the chord delay when taking a screenshot from the keyguard
764    private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f;
765    private boolean mScreenshotChordEnabled;
766    private boolean mScreenshotChordVolumeDownKeyTriggered;
767    private long mScreenshotChordVolumeDownKeyTime;
768    private boolean mScreenshotChordVolumeDownKeyConsumed;
769    private boolean mA11yShortcutChordVolumeUpKeyTriggered;
770    private long mA11yShortcutChordVolumeUpKeyTime;
771    private boolean mA11yShortcutChordVolumeUpKeyConsumed;
772
773    private boolean mScreenshotChordPowerKeyTriggered;
774    private long mScreenshotChordPowerKeyTime;
775
776    private static final long BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS = 1000;
777
778    private boolean mBugreportTvKey1Pressed;
779    private boolean mBugreportTvKey2Pressed;
780    private boolean mBugreportTvScheduled;
781
782    private boolean mAccessibilityTvKey1Pressed;
783    private boolean mAccessibilityTvKey2Pressed;
784    private boolean mAccessibilityTvScheduled;
785
786    /* The number of steps between min and max brightness */
787    private static final int BRIGHTNESS_STEPS = 10;
788
789    SettingsObserver mSettingsObserver;
790    ShortcutManager mShortcutManager;
791    PowerManager.WakeLock mBroadcastWakeLock;
792    PowerManager.WakeLock mPowerKeyWakeLock;
793    boolean mHavePendingMediaKeyRepeatWithWakeLock;
794
795    private int mCurrentUserId;
796
797    // Maps global key codes to the components that will handle them.
798    private GlobalKeyManager mGlobalKeyManager;
799
800    // Fallback actions by key code.
801    private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions =
802            new SparseArray<KeyCharacterMap.FallbackAction>();
803
804    private final LogDecelerateInterpolator mLogDecelerateInterpolator
805            = new LogDecelerateInterpolator(100, 0);
806
807    private final MutableBoolean mTmpBoolean = new MutableBoolean(false);
808
809    private static final int MSG_ENABLE_POINTER_LOCATION = 1;
810    private static final int MSG_DISABLE_POINTER_LOCATION = 2;
811    private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
812    private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
813    private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
814    private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6;
815    private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7;
816    private static final int MSG_DISPATCH_SHOW_RECENTS = 9;
817    private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10;
818    private static final int MSG_HIDE_BOOT_MESSAGE = 11;
819    private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12;
820    private static final int MSG_POWER_DELAYED_PRESS = 13;
821    private static final int MSG_POWER_LONG_PRESS = 14;
822    private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 15;
823    private static final int MSG_REQUEST_TRANSIENT_BARS = 16;
824    private static final int MSG_SHOW_PICTURE_IN_PICTURE_MENU = 17;
825    private static final int MSG_BACK_LONG_PRESS = 18;
826    private static final int MSG_DISPOSE_INPUT_CONSUMER = 19;
827    private static final int MSG_BACK_DELAYED_PRESS = 20;
828    private static final int MSG_ACCESSIBILITY_SHORTCUT = 21;
829    private static final int MSG_BUGREPORT_TV = 22;
830    private static final int MSG_ACCESSIBILITY_TV = 23;
831    private static final int MSG_DISPATCH_BACK_KEY_TO_AUTOFILL = 24;
832    private static final int MSG_SYSTEM_KEY_PRESS = 25;
833    private static final int MSG_HANDLE_ALL_APPS = 26;
834
835    private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
836    private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
837
838    private class PolicyHandler extends Handler {
839        @Override
840        public void handleMessage(Message msg) {
841            switch (msg.what) {
842                case MSG_ENABLE_POINTER_LOCATION:
843                    enablePointerLocation();
844                    break;
845                case MSG_DISABLE_POINTER_LOCATION:
846                    disablePointerLocation();
847                    break;
848                case MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK:
849                    dispatchMediaKeyWithWakeLock((KeyEvent)msg.obj);
850                    break;
851                case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK:
852                    dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj);
853                    break;
854                case MSG_DISPATCH_SHOW_RECENTS:
855                    showRecentApps(false, msg.arg1 != 0);
856                    break;
857                case MSG_DISPATCH_SHOW_GLOBAL_ACTIONS:
858                    showGlobalActionsInternal();
859                    break;
860                case MSG_KEYGUARD_DRAWN_COMPLETE:
861                    if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete");
862                    finishKeyguardDrawn();
863                    break;
864                case MSG_KEYGUARD_DRAWN_TIMEOUT:
865                    Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete");
866                    finishKeyguardDrawn();
867                    break;
868                case MSG_WINDOW_MANAGER_DRAWN_COMPLETE:
869                    if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete");
870                    finishWindowsDrawn();
871                    break;
872                case MSG_HIDE_BOOT_MESSAGE:
873                    handleHideBootMessage();
874                    break;
875                case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK:
876                    launchVoiceAssistWithWakeLock(msg.arg1 != 0);
877                    break;
878                case MSG_POWER_DELAYED_PRESS:
879                    powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2);
880                    finishPowerKeyPress();
881                    break;
882                case MSG_POWER_LONG_PRESS:
883                    powerLongPress();
884                    break;
885                case MSG_UPDATE_DREAMING_SLEEP_TOKEN:
886                    updateDreamingSleepToken(msg.arg1 != 0);
887                    break;
888                case MSG_REQUEST_TRANSIENT_BARS:
889                    WindowState targetBar = (msg.arg1 == MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS) ?
890                            mStatusBar : mNavigationBar;
891                    if (targetBar != null) {
892                        requestTransientBars(targetBar);
893                    }
894                    break;
895                case MSG_SHOW_PICTURE_IN_PICTURE_MENU:
896                    showPictureInPictureMenuInternal();
897                    break;
898                case MSG_BACK_LONG_PRESS:
899                    backLongPress();
900                    finishBackKeyPress();
901                    break;
902                case MSG_DISPOSE_INPUT_CONSUMER:
903                    disposeInputConsumer((InputConsumer) msg.obj);
904                    break;
905                case MSG_BACK_DELAYED_PRESS:
906                    backMultiPressAction((Long) msg.obj, msg.arg1);
907                    finishBackKeyPress();
908                    break;
909                case MSG_ACCESSIBILITY_SHORTCUT:
910                    accessibilityShortcutActivated();
911                    break;
912                case MSG_BUGREPORT_TV:
913                    takeBugreport();
914                    break;
915                case MSG_ACCESSIBILITY_TV:
916                    if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(false)) {
917                        accessibilityShortcutActivated();
918                    }
919                    break;
920                case MSG_DISPATCH_BACK_KEY_TO_AUTOFILL:
921                    mAutofillManagerInternal.onBackKeyPressed();
922                    break;
923                case MSG_SYSTEM_KEY_PRESS:
924                    sendSystemKeyToStatusBar(msg.arg1);
925                    break;
926                case MSG_HANDLE_ALL_APPS:
927                    launchAllAppsAction();
928                    break;
929            }
930        }
931    }
932
933    private UEventObserver mHDMIObserver = new UEventObserver() {
934        @Override
935        public void onUEvent(UEventObserver.UEvent event) {
936            setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
937        }
938    };
939
940    class SettingsObserver extends ContentObserver {
941        SettingsObserver(Handler handler) {
942            super(handler);
943        }
944
945        void observe() {
946            // Observe all users' changes
947            ContentResolver resolver = mContext.getContentResolver();
948            resolver.registerContentObserver(Settings.System.getUriFor(
949                    Settings.System.END_BUTTON_BEHAVIOR), false, this,
950                    UserHandle.USER_ALL);
951            resolver.registerContentObserver(Settings.Secure.getUriFor(
952                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this,
953                    UserHandle.USER_ALL);
954            resolver.registerContentObserver(Settings.Secure.getUriFor(
955                    Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR), false, this,
956                    UserHandle.USER_ALL);
957            resolver.registerContentObserver(Settings.Secure.getUriFor(
958                    Settings.Secure.WAKE_GESTURE_ENABLED), false, this,
959                    UserHandle.USER_ALL);
960            resolver.registerContentObserver(Settings.System.getUriFor(
961                    Settings.System.ACCELEROMETER_ROTATION), false, this,
962                    UserHandle.USER_ALL);
963            resolver.registerContentObserver(Settings.System.getUriFor(
964                    Settings.System.USER_ROTATION), false, this,
965                    UserHandle.USER_ALL);
966            resolver.registerContentObserver(Settings.System.getUriFor(
967                    Settings.System.SCREEN_OFF_TIMEOUT), false, this,
968                    UserHandle.USER_ALL);
969            resolver.registerContentObserver(Settings.System.getUriFor(
970                    Settings.System.POINTER_LOCATION), false, this,
971                    UserHandle.USER_ALL);
972            resolver.registerContentObserver(Settings.Secure.getUriFor(
973                    Settings.Secure.DEFAULT_INPUT_METHOD), false, this,
974                    UserHandle.USER_ALL);
975            resolver.registerContentObserver(Settings.Secure.getUriFor(
976                    Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this,
977                    UserHandle.USER_ALL);
978            resolver.registerContentObserver(Settings.Global.getUriFor(
979                    Settings.Global.POLICY_CONTROL), false, this,
980                    UserHandle.USER_ALL);
981            updateSettings();
982        }
983
984        @Override public void onChange(boolean selfChange) {
985            updateSettings();
986            updateRotation(false);
987        }
988    }
989
990    class MyWakeGestureListener extends WakeGestureListener {
991        MyWakeGestureListener(Context context, Handler handler) {
992            super(context, handler);
993        }
994
995        @Override
996        public void onWakeUp() {
997            synchronized (mLock) {
998                if (shouldEnableWakeGestureLp()) {
999                    performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
1000                    wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture,
1001                            "android.policy:GESTURE");
1002                }
1003            }
1004        }
1005    }
1006
1007    class MyOrientationListener extends WindowOrientationListener {
1008        private final Runnable mUpdateRotationRunnable = new Runnable() {
1009            @Override
1010            public void run() {
1011                // send interaction hint to improve redraw performance
1012                mPowerManagerInternal.powerHint(PowerHint.INTERACTION, 0);
1013                updateRotation(false);
1014            }
1015        };
1016
1017        MyOrientationListener(Context context, Handler handler) {
1018            super(context, handler);
1019        }
1020
1021        @Override
1022        public void onProposedRotationChanged(int rotation) {
1023            if (localLOGV) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
1024            mHandler.post(mUpdateRotationRunnable);
1025        }
1026    }
1027    MyOrientationListener mOrientationListener;
1028
1029    final IPersistentVrStateCallbacks mPersistentVrModeListener =
1030            new IPersistentVrStateCallbacks.Stub() {
1031        @Override
1032        public void onPersistentVrStateChanged(boolean enabled) {
1033            mPersistentVrModeEnabled = enabled;
1034        }
1035    };
1036
1037    private final StatusBarController mStatusBarController = new StatusBarController();
1038
1039    private final BarController mNavigationBarController = new BarController("NavigationBar",
1040            View.NAVIGATION_BAR_TRANSIENT,
1041            View.NAVIGATION_BAR_UNHIDE,
1042            View.NAVIGATION_BAR_TRANSLUCENT,
1043            StatusBarManager.WINDOW_NAVIGATION_BAR,
1044            WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
1045            View.NAVIGATION_BAR_TRANSPARENT);
1046
1047    private final BarController.OnBarVisibilityChangedListener mNavBarVisibilityListener =
1048            new BarController.OnBarVisibilityChangedListener() {
1049        @Override
1050        public void onBarVisibilityChanged(boolean visible) {
1051            mAccessibilityManager.notifyAccessibilityButtonVisibilityChanged(visible);
1052        }
1053    };
1054
1055    private final Runnable mAcquireSleepTokenRunnable = () -> {
1056        if (mWindowSleepToken != null) {
1057            return;
1058        }
1059        mWindowSleepToken = mActivityManagerInternal.acquireSleepToken("WindowSleepToken",
1060                DEFAULT_DISPLAY);
1061    };
1062
1063    private final Runnable mReleaseSleepTokenRunnable = () -> {
1064        if (mWindowSleepToken == null) {
1065            return;
1066        }
1067        mWindowSleepToken.release();
1068        mWindowSleepToken = null;
1069    };
1070
1071    private ImmersiveModeConfirmation mImmersiveModeConfirmation;
1072
1073    private SystemGesturesPointerEventListener mSystemGestures;
1074
1075    IStatusBarService getStatusBarService() {
1076        synchronized (mServiceAquireLock) {
1077            if (mStatusBarService == null) {
1078                mStatusBarService = IStatusBarService.Stub.asInterface(
1079                        ServiceManager.getService("statusbar"));
1080            }
1081            return mStatusBarService;
1082        }
1083    }
1084
1085    StatusBarManagerInternal getStatusBarManagerInternal() {
1086        synchronized (mServiceAquireLock) {
1087            if (mStatusBarManagerInternal == null) {
1088                mStatusBarManagerInternal =
1089                        LocalServices.getService(StatusBarManagerInternal.class);
1090            }
1091            return mStatusBarManagerInternal;
1092        }
1093    }
1094
1095    /*
1096     * We always let the sensor be switched on by default except when
1097     * the user has explicitly disabled sensor based rotation or when the
1098     * screen is switched off.
1099     */
1100    boolean needSensorRunningLp() {
1101        if (mSupportAutoRotation) {
1102            if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
1103                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
1104                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
1105                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
1106                // If the application has explicitly requested to follow the
1107                // orientation, then we need to turn the sensor on.
1108                return true;
1109            }
1110        }
1111        if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
1112                (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
1113                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
1114                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
1115            // enable accelerometer if we are docked in a dock that enables accelerometer
1116            // orientation management,
1117            return true;
1118        }
1119        if (mUserRotationMode == USER_ROTATION_LOCKED) {
1120            // If the setting for using the sensor by default is enabled, then
1121            // we will always leave it on.  Note that the user could go to
1122            // a window that forces an orientation that does not use the
1123            // sensor and in theory we could turn it off... however, when next
1124            // turning it on we won't have a good value for the current
1125            // orientation for a little bit, which can cause orientation
1126            // changes to lag, so we'd like to keep it always on.  (It will
1127            // still be turned off when the screen is off.)
1128            return false;
1129        }
1130        return mSupportAutoRotation;
1131    }
1132
1133    /*
1134     * Various use cases for invoking this function
1135     * screen turning off, should always disable listeners if already enabled
1136     * screen turned on and current app has sensor based orientation, enable listeners
1137     * if not already enabled
1138     * screen turned on and current app does not have sensor orientation, disable listeners if
1139     * already enabled
1140     * screen turning on and current app has sensor based orientation, enable listeners if needed
1141     * screen turning on and current app has nosensor based orientation, do nothing
1142     */
1143    void updateOrientationListenerLp() {
1144        if (!mOrientationListener.canDetectOrientation()) {
1145            // If sensor is turned off or nonexistent for some reason
1146            return;
1147        }
1148        // Could have been invoked due to screen turning on or off or
1149        // change of the currently visible window's orientation.
1150        if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly
1151                + ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation
1152                + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled
1153                + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
1154                + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
1155
1156        boolean disable = true;
1157        // Note: We postpone the rotating of the screen until the keyguard as well as the
1158        // window manager have reported a draw complete or the keyguard is going away in dismiss
1159        // mode.
1160        if (mScreenOnEarly && mAwake && ((mKeyguardDrawComplete && mWindowManagerDrawComplete))) {
1161            if (needSensorRunningLp()) {
1162                disable = false;
1163                //enable listener if not already enabled
1164                if (!mOrientationSensorEnabled) {
1165                    // Don't clear the current sensor orientation if the keyguard is going away in
1166                    // dismiss mode. This allows window manager to use the last sensor reading to
1167                    // determine the orientation vs. falling back to the last known orientation if
1168                    // the sensor reading was cleared which can cause it to relaunch the app that
1169                    // will show in the wrong orientation first before correcting leading to app
1170                    // launch delays.
1171                    mOrientationListener.enable(true /* clearCurrentRotation */);
1172                    if(localLOGV) Slog.v(TAG, "Enabling listeners");
1173                    mOrientationSensorEnabled = true;
1174                }
1175            }
1176        }
1177        //check if sensors need to be disabled
1178        if (disable && mOrientationSensorEnabled) {
1179            mOrientationListener.disable();
1180            if(localLOGV) Slog.v(TAG, "Disabling listeners");
1181            mOrientationSensorEnabled = false;
1182        }
1183    }
1184
1185    private void interceptBackKeyDown() {
1186        MetricsLogger.count(mContext, "key_back_down", 1);
1187        // Reset back key state for long press
1188        mBackKeyHandled = false;
1189
1190        // Cancel multi-press detection timeout.
1191        if (hasPanicPressOnBackBehavior()) {
1192            if (mBackKeyPressCounter != 0
1193                    && mBackKeyPressCounter < PANIC_PRESS_BACK_COUNT) {
1194                mHandler.removeMessages(MSG_BACK_DELAYED_PRESS);
1195            }
1196        }
1197
1198        if (hasLongPressOnBackBehavior()) {
1199            Message msg = mHandler.obtainMessage(MSG_BACK_LONG_PRESS);
1200            msg.setAsynchronous(true);
1201            mHandler.sendMessageDelayed(msg,
1202                    ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1203        }
1204    }
1205
1206    // returns true if the key was handled and should not be passed to the user
1207    private boolean interceptBackKeyUp(KeyEvent event) {
1208        // Cache handled state
1209        boolean handled = mBackKeyHandled;
1210
1211        if (hasPanicPressOnBackBehavior()) {
1212            // Check for back key panic press
1213            ++mBackKeyPressCounter;
1214
1215            final long eventTime = event.getDownTime();
1216
1217            if (mBackKeyPressCounter <= PANIC_PRESS_BACK_COUNT) {
1218                // This could be a multi-press.  Wait a little bit longer to confirm.
1219                Message msg = mHandler.obtainMessage(MSG_BACK_DELAYED_PRESS,
1220                    mBackKeyPressCounter, 0, eventTime);
1221                msg.setAsynchronous(true);
1222                mHandler.sendMessageDelayed(msg, ViewConfiguration.getMultiPressTimeout());
1223            }
1224        }
1225
1226        // Reset back long press state
1227        cancelPendingBackKeyAction();
1228
1229        if (mHasFeatureWatch) {
1230            TelecomManager telecomManager = getTelecommService();
1231
1232            if (telecomManager != null) {
1233                if (telecomManager.isRinging()) {
1234                    // Pressing back while there's a ringing incoming
1235                    // call should silence the ringer.
1236                    telecomManager.silenceRinger();
1237
1238                    // It should not prevent navigating away
1239                    return false;
1240                } else if (
1241                    (mIncallBackBehavior & Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_HANGUP) != 0
1242                        && telecomManager.isInCall()) {
1243                    // Otherwise, if "Back button ends call" is enabled,
1244                    // the Back button will hang up any current active call.
1245                    return telecomManager.endCall();
1246                }
1247            }
1248        }
1249
1250        if (mAutofillManagerInternal != null && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
1251            mHandler.sendMessage(mHandler.obtainMessage(MSG_DISPATCH_BACK_KEY_TO_AUTOFILL));
1252        }
1253
1254        return handled;
1255    }
1256
1257    private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
1258        // Hold a wake lock until the power key is released.
1259        if (!mPowerKeyWakeLock.isHeld()) {
1260            mPowerKeyWakeLock.acquire();
1261        }
1262
1263        // Cancel multi-press detection timeout.
1264        if (mPowerKeyPressCounter != 0) {
1265            mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);
1266        }
1267
1268        // Detect user pressing the power button in panic when an application has
1269        // taken over the whole screen.
1270        boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
1271                SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags),
1272                isNavBarEmpty(mLastSystemUiFlags));
1273        if (panic) {
1274            mHandler.post(mHiddenNavPanic);
1275        }
1276
1277        // Latch power key state to detect screenshot chord.
1278        if (interactive && !mScreenshotChordPowerKeyTriggered
1279                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
1280            mScreenshotChordPowerKeyTriggered = true;
1281            mScreenshotChordPowerKeyTime = event.getDownTime();
1282            interceptScreenshotChord();
1283        }
1284
1285        // Stop ringing or end call if configured to do so when power is pressed.
1286        TelecomManager telecomManager = getTelecommService();
1287        boolean hungUp = false;
1288        if (telecomManager != null) {
1289            if (telecomManager.isRinging()) {
1290                // Pressing Power while there's a ringing incoming
1291                // call should silence the ringer.
1292                telecomManager.silenceRinger();
1293            } else if ((mIncallPowerBehavior
1294                    & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
1295                    && telecomManager.isInCall() && interactive) {
1296                // Otherwise, if "Power button ends call" is enabled,
1297                // the Power button will hang up any current active call.
1298                hungUp = telecomManager.endCall();
1299            }
1300        }
1301
1302        GestureLauncherService gestureService = LocalServices.getService(
1303                GestureLauncherService.class);
1304        boolean gesturedServiceIntercepted = false;
1305        if (gestureService != null) {
1306            gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive,
1307                    mTmpBoolean);
1308            if (mTmpBoolean.value && mRequestedOrGoingToSleep) {
1309                mCameraGestureTriggeredDuringGoingToSleep = true;
1310            }
1311        }
1312
1313        // Inform the StatusBar; but do not allow it to consume the event.
1314        sendSystemKeyToStatusBarAsync(event.getKeyCode());
1315
1316        // If the power key has still not yet been handled, then detect short
1317        // press, long press, or multi press and decide what to do.
1318        mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
1319                || mA11yShortcutChordVolumeUpKeyTriggered || gesturedServiceIntercepted;
1320        if (!mPowerKeyHandled) {
1321            if (interactive) {
1322                // When interactive, we're already awake.
1323                // Wait for a long press or for the button to be released to decide what to do.
1324                if (hasLongPressOnPowerBehavior()) {
1325                    Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
1326                    msg.setAsynchronous(true);
1327                    mHandler.sendMessageDelayed(msg,
1328                            ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1329                }
1330            } else {
1331                wakeUpFromPowerKey(event.getDownTime());
1332
1333                if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
1334                    Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
1335                    msg.setAsynchronous(true);
1336                    mHandler.sendMessageDelayed(msg,
1337                            ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1338                    mBeganFromNonInteractive = true;
1339                } else {
1340                    final int maxCount = getMaxMultiPressPowerCount();
1341
1342                    if (maxCount <= 1) {
1343                        mPowerKeyHandled = true;
1344                    } else {
1345                        mBeganFromNonInteractive = true;
1346                    }
1347                }
1348            }
1349        }
1350    }
1351
1352    private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
1353        final boolean handled = canceled || mPowerKeyHandled;
1354        mScreenshotChordPowerKeyTriggered = false;
1355        cancelPendingScreenshotChordAction();
1356        cancelPendingPowerKeyAction();
1357
1358        if (!handled) {
1359            // Figure out how to handle the key now that it has been released.
1360            mPowerKeyPressCounter += 1;
1361
1362            final int maxCount = getMaxMultiPressPowerCount();
1363            final long eventTime = event.getDownTime();
1364            if (mPowerKeyPressCounter < maxCount) {
1365                // This could be a multi-press.  Wait a little bit longer to confirm.
1366                // Continue holding the wake lock.
1367                Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
1368                        interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
1369                msg.setAsynchronous(true);
1370                mHandler.sendMessageDelayed(msg, ViewConfiguration.getMultiPressTimeout());
1371                return;
1372            }
1373
1374            // No other actions.  Handle it immediately.
1375            powerPress(eventTime, interactive, mPowerKeyPressCounter);
1376        }
1377
1378        // Done.  Reset our state.
1379        finishPowerKeyPress();
1380    }
1381
1382    private void finishPowerKeyPress() {
1383        mBeganFromNonInteractive = false;
1384        mPowerKeyPressCounter = 0;
1385        if (mPowerKeyWakeLock.isHeld()) {
1386            mPowerKeyWakeLock.release();
1387        }
1388    }
1389
1390    private void finishBackKeyPress() {
1391        mBackKeyPressCounter = 0;
1392    }
1393
1394    private void cancelPendingPowerKeyAction() {
1395        if (!mPowerKeyHandled) {
1396            mPowerKeyHandled = true;
1397            mHandler.removeMessages(MSG_POWER_LONG_PRESS);
1398        }
1399    }
1400
1401    private void cancelPendingBackKeyAction() {
1402        if (!mBackKeyHandled) {
1403            mBackKeyHandled = true;
1404            mHandler.removeMessages(MSG_BACK_LONG_PRESS);
1405        }
1406    }
1407
1408    private void backMultiPressAction(long eventTime, int count) {
1409        if (count >= PANIC_PRESS_BACK_COUNT) {
1410            switch (mPanicPressOnBackBehavior) {
1411                case PANIC_PRESS_BACK_NOTHING:
1412                    break;
1413                case PANIC_PRESS_BACK_HOME:
1414                    launchHomeFromHotKey();
1415                    break;
1416            }
1417        }
1418    }
1419
1420    private void powerPress(long eventTime, boolean interactive, int count) {
1421        if (mScreenOnEarly && !mScreenOnFully) {
1422            Slog.i(TAG, "Suppressed redundant power key press while "
1423                    + "already in the process of turning the screen on.");
1424            return;
1425        }
1426
1427        if (count == 2) {
1428            powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
1429        } else if (count == 3) {
1430            powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
1431        } else if (interactive && !mBeganFromNonInteractive) {
1432            switch (mShortPressOnPowerBehavior) {
1433                case SHORT_PRESS_POWER_NOTHING:
1434                    break;
1435                case SHORT_PRESS_POWER_GO_TO_SLEEP:
1436                    goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
1437                    break;
1438                case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
1439                    goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
1440                            PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
1441                    break;
1442                case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
1443                    goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
1444                            PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
1445                    launchHomeFromHotKey();
1446                    break;
1447                case SHORT_PRESS_POWER_GO_HOME:
1448                    shortPressPowerGoHome();
1449                    break;
1450                case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME: {
1451                    if (mDismissImeOnBackKeyPressed) {
1452                        if (mInputMethodManagerInternal == null) {
1453                            mInputMethodManagerInternal =
1454                                    LocalServices.getService(InputMethodManagerInternal.class);
1455                        }
1456                        if (mInputMethodManagerInternal != null) {
1457                            mInputMethodManagerInternal.hideCurrentInputMethod();
1458                        }
1459                    } else {
1460                        shortPressPowerGoHome();
1461                    }
1462                    break;
1463                }
1464            }
1465        }
1466    }
1467
1468    private void goToSleep(long eventTime, int reason, int flags) {
1469        mRequestedOrGoingToSleep = true;
1470        mPowerManager.goToSleep(eventTime, reason, flags);
1471    }
1472
1473    private void shortPressPowerGoHome() {
1474        launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
1475        if (isKeyguardShowingAndNotOccluded()) {
1476            // Notify keyguard so it can do any special handling for the power button since the
1477            // device will not power off and only launch home.
1478            mKeyguardDelegate.onShortPowerPressedGoHome();
1479        }
1480    }
1481
1482    private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) {
1483        switch (behavior) {
1484            case MULTI_PRESS_POWER_NOTHING:
1485                break;
1486            case MULTI_PRESS_POWER_THEATER_MODE:
1487                if (!isUserSetupComplete()) {
1488                    Slog.i(TAG, "Ignoring toggling theater mode - device not setup.");
1489                    break;
1490                }
1491
1492                if (isTheaterModeEnabled()) {
1493                    Slog.i(TAG, "Toggling theater mode off.");
1494                    Settings.Global.putInt(mContext.getContentResolver(),
1495                            Settings.Global.THEATER_MODE_ON, 0);
1496                    if (!interactive) {
1497                        wakeUpFromPowerKey(eventTime);
1498                    }
1499                } else {
1500                    Slog.i(TAG, "Toggling theater mode on.");
1501                    Settings.Global.putInt(mContext.getContentResolver(),
1502                            Settings.Global.THEATER_MODE_ON, 1);
1503
1504                    if (mGoToSleepOnButtonPressTheaterMode && interactive) {
1505                        goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
1506                    }
1507                }
1508                break;
1509            case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
1510                Slog.i(TAG, "Starting brightness boost.");
1511                if (!interactive) {
1512                    wakeUpFromPowerKey(eventTime);
1513                }
1514                mPowerManager.boostScreenBrightness(eventTime);
1515                break;
1516        }
1517    }
1518
1519    private int getMaxMultiPressPowerCount() {
1520        if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
1521            return 3;
1522        }
1523        if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
1524            return 2;
1525        }
1526        return 1;
1527    }
1528
1529    private void powerLongPress() {
1530        final int behavior = getResolvedLongPressOnPowerBehavior();
1531        switch (behavior) {
1532        case LONG_PRESS_POWER_NOTHING:
1533            break;
1534        case LONG_PRESS_POWER_GLOBAL_ACTIONS:
1535            mPowerKeyHandled = true;
1536            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1537            showGlobalActionsInternal();
1538            break;
1539        case LONG_PRESS_POWER_SHUT_OFF:
1540        case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
1541            mPowerKeyHandled = true;
1542            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1543            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
1544            mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
1545            break;
1546        }
1547    }
1548
1549    private void backLongPress() {
1550        mBackKeyHandled = true;
1551
1552        switch (mLongPressOnBackBehavior) {
1553            case LONG_PRESS_BACK_NOTHING:
1554                break;
1555            case LONG_PRESS_BACK_GO_TO_VOICE_ASSIST:
1556                final boolean keyguardActive = mKeyguardDelegate == null
1557                        ? false
1558                        : mKeyguardDelegate.isShowing();
1559                if (!keyguardActive) {
1560                    Intent intent = new Intent(Intent.ACTION_VOICE_ASSIST);
1561                    startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
1562                }
1563                break;
1564        }
1565    }
1566
1567    private void accessibilityShortcutActivated() {
1568        mAccessibilityShortcutController.performAccessibilityShortcut();
1569    }
1570
1571    private void disposeInputConsumer(InputConsumer inputConsumer) {
1572        if (inputConsumer != null) {
1573            inputConsumer.dismiss();
1574        }
1575    }
1576
1577    private void sleepPress(long eventTime) {
1578        if (mShortPressOnSleepBehavior == SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME) {
1579            launchHomeFromHotKey(false /* awakenDreams */, true /*respectKeyguard*/);
1580        }
1581    }
1582
1583    private void sleepRelease(long eventTime) {
1584        switch (mShortPressOnSleepBehavior) {
1585            case SHORT_PRESS_SLEEP_GO_TO_SLEEP:
1586            case SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME:
1587                Slog.i(TAG, "sleepRelease() calling goToSleep(GO_TO_SLEEP_REASON_SLEEP_BUTTON)");
1588                goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON, 0);
1589                break;
1590        }
1591    }
1592
1593    private int getResolvedLongPressOnPowerBehavior() {
1594        if (FactoryTest.isLongPressOnPowerOffEnabled()) {
1595            return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
1596        }
1597        return mLongPressOnPowerBehavior;
1598    }
1599
1600    private boolean hasLongPressOnPowerBehavior() {
1601        return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;
1602    }
1603
1604    private boolean hasLongPressOnBackBehavior() {
1605        return mLongPressOnBackBehavior != LONG_PRESS_BACK_NOTHING;
1606    }
1607
1608    private boolean hasPanicPressOnBackBehavior() {
1609        return mPanicPressOnBackBehavior != PANIC_PRESS_BACK_NOTHING;
1610    }
1611
1612    private void interceptScreenshotChord() {
1613        if (mScreenshotChordEnabled
1614                && mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered
1615                && !mA11yShortcutChordVolumeUpKeyTriggered) {
1616            final long now = SystemClock.uptimeMillis();
1617            if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
1618                    && now <= mScreenshotChordPowerKeyTime
1619                            + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
1620                mScreenshotChordVolumeDownKeyConsumed = true;
1621                cancelPendingPowerKeyAction();
1622                mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
1623                mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
1624            }
1625        }
1626    }
1627
1628    private void interceptAccessibilityShortcutChord() {
1629        if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(isKeyguardLocked())
1630                && mScreenshotChordVolumeDownKeyTriggered && mA11yShortcutChordVolumeUpKeyTriggered
1631                && !mScreenshotChordPowerKeyTriggered) {
1632            final long now = SystemClock.uptimeMillis();
1633            if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
1634                    && now <= mA11yShortcutChordVolumeUpKeyTime
1635                    + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
1636                mScreenshotChordVolumeDownKeyConsumed = true;
1637                mA11yShortcutChordVolumeUpKeyConsumed = true;
1638                mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_ACCESSIBILITY_SHORTCUT),
1639                        ViewConfiguration.get(mContext).getAccessibilityShortcutKeyTimeout());
1640            }
1641        }
1642    }
1643
1644    private long getScreenshotChordLongPressDelay() {
1645        if (mKeyguardDelegate.isShowing()) {
1646            // Double the time it takes to take a screenshot from the keyguard
1647            return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER *
1648                    ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1649        }
1650        return ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout();
1651    }
1652
1653    private void cancelPendingScreenshotChordAction() {
1654        mHandler.removeCallbacks(mScreenshotRunnable);
1655    }
1656
1657    private void cancelPendingAccessibilityShortcutAction() {
1658        mHandler.removeMessages(MSG_ACCESSIBILITY_SHORTCUT);
1659    }
1660
1661    private final Runnable mEndCallLongPress = new Runnable() {
1662        @Override
1663        public void run() {
1664            mEndCallKeyHandled = true;
1665            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1666            showGlobalActionsInternal();
1667        }
1668    };
1669
1670    private class ScreenshotRunnable implements Runnable {
1671        private int mScreenshotType = TAKE_SCREENSHOT_FULLSCREEN;
1672
1673        public void setScreenshotType(int screenshotType) {
1674            mScreenshotType = screenshotType;
1675        }
1676
1677        @Override
1678        public void run() {
1679            takeScreenshot(mScreenshotType);
1680        }
1681    }
1682
1683    private final ScreenshotRunnable mScreenshotRunnable = new ScreenshotRunnable();
1684
1685    @Override
1686    public void showGlobalActions() {
1687        mHandler.removeMessages(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
1688        mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
1689    }
1690
1691    void showGlobalActionsInternal() {
1692        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
1693        if (mGlobalActions == null) {
1694            mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
1695        }
1696        final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();
1697        mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
1698        if (keyguardShowing) {
1699            // since it took two seconds of long press to bring this up,
1700            // poke the wake lock so they have some time to see the dialog.
1701            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
1702        }
1703    }
1704
1705    boolean isDeviceProvisioned() {
1706        return Settings.Global.getInt(
1707                mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
1708    }
1709
1710    boolean isUserSetupComplete() {
1711        boolean isSetupComplete = Settings.Secure.getIntForUser(mContext.getContentResolver(),
1712                Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
1713        if (mHasFeatureLeanback) {
1714            isSetupComplete &= isTvUserSetupComplete();
1715        }
1716        return isSetupComplete;
1717    }
1718
1719    private boolean isTvUserSetupComplete() {
1720        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
1721                Settings.Secure.TV_USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
1722    }
1723
1724    private void handleShortPressOnHome() {
1725        // Turn on the connected TV and switch HDMI input if we're a HDMI playback device.
1726        final HdmiControl hdmiControl = getHdmiControl();
1727        if (hdmiControl != null) {
1728            hdmiControl.turnOnTv();
1729        }
1730
1731        // If there's a dream running then use home to escape the dream
1732        // but don't actually go home.
1733        if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) {
1734            mDreamManagerInternal.stopDream(false /*immediate*/);
1735            return;
1736        }
1737
1738        // Go home!
1739        launchHomeFromHotKey();
1740    }
1741
1742    /**
1743     * Creates an accessor to HDMI control service that performs the operation of
1744     * turning on TV (optional) and switching input to us. If HDMI control service
1745     * is not available or we're not a HDMI playback device, the operation is no-op.
1746     * @return {@link HdmiControl} instance if available, null otherwise.
1747     */
1748    private HdmiControl getHdmiControl() {
1749        if (null == mHdmiControl) {
1750            if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
1751                return null;
1752            }
1753            HdmiControlManager manager = (HdmiControlManager) mContext.getSystemService(
1754                        Context.HDMI_CONTROL_SERVICE);
1755            HdmiPlaybackClient client = null;
1756            if (manager != null) {
1757                client = manager.getPlaybackClient();
1758            }
1759            mHdmiControl = new HdmiControl(client);
1760        }
1761        return mHdmiControl;
1762    }
1763
1764    private static class HdmiControl {
1765        private final HdmiPlaybackClient mClient;
1766
1767        private HdmiControl(HdmiPlaybackClient client) {
1768            mClient = client;
1769        }
1770
1771        public void turnOnTv() {
1772            if (mClient == null) {
1773                return;
1774            }
1775            mClient.oneTouchPlay(new OneTouchPlayCallback() {
1776                @Override
1777                public void onComplete(int result) {
1778                    if (result != HdmiControlManager.RESULT_SUCCESS) {
1779                        Log.w(TAG, "One touch play failed: " + result);
1780                    }
1781                }
1782            });
1783        }
1784    }
1785
1786    private void handleLongPressOnHome(int deviceId) {
1787        if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_NOTHING) {
1788            return;
1789        }
1790        mHomeConsumed = true;
1791        performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1792        switch (mLongPressOnHomeBehavior) {
1793            case LONG_PRESS_HOME_ALL_APPS:
1794                launchAllAppsAction();
1795                break;
1796            case LONG_PRESS_HOME_ASSIST:
1797                launchAssistAction(null, deviceId);
1798                break;
1799            default:
1800                Log.w(TAG, "Undefined home long press behavior: " + mLongPressOnHomeBehavior);
1801                break;
1802        }
1803    }
1804
1805    private void launchAllAppsAction() {
1806        Intent intent = new Intent(Intent.ACTION_ALL_APPS);
1807        if (mHasFeatureLeanback) {
1808            final PackageManager pm = mContext.getPackageManager();
1809            Intent intentLauncher = new Intent(Intent.ACTION_MAIN);
1810            intentLauncher.addCategory(Intent.CATEGORY_HOME);
1811            ResolveInfo resolveInfo = pm.resolveActivityAsUser(intentLauncher,
1812                    PackageManager.MATCH_SYSTEM_ONLY,
1813                    mCurrentUserId);
1814            if (resolveInfo != null) {
1815                intent.setPackage(resolveInfo.activityInfo.packageName);
1816            }
1817        }
1818        startActivityAsUser(intent, UserHandle.CURRENT);
1819    }
1820
1821    private void handleDoubleTapOnHome() {
1822        if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
1823            mHomeConsumed = true;
1824            toggleRecentApps();
1825        }
1826    }
1827
1828    private void showPictureInPictureMenu(KeyEvent event) {
1829        if (DEBUG_INPUT) Log.d(TAG, "showPictureInPictureMenu event=" + event);
1830        mHandler.removeMessages(MSG_SHOW_PICTURE_IN_PICTURE_MENU);
1831        Message msg = mHandler.obtainMessage(MSG_SHOW_PICTURE_IN_PICTURE_MENU);
1832        msg.setAsynchronous(true);
1833        msg.sendToTarget();
1834    }
1835
1836    private void showPictureInPictureMenuInternal() {
1837        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
1838        if (statusbar != null) {
1839            statusbar.showPictureInPictureMenu();
1840        }
1841    }
1842
1843    private final Runnable mHomeDoubleTapTimeoutRunnable = new Runnable() {
1844        @Override
1845        public void run() {
1846            if (mHomeDoubleTapPending) {
1847                mHomeDoubleTapPending = false;
1848                handleShortPressOnHome();
1849            }
1850        }
1851    };
1852
1853    private boolean isRoundWindow() {
1854        return mContext.getResources().getConfiguration().isScreenRound();
1855    }
1856
1857    /** {@inheritDoc} */
1858    @Override
1859    public void init(Context context, IWindowManager windowManager,
1860            WindowManagerFuncs windowManagerFuncs) {
1861        mContext = context;
1862        mWindowManager = windowManager;
1863        mWindowManagerFuncs = windowManagerFuncs;
1864        mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
1865        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
1866        mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
1867        mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
1868        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
1869        mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
1870        mHasFeatureWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH);
1871        mHasFeatureLeanback = mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK);
1872        mAccessibilityShortcutController =
1873                new AccessibilityShortcutController(mContext, new Handler(), mCurrentUserId);
1874        // Init display burn-in protection
1875        boolean burnInProtectionEnabled = context.getResources().getBoolean(
1876                com.android.internal.R.bool.config_enableBurnInProtection);
1877        // Allow a system property to override this. Used by developer settings.
1878        boolean burnInProtectionDevMode =
1879                SystemProperties.getBoolean("persist.debug.force_burn_in", false);
1880        if (burnInProtectionEnabled || burnInProtectionDevMode) {
1881            final int minHorizontal;
1882            final int maxHorizontal;
1883            final int minVertical;
1884            final int maxVertical;
1885            final int maxRadius;
1886            if (burnInProtectionDevMode) {
1887                minHorizontal = -8;
1888                maxHorizontal = 8;
1889                minVertical = -8;
1890                maxVertical = -4;
1891                maxRadius = (isRoundWindow()) ? 6 : -1;
1892            } else {
1893                Resources resources = context.getResources();
1894                minHorizontal = resources.getInteger(
1895                        com.android.internal.R.integer.config_burnInProtectionMinHorizontalOffset);
1896                maxHorizontal = resources.getInteger(
1897                        com.android.internal.R.integer.config_burnInProtectionMaxHorizontalOffset);
1898                minVertical = resources.getInteger(
1899                        com.android.internal.R.integer.config_burnInProtectionMinVerticalOffset);
1900                maxVertical = resources.getInteger(
1901                        com.android.internal.R.integer.config_burnInProtectionMaxVerticalOffset);
1902                maxRadius = resources.getInteger(
1903                        com.android.internal.R.integer.config_burnInProtectionMaxRadius);
1904            }
1905            mBurnInProtectionHelper = new BurnInProtectionHelper(
1906                    context, minHorizontal, maxHorizontal, minVertical, maxVertical, maxRadius);
1907        }
1908
1909        mHandler = new PolicyHandler();
1910        mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
1911        mOrientationListener = new MyOrientationListener(mContext, mHandler);
1912        try {
1913            mOrientationListener.setCurrentRotation(windowManager.getDefaultDisplayRotation());
1914        } catch (RemoteException ex) { }
1915        mSettingsObserver = new SettingsObserver(mHandler);
1916        mSettingsObserver.observe();
1917        mShortcutManager = new ShortcutManager(context);
1918        mUiMode = context.getResources().getInteger(
1919                com.android.internal.R.integer.config_defaultUiModeType);
1920        mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
1921        mHomeIntent.addCategory(Intent.CATEGORY_HOME);
1922        mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1923                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1924        mEnableCarDockHomeCapture = context.getResources().getBoolean(
1925                com.android.internal.R.bool.config_enableCarDockHomeLaunch);
1926        mCarDockIntent =  new Intent(Intent.ACTION_MAIN, null);
1927        mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
1928        mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1929                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1930        mDeskDockIntent =  new Intent(Intent.ACTION_MAIN, null);
1931        mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
1932        mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1933                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1934        mVrHeadsetHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
1935        mVrHeadsetHomeIntent.addCategory(Intent.CATEGORY_VR_HOME);
1936        mVrHeadsetHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1937                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1938
1939        mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1940        mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1941                "PhoneWindowManager.mBroadcastWakeLock");
1942        mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1943                "PhoneWindowManager.mPowerKeyWakeLock");
1944        mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
1945        mSupportAutoRotation = mContext.getResources().getBoolean(
1946                com.android.internal.R.bool.config_supportAutoRotation);
1947        mLidOpenRotation = readRotation(
1948                com.android.internal.R.integer.config_lidOpenRotation);
1949        mCarDockRotation = readRotation(
1950                com.android.internal.R.integer.config_carDockRotation);
1951        mDeskDockRotation = readRotation(
1952                com.android.internal.R.integer.config_deskDockRotation);
1953        mUndockedHdmiRotation = readRotation(
1954                com.android.internal.R.integer.config_undockedHdmiRotation);
1955        mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
1956                com.android.internal.R.bool.config_carDockEnablesAccelerometer);
1957        mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
1958                com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
1959        mLidKeyboardAccessibility = mContext.getResources().getInteger(
1960                com.android.internal.R.integer.config_lidKeyboardAccessibility);
1961        mLidNavigationAccessibility = mContext.getResources().getInteger(
1962                com.android.internal.R.integer.config_lidNavigationAccessibility);
1963        mLidControlsScreenLock = mContext.getResources().getBoolean(
1964                com.android.internal.R.bool.config_lidControlsScreenLock);
1965        mLidControlsSleep = mContext.getResources().getBoolean(
1966                com.android.internal.R.bool.config_lidControlsSleep);
1967        mTranslucentDecorEnabled = mContext.getResources().getBoolean(
1968                com.android.internal.R.bool.config_enableTranslucentDecor);
1969
1970        mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
1971                com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
1972        mAllowTheaterModeWakeFromPowerKey = mAllowTheaterModeWakeFromKey
1973                || mContext.getResources().getBoolean(
1974                    com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey);
1975        mAllowTheaterModeWakeFromMotion = mContext.getResources().getBoolean(
1976                com.android.internal.R.bool.config_allowTheaterModeWakeFromMotion);
1977        mAllowTheaterModeWakeFromMotionWhenNotDreaming = mContext.getResources().getBoolean(
1978                com.android.internal.R.bool.config_allowTheaterModeWakeFromMotionWhenNotDreaming);
1979        mAllowTheaterModeWakeFromCameraLens = mContext.getResources().getBoolean(
1980                com.android.internal.R.bool.config_allowTheaterModeWakeFromCameraLens);
1981        mAllowTheaterModeWakeFromLidSwitch = mContext.getResources().getBoolean(
1982                com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch);
1983        mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean(
1984                com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture);
1985
1986        mGoToSleepOnButtonPressTheaterMode = mContext.getResources().getBoolean(
1987                com.android.internal.R.bool.config_goToSleepOnButtonPressTheaterMode);
1988
1989        mSupportLongPressPowerWhenNonInteractive = mContext.getResources().getBoolean(
1990                com.android.internal.R.bool.config_supportLongPressPowerWhenNonInteractive);
1991
1992        mLongPressOnBackBehavior = mContext.getResources().getInteger(
1993                com.android.internal.R.integer.config_longPressOnBackBehavior);
1994        mPanicPressOnBackBehavior = mContext.getResources().getInteger(
1995                com.android.internal.R.integer.config_backPanicBehavior);
1996
1997        mShortPressOnPowerBehavior = mContext.getResources().getInteger(
1998                com.android.internal.R.integer.config_shortPressOnPowerBehavior);
1999        mLongPressOnPowerBehavior = mContext.getResources().getInteger(
2000                com.android.internal.R.integer.config_longPressOnPowerBehavior);
2001        mDoublePressOnPowerBehavior = mContext.getResources().getInteger(
2002                com.android.internal.R.integer.config_doublePressOnPowerBehavior);
2003        mTriplePressOnPowerBehavior = mContext.getResources().getInteger(
2004                com.android.internal.R.integer.config_triplePressOnPowerBehavior);
2005        mShortPressOnSleepBehavior = mContext.getResources().getInteger(
2006                com.android.internal.R.integer.config_shortPressOnSleepBehavior);
2007
2008        mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION;
2009
2010        mHandleVolumeKeysInWM = mContext.getResources().getBoolean(
2011                com.android.internal.R.bool.config_handleVolumeKeysInWindowManager);
2012
2013        readConfigurationDependentBehaviors();
2014
2015        mAccessibilityManager = (AccessibilityManager) context.getSystemService(
2016                Context.ACCESSIBILITY_SERVICE);
2017
2018        // register for dock events
2019        IntentFilter filter = new IntentFilter();
2020        filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
2021        filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
2022        filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
2023        filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
2024        filter.addAction(Intent.ACTION_DOCK_EVENT);
2025        Intent intent = context.registerReceiver(mDockReceiver, filter);
2026        if (intent != null) {
2027            // Retrieve current sticky dock event broadcast.
2028            mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
2029                    Intent.EXTRA_DOCK_STATE_UNDOCKED);
2030        }
2031
2032        // register for dream-related broadcasts
2033        filter = new IntentFilter();
2034        filter.addAction(Intent.ACTION_DREAMING_STARTED);
2035        filter.addAction(Intent.ACTION_DREAMING_STOPPED);
2036        context.registerReceiver(mDreamReceiver, filter);
2037
2038        // register for multiuser-relevant broadcasts
2039        filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
2040        context.registerReceiver(mMultiuserReceiver, filter);
2041
2042        // monitor for system gestures
2043        mSystemGestures = new SystemGesturesPointerEventListener(context,
2044                new SystemGesturesPointerEventListener.Callbacks() {
2045                    @Override
2046                    public void onSwipeFromTop() {
2047                        if (mStatusBar != null) {
2048                            requestTransientBars(mStatusBar);
2049                        }
2050                    }
2051                    @Override
2052                    public void onSwipeFromBottom() {
2053                        if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_BOTTOM) {
2054                            requestTransientBars(mNavigationBar);
2055                        }
2056                    }
2057                    @Override
2058                    public void onSwipeFromRight() {
2059                        if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_RIGHT) {
2060                            requestTransientBars(mNavigationBar);
2061                        }
2062                    }
2063                    @Override
2064                    public void onSwipeFromLeft() {
2065                        if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_LEFT) {
2066                            requestTransientBars(mNavigationBar);
2067                        }
2068                    }
2069                    @Override
2070                    public void onFling(int duration) {
2071                        if (mPowerManagerInternal != null) {
2072                            mPowerManagerInternal.powerHint(
2073                                    PowerHint.INTERACTION, duration);
2074                        }
2075                    }
2076                    @Override
2077                    public void onDebug() {
2078                        // no-op
2079                    }
2080                    @Override
2081                    public void onDown() {
2082                        mOrientationListener.onTouchStart();
2083                    }
2084                    @Override
2085                    public void onUpOrCancel() {
2086                        mOrientationListener.onTouchEnd();
2087                    }
2088                    @Override
2089                    public void onMouseHoverAtTop() {
2090                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
2091                        Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
2092                        msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
2093                        mHandler.sendMessageDelayed(msg, 500);
2094                    }
2095                    @Override
2096                    public void onMouseHoverAtBottom() {
2097                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
2098                        Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
2099                        msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
2100                        mHandler.sendMessageDelayed(msg, 500);
2101                    }
2102                    @Override
2103                    public void onMouseLeaveFromEdge() {
2104                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
2105                    }
2106                });
2107        mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext);
2108        mWindowManagerFuncs.registerPointerEventListener(mSystemGestures);
2109
2110        mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
2111        mLongPressVibePattern = getLongIntArray(mContext.getResources(),
2112                com.android.internal.R.array.config_longPressVibePattern);
2113        mCalendarDateVibePattern = getLongIntArray(mContext.getResources(),
2114                com.android.internal.R.array.config_calendarDateVibePattern);
2115        mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
2116                com.android.internal.R.array.config_safeModeEnabledVibePattern);
2117
2118        mScreenshotChordEnabled = mContext.getResources().getBoolean(
2119                com.android.internal.R.bool.config_enableScreenshotChord);
2120
2121        mGlobalKeyManager = new GlobalKeyManager(mContext);
2122
2123        // Controls rotation and the like.
2124        initializeHdmiState();
2125
2126        // Match current screen state.
2127        if (!mPowerManager.isInteractive()) {
2128            startedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
2129            finishedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
2130        }
2131
2132        mWindowManagerInternal.registerAppTransitionListener(
2133                mStatusBarController.getAppTransitionListener());
2134        mWindowManagerInternal.registerAppTransitionListener(new AppTransitionListener() {
2135            @Override
2136            public int onAppTransitionStartingLocked(int transit, IBinder openToken,
2137                    IBinder closeToken,
2138                    Animation openAnimation, Animation closeAnimation) {
2139                return handleStartTransitionForKeyguardLw(transit, openAnimation);
2140            }
2141
2142            @Override
2143            public void onAppTransitionCancelledLocked(int transit) {
2144                handleStartTransitionForKeyguardLw(transit, null /* transit */);
2145            }
2146        });
2147        mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
2148                new StateCallback() {
2149                    @Override
2150                    public void onTrustedChanged() {
2151                        mWindowManagerFuncs.notifyKeyguardTrustedChanged();
2152                    }
2153                });
2154    }
2155
2156    /**
2157     * Read values from config.xml that may be overridden depending on
2158     * the configuration of the device.
2159     * eg. Disable long press on home goes to recents on sw600dp.
2160     */
2161    private void readConfigurationDependentBehaviors() {
2162        final Resources res = mContext.getResources();
2163
2164        mLongPressOnHomeBehavior = res.getInteger(
2165                com.android.internal.R.integer.config_longPressOnHomeBehavior);
2166        if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||
2167                mLongPressOnHomeBehavior > LAST_LONG_PRESS_HOME_BEHAVIOR) {
2168            mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
2169        }
2170
2171        mDoubleTapOnHomeBehavior = res.getInteger(
2172                com.android.internal.R.integer.config_doubleTapOnHomeBehavior);
2173        if (mDoubleTapOnHomeBehavior < DOUBLE_TAP_HOME_NOTHING ||
2174                mDoubleTapOnHomeBehavior > DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
2175            mDoubleTapOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
2176        }
2177
2178        mShortPressWindowBehavior = SHORT_PRESS_WINDOW_NOTHING;
2179        if (mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
2180            mShortPressWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE;
2181        }
2182
2183        mNavBarOpacityMode = res.getInteger(
2184                com.android.internal.R.integer.config_navBarOpacityMode);
2185    }
2186
2187    @Override
2188    public void setInitialDisplaySize(Display display, int width, int height, int density) {
2189        // This method might be called before the policy has been fully initialized
2190        // or for other displays we don't care about.
2191        // TODO(multi-display): Define policy for secondary displays.
2192        if (mContext == null || display.getDisplayId() != DEFAULT_DISPLAY) {
2193            return;
2194        }
2195        mDisplay = display;
2196
2197        final Resources res = mContext.getResources();
2198        int shortSize, longSize;
2199        if (width > height) {
2200            shortSize = height;
2201            longSize = width;
2202            mLandscapeRotation = Surface.ROTATION_0;
2203            mSeascapeRotation = Surface.ROTATION_180;
2204            if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
2205                mPortraitRotation = Surface.ROTATION_90;
2206                mUpsideDownRotation = Surface.ROTATION_270;
2207            } else {
2208                mPortraitRotation = Surface.ROTATION_270;
2209                mUpsideDownRotation = Surface.ROTATION_90;
2210            }
2211        } else {
2212            shortSize = width;
2213            longSize = height;
2214            mPortraitRotation = Surface.ROTATION_0;
2215            mUpsideDownRotation = Surface.ROTATION_180;
2216            if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
2217                mLandscapeRotation = Surface.ROTATION_270;
2218                mSeascapeRotation = Surface.ROTATION_90;
2219            } else {
2220                mLandscapeRotation = Surface.ROTATION_90;
2221                mSeascapeRotation = Surface.ROTATION_270;
2222            }
2223        }
2224
2225        // SystemUI (status bar) layout policy
2226        int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
2227        int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
2228
2229        // Allow the navigation bar to move on non-square small devices (phones).
2230        mNavigationBarCanMove = width != height && shortSizeDp < 600;
2231
2232        mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
2233
2234        // Allow a system property to override this. Used by the emulator.
2235        // See also hasNavigationBar().
2236        String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
2237        if ("1".equals(navBarOverride)) {
2238            mHasNavigationBar = false;
2239        } else if ("0".equals(navBarOverride)) {
2240            mHasNavigationBar = true;
2241        }
2242
2243        // For demo purposes, allow the rotation of the HDMI display to be controlled.
2244        // By default, HDMI locks rotation to landscape.
2245        if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
2246            mDemoHdmiRotation = mPortraitRotation;
2247        } else {
2248            mDemoHdmiRotation = mLandscapeRotation;
2249        }
2250        mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
2251
2252        // For demo purposes, allow the rotation of the remote display to be controlled.
2253        // By default, remote display locks rotation to landscape.
2254        if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
2255            mDemoRotation = mPortraitRotation;
2256        } else {
2257            mDemoRotation = mLandscapeRotation;
2258        }
2259        mDemoRotationLock = SystemProperties.getBoolean(
2260                "persist.demo.rotationlock", false);
2261
2262        // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
2263        // http://developer.android.com/guide/practices/screens_support.html#range
2264        mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 &&
2265                res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
2266                // For debug purposes the next line turns this feature off with:
2267                // $ adb shell setprop config.override_forced_orient true
2268                // $ adb shell wm size reset
2269                !"true".equals(SystemProperties.get("config.override_forced_orient"));
2270    }
2271
2272    /**
2273     * @return whether the navigation bar can be hidden, e.g. the device has a
2274     *         navigation bar and touch exploration is not enabled
2275     */
2276    private boolean canHideNavigationBar() {
2277        return mHasNavigationBar;
2278    }
2279
2280    @Override
2281    public boolean isDefaultOrientationForced() {
2282        return mForceDefaultOrientation;
2283    }
2284
2285    @Override
2286    public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) {
2287        // TODO(multi-display): Define policy for secondary displays.
2288        if (display.getDisplayId() == DEFAULT_DISPLAY) {
2289            mOverscanLeft = left;
2290            mOverscanTop = top;
2291            mOverscanRight = right;
2292            mOverscanBottom = bottom;
2293        }
2294    }
2295
2296    public void updateSettings() {
2297        ContentResolver resolver = mContext.getContentResolver();
2298        boolean updateRotation = false;
2299        synchronized (mLock) {
2300            mEndcallBehavior = Settings.System.getIntForUser(resolver,
2301                    Settings.System.END_BUTTON_BEHAVIOR,
2302                    Settings.System.END_BUTTON_BEHAVIOR_DEFAULT,
2303                    UserHandle.USER_CURRENT);
2304            mIncallPowerBehavior = Settings.Secure.getIntForUser(resolver,
2305                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
2306                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT,
2307                    UserHandle.USER_CURRENT);
2308            mIncallBackBehavior = Settings.Secure.getIntForUser(resolver,
2309                    Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR,
2310                    Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_DEFAULT,
2311                    UserHandle.USER_CURRENT);
2312
2313            // Configure wake gesture.
2314            boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver,
2315                    Settings.Secure.WAKE_GESTURE_ENABLED, 0,
2316                    UserHandle.USER_CURRENT) != 0;
2317            if (mWakeGestureEnabledSetting != wakeGestureEnabledSetting) {
2318                mWakeGestureEnabledSetting = wakeGestureEnabledSetting;
2319                updateWakeGestureListenerLp();
2320            }
2321
2322            // Configure rotation lock.
2323            int userRotation = Settings.System.getIntForUser(resolver,
2324                    Settings.System.USER_ROTATION, Surface.ROTATION_0,
2325                    UserHandle.USER_CURRENT);
2326            if (mUserRotation != userRotation) {
2327                mUserRotation = userRotation;
2328                updateRotation = true;
2329            }
2330            int userRotationMode = Settings.System.getIntForUser(resolver,
2331                    Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
2332                            WindowManagerPolicy.USER_ROTATION_FREE :
2333                                    WindowManagerPolicy.USER_ROTATION_LOCKED;
2334            if (mUserRotationMode != userRotationMode) {
2335                mUserRotationMode = userRotationMode;
2336                updateRotation = true;
2337                updateOrientationListenerLp();
2338            }
2339
2340            if (mSystemReady) {
2341                int pointerLocation = Settings.System.getIntForUser(resolver,
2342                        Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT);
2343                if (mPointerLocationMode != pointerLocation) {
2344                    mPointerLocationMode = pointerLocation;
2345                    mHandler.sendEmptyMessage(pointerLocation != 0 ?
2346                            MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
2347                }
2348            }
2349            // use screen off timeout setting as the timeout for the lockscreen
2350            mLockScreenTimeout = Settings.System.getIntForUser(resolver,
2351                    Settings.System.SCREEN_OFF_TIMEOUT, 0, UserHandle.USER_CURRENT);
2352            String imId = Settings.Secure.getStringForUser(resolver,
2353                    Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.USER_CURRENT);
2354            boolean hasSoftInput = imId != null && imId.length() > 0;
2355            if (mHasSoftInput != hasSoftInput) {
2356                mHasSoftInput = hasSoftInput;
2357                updateRotation = true;
2358            }
2359            if (mImmersiveModeConfirmation != null) {
2360                mImmersiveModeConfirmation.loadSetting(mCurrentUserId);
2361            }
2362        }
2363        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
2364            PolicyControl.reloadFromSetting(mContext);
2365        }
2366        if (updateRotation) {
2367            updateRotation(true);
2368        }
2369    }
2370
2371    private void updateWakeGestureListenerLp() {
2372        if (shouldEnableWakeGestureLp()) {
2373            mWakeGestureListener.requestWakeUpTrigger();
2374        } else {
2375            mWakeGestureListener.cancelWakeUpTrigger();
2376        }
2377    }
2378
2379    private boolean shouldEnableWakeGestureLp() {
2380        return mWakeGestureEnabledSetting && !mAwake
2381                && (!mLidControlsSleep || mLidState != LID_CLOSED)
2382                && mWakeGestureListener.isSupported();
2383    }
2384
2385    private void enablePointerLocation() {
2386        if (mPointerLocationView == null) {
2387            mPointerLocationView = new PointerLocationView(mContext);
2388            mPointerLocationView.setPrintCoords(false);
2389            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
2390                    WindowManager.LayoutParams.MATCH_PARENT,
2391                    WindowManager.LayoutParams.MATCH_PARENT);
2392            lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
2393            lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
2394                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
2395                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2396                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
2397            if (ActivityManager.isHighEndGfx()) {
2398                lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
2399                lp.privateFlags |=
2400                        WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
2401            }
2402            lp.format = PixelFormat.TRANSLUCENT;
2403            lp.setTitle("PointerLocation");
2404            WindowManager wm = (WindowManager) mContext.getSystemService(WINDOW_SERVICE);
2405            lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
2406            wm.addView(mPointerLocationView, lp);
2407            mWindowManagerFuncs.registerPointerEventListener(mPointerLocationView);
2408        }
2409    }
2410
2411    private void disablePointerLocation() {
2412        if (mPointerLocationView != null) {
2413            mWindowManagerFuncs.unregisterPointerEventListener(mPointerLocationView);
2414            WindowManager wm = (WindowManager) mContext.getSystemService(WINDOW_SERVICE);
2415            wm.removeView(mPointerLocationView);
2416            mPointerLocationView = null;
2417        }
2418    }
2419
2420    private int readRotation(int resID) {
2421        try {
2422            int rotation = mContext.getResources().getInteger(resID);
2423            switch (rotation) {
2424                case 0:
2425                    return Surface.ROTATION_0;
2426                case 90:
2427                    return Surface.ROTATION_90;
2428                case 180:
2429                    return Surface.ROTATION_180;
2430                case 270:
2431                    return Surface.ROTATION_270;
2432            }
2433        } catch (Resources.NotFoundException e) {
2434            // fall through
2435        }
2436        return -1;
2437    }
2438
2439    /** {@inheritDoc} */
2440    @Override
2441    public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) {
2442        int type = attrs.type;
2443
2444        outAppOp[0] = AppOpsManager.OP_NONE;
2445
2446        if (!((type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW)
2447                || (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW)
2448                || (type >= FIRST_SYSTEM_WINDOW && type <= LAST_SYSTEM_WINDOW))) {
2449            return WindowManagerGlobal.ADD_INVALID_TYPE;
2450        }
2451
2452        if (type < FIRST_SYSTEM_WINDOW || type > LAST_SYSTEM_WINDOW) {
2453            // Window manager will make sure these are okay.
2454            return ADD_OKAY;
2455        }
2456
2457        if (!isSystemAlertWindowType(type)) {
2458            switch (type) {
2459                case TYPE_TOAST:
2460                    // Only apps that target older than O SDK can add window without a token, after
2461                    // that we require a token so apps cannot add toasts directly as the token is
2462                    // added by the notification system.
2463                    // Window manager does the checking for this.
2464                    outAppOp[0] = OP_TOAST_WINDOW;
2465                    return ADD_OKAY;
2466                case TYPE_DREAM:
2467                case TYPE_INPUT_METHOD:
2468                case TYPE_WALLPAPER:
2469                case TYPE_PRESENTATION:
2470                case TYPE_PRIVATE_PRESENTATION:
2471                case TYPE_VOICE_INTERACTION:
2472                case TYPE_ACCESSIBILITY_OVERLAY:
2473                case TYPE_QS_DIALOG:
2474                    // The window manager will check these.
2475                    return ADD_OKAY;
2476            }
2477            return mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
2478                    == PERMISSION_GRANTED ? ADD_OKAY : ADD_PERMISSION_DENIED;
2479        }
2480
2481        // Things get a little more interesting for alert windows...
2482        outAppOp[0] = OP_SYSTEM_ALERT_WINDOW;
2483
2484        final int callingUid = Binder.getCallingUid();
2485        // system processes will be automatically granted privilege to draw
2486        if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
2487            return ADD_OKAY;
2488        }
2489
2490        ApplicationInfo appInfo;
2491        try {
2492            appInfo = mContext.getPackageManager().getApplicationInfoAsUser(
2493                            attrs.packageName,
2494                            0 /* flags */,
2495                            UserHandle.getUserId(callingUid));
2496        } catch (PackageManager.NameNotFoundException e) {
2497            appInfo = null;
2498        }
2499
2500        if (appInfo == null || (type != TYPE_APPLICATION_OVERLAY && appInfo.targetSdkVersion >= O)) {
2501            /**
2502             * Apps targeting >= {@link Build.VERSION_CODES#O} are required to hold
2503             * {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW} (system signature apps)
2504             * permission to add alert windows that aren't
2505             * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY}.
2506             */
2507            return (mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
2508                    == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
2509        }
2510
2511        // check if user has enabled this operation. SecurityException will be thrown if this app
2512        // has not been allowed by the user
2513        final int mode = mAppOpsManager.checkOpNoThrow(outAppOp[0], callingUid, attrs.packageName);
2514        switch (mode) {
2515            case AppOpsManager.MODE_ALLOWED:
2516            case AppOpsManager.MODE_IGNORED:
2517                // although we return ADD_OKAY for MODE_IGNORED, the added window will
2518                // actually be hidden in WindowManagerService
2519                return ADD_OKAY;
2520            case AppOpsManager.MODE_ERRORED:
2521                // Don't crash legacy apps
2522                if (appInfo.targetSdkVersion < M) {
2523                    return ADD_OKAY;
2524                }
2525                return ADD_PERMISSION_DENIED;
2526            default:
2527                // in the default mode, we will make a decision here based on
2528                // checkCallingPermission()
2529                return (mContext.checkCallingOrSelfPermission(SYSTEM_ALERT_WINDOW)
2530                        == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
2531        }
2532    }
2533
2534    @Override
2535    public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) {
2536
2537        // If this switch statement is modified, modify the comment in the declarations of
2538        // the type in {@link WindowManager.LayoutParams} as well.
2539        switch (attrs.type) {
2540            default:
2541                // These are the windows that by default are shown only to the user that created
2542                // them. If this needs to be overridden, set
2543                // {@link WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS} in
2544                // {@link WindowManager.LayoutParams}. Note that permission
2545                // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well.
2546                if ((attrs.privateFlags & PRIVATE_FLAG_SHOW_FOR_ALL_USERS) == 0) {
2547                    return true;
2548                }
2549                break;
2550
2551            // These are the windows that by default are shown to all users. However, to
2552            // protect against spoofing, check permissions below.
2553            case TYPE_APPLICATION_STARTING:
2554            case TYPE_BOOT_PROGRESS:
2555            case TYPE_DISPLAY_OVERLAY:
2556            case TYPE_INPUT_CONSUMER:
2557            case TYPE_KEYGUARD_DIALOG:
2558            case TYPE_MAGNIFICATION_OVERLAY:
2559            case TYPE_NAVIGATION_BAR:
2560            case TYPE_NAVIGATION_BAR_PANEL:
2561            case TYPE_PHONE:
2562            case TYPE_POINTER:
2563            case TYPE_PRIORITY_PHONE:
2564            case TYPE_SEARCH_BAR:
2565            case TYPE_STATUS_BAR:
2566            case TYPE_STATUS_BAR_PANEL:
2567            case TYPE_STATUS_BAR_SUB_PANEL:
2568            case TYPE_SYSTEM_DIALOG:
2569            case TYPE_VOLUME_OVERLAY:
2570            case TYPE_PRESENTATION:
2571            case TYPE_PRIVATE_PRESENTATION:
2572            case TYPE_DOCK_DIVIDER:
2573                break;
2574        }
2575
2576        // Check if third party app has set window to system window type.
2577        return mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW) != PERMISSION_GRANTED;
2578    }
2579
2580    @Override
2581    public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
2582        switch (attrs.type) {
2583            case TYPE_SYSTEM_OVERLAY:
2584            case TYPE_SECURE_SYSTEM_OVERLAY:
2585                // These types of windows can't receive input events.
2586                attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2587                        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
2588                attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
2589                break;
2590            case TYPE_STATUS_BAR:
2591
2592                // If the Keyguard is in a hidden state (occluded by another window), we force to
2593                // remove the wallpaper and keyguard flag so that any change in-flight after setting
2594                // the keyguard as occluded wouldn't set these flags again.
2595                // See {@link #processKeyguardSetHiddenResultLw}.
2596                if (mKeyguardOccluded) {
2597                    attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
2598                    attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2599                }
2600                break;
2601
2602            case TYPE_SCREENSHOT:
2603                attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
2604                break;
2605
2606            case TYPE_TOAST:
2607                // While apps should use the dedicated toast APIs to add such windows
2608                // it possible legacy apps to add the window directly. Therefore, we
2609                // make windows added directly by the app behave as a toast as much
2610                // as possible in terms of timeout and animation.
2611                if (attrs.hideTimeoutMilliseconds < 0
2612                        || attrs.hideTimeoutMilliseconds > TOAST_WINDOW_TIMEOUT) {
2613                    attrs.hideTimeoutMilliseconds = TOAST_WINDOW_TIMEOUT;
2614                }
2615                attrs.windowAnimations = com.android.internal.R.style.Animation_Toast;
2616                break;
2617        }
2618
2619        if (attrs.type != TYPE_STATUS_BAR) {
2620            // The status bar is the only window allowed to exhibit keyguard behavior.
2621            attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2622        }
2623
2624        if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
2625            attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
2626        }
2627        final boolean forceWindowDrawsStatusBarBackground =
2628                (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
2629        if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
2630                || forceWindowDrawsStatusBarBackground
2631                        && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) {
2632            attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2633        }
2634    }
2635
2636    void readLidState() {
2637        mLidState = mWindowManagerFuncs.getLidState();
2638    }
2639
2640    private void readCameraLensCoverState() {
2641        mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState();
2642    }
2643
2644    private boolean isHidden(int accessibilityMode) {
2645        switch (accessibilityMode) {
2646            case 1:
2647                return mLidState == LID_CLOSED;
2648            case 2:
2649                return mLidState == LID_OPEN;
2650            default:
2651                return false;
2652        }
2653    }
2654
2655    /** {@inheritDoc} */
2656    @Override
2657    public void adjustConfigurationLw(Configuration config, int keyboardPresence,
2658            int navigationPresence) {
2659        mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0;
2660
2661        readConfigurationDependentBehaviors();
2662        readLidState();
2663
2664        if (config.keyboard == Configuration.KEYBOARD_NOKEYS
2665                || (keyboardPresence == PRESENCE_INTERNAL
2666                        && isHidden(mLidKeyboardAccessibility))) {
2667            config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
2668            if (!mHasSoftInput) {
2669                config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
2670            }
2671        }
2672
2673        if (config.navigation == Configuration.NAVIGATION_NONAV
2674                || (navigationPresence == PRESENCE_INTERNAL
2675                        && isHidden(mLidNavigationAccessibility))) {
2676            config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
2677        }
2678    }
2679
2680    @Override
2681    public void onConfigurationChanged() {
2682        // TODO(multi-display): Define policy for secondary displays.
2683        Context uiContext = ActivityThread.currentActivityThread().getSystemUiContext();
2684        final Resources res = uiContext.getResources();
2685
2686        mStatusBarHeight =
2687                res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
2688
2689        // Height of the navigation bar when presented horizontally at bottom
2690        mNavigationBarHeightForRotationDefault[mPortraitRotation] =
2691        mNavigationBarHeightForRotationDefault[mUpsideDownRotation] =
2692                res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
2693        mNavigationBarHeightForRotationDefault[mLandscapeRotation] =
2694        mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize(
2695                com.android.internal.R.dimen.navigation_bar_height_landscape);
2696
2697        // Width of the navigation bar when presented vertically along one side
2698        mNavigationBarWidthForRotationDefault[mPortraitRotation] =
2699        mNavigationBarWidthForRotationDefault[mUpsideDownRotation] =
2700        mNavigationBarWidthForRotationDefault[mLandscapeRotation] =
2701        mNavigationBarWidthForRotationDefault[mSeascapeRotation] =
2702                res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
2703
2704        if (ALTERNATE_CAR_MODE_NAV_SIZE) {
2705            // Height of the navigation bar when presented horizontally at bottom
2706            mNavigationBarHeightForRotationInCarMode[mPortraitRotation] =
2707            mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] =
2708                    res.getDimensionPixelSize(
2709                            com.android.internal.R.dimen.navigation_bar_height_car_mode);
2710            mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] =
2711            mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize(
2712                    com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode);
2713
2714            // Width of the navigation bar when presented vertically along one side
2715            mNavigationBarWidthForRotationInCarMode[mPortraitRotation] =
2716            mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] =
2717            mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] =
2718            mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] =
2719                    res.getDimensionPixelSize(
2720                            com.android.internal.R.dimen.navigation_bar_width_car_mode);
2721        }
2722    }
2723
2724    @Override
2725    public int getMaxWallpaperLayer() {
2726        return getWindowLayerFromTypeLw(TYPE_STATUS_BAR);
2727    }
2728
2729    private int getNavigationBarWidth(int rotation, int uiMode) {
2730        if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2731            return mNavigationBarWidthForRotationInCarMode[rotation];
2732        } else {
2733            return mNavigationBarWidthForRotationDefault[rotation];
2734        }
2735    }
2736
2737    @Override
2738    public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
2739            int displayId) {
2740        // TODO(multi-display): Support navigation bar on secondary displays.
2741        if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) {
2742            // For a basic navigation bar, when we are in landscape mode we place
2743            // the navigation bar to the side.
2744            if (mNavigationBarCanMove && fullWidth > fullHeight) {
2745                return fullWidth - getNavigationBarWidth(rotation, uiMode);
2746            }
2747        }
2748        return fullWidth;
2749    }
2750
2751    private int getNavigationBarHeight(int rotation, int uiMode) {
2752        if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2753            return mNavigationBarHeightForRotationInCarMode[rotation];
2754        } else {
2755            return mNavigationBarHeightForRotationDefault[rotation];
2756        }
2757    }
2758
2759    @Override
2760    public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
2761            int displayId) {
2762        // TODO(multi-display): Support navigation bar on secondary displays.
2763        if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) {
2764            // For a basic navigation bar, when we are in portrait mode we place
2765            // the navigation bar to the bottom.
2766            if (!mNavigationBarCanMove || fullWidth < fullHeight) {
2767                return fullHeight - getNavigationBarHeight(rotation, uiMode);
2768            }
2769        }
2770        return fullHeight;
2771    }
2772
2773    @Override
2774    public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
2775            int displayId) {
2776        return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode, displayId);
2777    }
2778
2779    @Override
2780    public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
2781            int displayId) {
2782        // There is a separate status bar at the top of the display.  We don't count that as part
2783        // of the fixed decor, since it can hide; however, for purposes of configurations,
2784        // we do want to exclude it since applications can't generally use that part
2785        // of the screen.
2786        // TODO(multi-display): Support status bars on secondary displays.
2787        if (displayId == DEFAULT_DISPLAY) {
2788            return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayId)
2789                    - mStatusBarHeight;
2790        }
2791        return fullHeight;
2792    }
2793
2794    @Override
2795    public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) {
2796        return attrs.type == TYPE_STATUS_BAR;
2797    }
2798
2799    @Override
2800    public boolean canBeHiddenByKeyguardLw(WindowState win) {
2801        switch (win.getAttrs().type) {
2802            case TYPE_STATUS_BAR:
2803            case TYPE_NAVIGATION_BAR:
2804            case TYPE_WALLPAPER:
2805            case TYPE_DREAM:
2806                return false;
2807            default:
2808                // Hide only windows below the keyguard host window.
2809                return getWindowLayerLw(win) < getWindowLayerFromTypeLw(TYPE_STATUS_BAR);
2810        }
2811    }
2812
2813    private boolean shouldBeHiddenByKeyguard(WindowState win, WindowState imeTarget) {
2814
2815        // Keyguard visibility of window from activities are determined over activity visibility.
2816        if (win.getAppToken() != null) {
2817            return false;
2818        }
2819
2820        final LayoutParams attrs = win.getAttrs();
2821        final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleLw() &&
2822                ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0
2823                        || !canBeHiddenByKeyguardLw(imeTarget));
2824
2825        // Show IME over the keyguard if the target allows it
2826        boolean allowWhenLocked = (win.isInputMethodWindow() || imeTarget == this)
2827                && showImeOverKeyguard;;
2828
2829        if (isKeyguardLocked() && isKeyguardOccluded()) {
2830            // Show SHOW_WHEN_LOCKED windows if Keyguard is occluded.
2831            allowWhenLocked |= (attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
2832                    // Show error dialogs over apps that are shown on lockscreen
2833                    || (attrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
2834        }
2835
2836        boolean keyguardLocked = isKeyguardLocked();
2837        boolean hideDockDivider = attrs.type == TYPE_DOCK_DIVIDER
2838                && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
2839        return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == DEFAULT_DISPLAY)
2840                || hideDockDivider;
2841    }
2842
2843    /** {@inheritDoc} */
2844    @Override
2845    public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme,
2846            CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon,
2847            int logo, int windowFlags, Configuration overrideConfig, int displayId) {
2848        if (!SHOW_SPLASH_SCREENS) {
2849            return null;
2850        }
2851        if (packageName == null) {
2852            return null;
2853        }
2854
2855        WindowManager wm = null;
2856        View view = null;
2857
2858        try {
2859            Context context = mContext;
2860            if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen " + packageName
2861                    + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
2862                    + Integer.toHexString(theme));
2863
2864            // Obtain proper context to launch on the right display.
2865            final Context displayContext = getDisplayContext(context, displayId);
2866            if (displayContext == null) {
2867                // Can't show splash screen on requested display, so skip showing at all.
2868                return null;
2869            }
2870            context = displayContext;
2871
2872            if (theme != context.getThemeResId() || labelRes != 0) {
2873                try {
2874                    context = context.createPackageContext(packageName, CONTEXT_RESTRICTED);
2875                    context.setTheme(theme);
2876                } catch (PackageManager.NameNotFoundException e) {
2877                    // Ignore
2878                }
2879            }
2880
2881            if (overrideConfig != null && !overrideConfig.equals(EMPTY)) {
2882                if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: creating context based"
2883                        + " on overrideConfig" + overrideConfig + " for splash screen");
2884                final Context overrideContext = context.createConfigurationContext(overrideConfig);
2885                overrideContext.setTheme(theme);
2886                final TypedArray typedArray = overrideContext.obtainStyledAttributes(
2887                        com.android.internal.R.styleable.Window);
2888                final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
2889                if (resId != 0 && overrideContext.getDrawable(resId) != null) {
2890                    // We want to use the windowBackground for the override context if it is
2891                    // available, otherwise we use the default one to make sure a themed starting
2892                    // window is displayed for the app.
2893                    if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: apply overrideConfig"
2894                            + overrideConfig + " to starting window resId=" + resId);
2895                    context = overrideContext;
2896                }
2897                typedArray.recycle();
2898            }
2899
2900            final PhoneWindow win = new PhoneWindow(context);
2901            win.setIsStartingWindow(true);
2902
2903            CharSequence label = context.getResources().getText(labelRes, null);
2904            // Only change the accessibility title if the label is localized
2905            if (label != null) {
2906                win.setTitle(label, true);
2907            } else {
2908                win.setTitle(nonLocalizedLabel, false);
2909            }
2910
2911            win.setType(
2912                WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
2913
2914            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
2915                // Assumes it's safe to show starting windows of launched apps while
2916                // the keyguard is being hidden. This is okay because starting windows never show
2917                // secret information.
2918                if (mKeyguardOccluded) {
2919                    windowFlags |= FLAG_SHOW_WHEN_LOCKED;
2920                }
2921            }
2922
2923            // Force the window flags: this is a fake window, so it is not really
2924            // touchable or focusable by the user.  We also add in the ALT_FOCUSABLE_IM
2925            // flag because we do know that the next window will take input
2926            // focus, so we want to get the IME window up on top of us right away.
2927            win.setFlags(
2928                windowFlags|
2929                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2930                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2931                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
2932                windowFlags|
2933                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2934                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2935                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
2936
2937            win.setDefaultIcon(icon);
2938            win.setDefaultLogo(logo);
2939
2940            win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
2941                    WindowManager.LayoutParams.MATCH_PARENT);
2942
2943            final WindowManager.LayoutParams params = win.getAttributes();
2944            params.token = appToken;
2945            params.packageName = packageName;
2946            params.windowAnimations = win.getWindowStyle().getResourceId(
2947                    com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
2948            params.privateFlags |=
2949                    WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
2950            params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
2951
2952            if (!compatInfo.supportsScreen()) {
2953                params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
2954            }
2955
2956            params.setTitle("Splash Screen " + packageName);
2957            addSplashscreenContent(win, context);
2958
2959            wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
2960            view = win.getDecorView();
2961
2962            if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "Adding splash screen window for "
2963                + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null));
2964
2965            wm.addView(view, params);
2966
2967            // Only return the view if it was successfully added to the
2968            // window manager... which we can tell by it having a parent.
2969            return view.getParent() != null ? new SplashScreenSurface(view, appToken) : null;
2970        } catch (WindowManager.BadTokenException e) {
2971            // ignore
2972            Log.w(TAG, appToken + " already running, starting window not displayed. " +
2973                    e.getMessage());
2974        } catch (RuntimeException e) {
2975            // don't crash if something else bad happens, for example a
2976            // failure loading resources because we are loading from an app
2977            // on external storage that has been unmounted.
2978            Log.w(TAG, appToken + " failed creating starting window", e);
2979        } finally {
2980            if (view != null && view.getParent() == null) {
2981                Log.w(TAG, "view not successfully added to wm, removing view");
2982                wm.removeViewImmediate(view);
2983            }
2984        }
2985
2986        return null;
2987    }
2988
2989    private void addSplashscreenContent(PhoneWindow win, Context ctx) {
2990        final TypedArray a = ctx.obtainStyledAttributes(R.styleable.Window);
2991        final int resId = a.getResourceId(R.styleable.Window_windowSplashscreenContent, 0);
2992        a.recycle();
2993        if (resId == 0) {
2994            return;
2995        }
2996        final Drawable drawable = ctx.getDrawable(resId);
2997        if (drawable == null) {
2998            return;
2999        }
3000
3001        // We wrap this into a view so the system insets get applied to the drawable.
3002        final View v = new View(ctx);
3003        v.setBackground(drawable);
3004        win.setContentView(v);
3005    }
3006
3007    /** Obtain proper context for showing splash screen on the provided display. */
3008    private Context getDisplayContext(Context context, int displayId) {
3009        if (displayId == DEFAULT_DISPLAY) {
3010            // The default context fits.
3011            return context;
3012        }
3013
3014        final DisplayManager dm = (DisplayManager) context.getSystemService(DISPLAY_SERVICE);
3015        final Display targetDisplay = dm.getDisplay(displayId);
3016        if (targetDisplay == null) {
3017            // Failed to obtain the non-default display where splash screen should be shown,
3018            // lets not show at all.
3019            return null;
3020        }
3021
3022        return context.createDisplayContext(targetDisplay);
3023    }
3024
3025    /**
3026     * Preflight adding a window to the system.
3027     *
3028     * Currently enforces that three window types are singletons:
3029     * <ul>
3030     * <li>STATUS_BAR_TYPE</li>
3031     * <li>KEYGUARD_TYPE</li>
3032     * </ul>
3033     *
3034     * @param win The window to be added
3035     * @param attrs Information about the window to be added
3036     *
3037     * @return If ok, WindowManagerImpl.ADD_OKAY.  If too many singletons,
3038     * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
3039     */
3040    @Override
3041    public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
3042        switch (attrs.type) {
3043            case TYPE_STATUS_BAR:
3044                mContext.enforceCallingOrSelfPermission(
3045                        android.Manifest.permission.STATUS_BAR_SERVICE,
3046                        "PhoneWindowManager");
3047                if (mStatusBar != null) {
3048                    if (mStatusBar.isAlive()) {
3049                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
3050                    }
3051                }
3052                mStatusBar = win;
3053                mStatusBarController.setWindow(win);
3054                setKeyguardOccludedLw(mKeyguardOccluded, true /* force */);
3055                break;
3056            case TYPE_NAVIGATION_BAR:
3057                mContext.enforceCallingOrSelfPermission(
3058                        android.Manifest.permission.STATUS_BAR_SERVICE,
3059                        "PhoneWindowManager");
3060                if (mNavigationBar != null) {
3061                    if (mNavigationBar.isAlive()) {
3062                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
3063                    }
3064                }
3065                mNavigationBar = win;
3066                mNavigationBarController.setWindow(win);
3067                mNavigationBarController.setOnBarVisibilityChangedListener(
3068                        mNavBarVisibilityListener, true);
3069                if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
3070                break;
3071            case TYPE_NAVIGATION_BAR_PANEL:
3072            case TYPE_STATUS_BAR_PANEL:
3073            case TYPE_STATUS_BAR_SUB_PANEL:
3074            case TYPE_VOICE_INTERACTION_STARTING:
3075                mContext.enforceCallingOrSelfPermission(
3076                        android.Manifest.permission.STATUS_BAR_SERVICE,
3077                        "PhoneWindowManager");
3078                break;
3079        }
3080        return ADD_OKAY;
3081    }
3082
3083    /** {@inheritDoc} */
3084    @Override
3085    public void removeWindowLw(WindowState win) {
3086        if (mStatusBar == win) {
3087            mStatusBar = null;
3088            mStatusBarController.setWindow(null);
3089        } else if (mNavigationBar == win) {
3090            mNavigationBar = null;
3091            mNavigationBarController.setWindow(null);
3092        }
3093    }
3094
3095    static final boolean PRINT_ANIM = false;
3096
3097    /** {@inheritDoc} */
3098    @Override
3099    public int selectAnimationLw(WindowState win, int transit) {
3100        if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
3101              + ": transit=" + transit);
3102        if (win == mStatusBar) {
3103            final boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
3104            final boolean expanded = win.getAttrs().height == MATCH_PARENT
3105                    && win.getAttrs().width == MATCH_PARENT;
3106            if (isKeyguard || expanded) {
3107                return -1;
3108            }
3109            if (transit == TRANSIT_EXIT
3110                    || transit == TRANSIT_HIDE) {
3111                return R.anim.dock_top_exit;
3112            } else if (transit == TRANSIT_ENTER
3113                    || transit == TRANSIT_SHOW) {
3114                return R.anim.dock_top_enter;
3115            }
3116        } else if (win == mNavigationBar) {
3117            if (win.getAttrs().windowAnimations != 0) {
3118                return 0;
3119            }
3120            // This can be on either the bottom or the right or the left.
3121            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
3122                if (transit == TRANSIT_EXIT
3123                        || transit == TRANSIT_HIDE) {
3124                    if (isKeyguardShowingAndNotOccluded()) {
3125                        return R.anim.dock_bottom_exit_keyguard;
3126                    } else {
3127                        return R.anim.dock_bottom_exit;
3128                    }
3129                } else if (transit == TRANSIT_ENTER
3130                        || transit == TRANSIT_SHOW) {
3131                    return R.anim.dock_bottom_enter;
3132                }
3133            } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
3134                if (transit == TRANSIT_EXIT
3135                        || transit == TRANSIT_HIDE) {
3136                    return R.anim.dock_right_exit;
3137                } else if (transit == TRANSIT_ENTER
3138                        || transit == TRANSIT_SHOW) {
3139                    return R.anim.dock_right_enter;
3140                }
3141            } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
3142                if (transit == TRANSIT_EXIT
3143                        || transit == TRANSIT_HIDE) {
3144                    return R.anim.dock_left_exit;
3145                } else if (transit == TRANSIT_ENTER
3146                        || transit == TRANSIT_SHOW) {
3147                    return R.anim.dock_left_enter;
3148                }
3149            }
3150        } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) {
3151            return selectDockedDividerAnimationLw(win, transit);
3152        }
3153
3154        if (transit == TRANSIT_PREVIEW_DONE) {
3155            if (win.hasAppShownWindows()) {
3156                if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
3157                return com.android.internal.R.anim.app_starting_exit;
3158            }
3159        } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
3160                && transit == TRANSIT_ENTER) {
3161            // Special case: we are animating in a dream, while the keyguard
3162            // is shown.  We don't want an animation on the dream, because
3163            // we need it shown immediately with the keyguard animating away
3164            // to reveal it.
3165            return -1;
3166        }
3167
3168        return 0;
3169    }
3170
3171    private int selectDockedDividerAnimationLw(WindowState win, int transit) {
3172        int insets = mWindowManagerFuncs.getDockedDividerInsetsLw();
3173
3174        // If the divider is behind the navigation bar, don't animate.
3175        final Rect frame = win.getFrameLw();
3176        final boolean behindNavBar = mNavigationBar != null
3177                && ((mNavigationBarPosition == NAV_BAR_BOTTOM
3178                        && frame.top + insets >= mNavigationBar.getFrameLw().top)
3179                || (mNavigationBarPosition == NAV_BAR_RIGHT
3180                        && frame.left + insets >= mNavigationBar.getFrameLw().left)
3181                || (mNavigationBarPosition == NAV_BAR_LEFT
3182                        && frame.right - insets <= mNavigationBar.getFrameLw().right));
3183        final boolean landscape = frame.height() > frame.width();
3184        final boolean offscreenLandscape = landscape && (frame.right - insets <= 0
3185                || frame.left + insets >= win.getDisplayFrameLw().right);
3186        final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0
3187                || frame.bottom + insets >= win.getDisplayFrameLw().bottom);
3188        final boolean offscreen = offscreenLandscape || offscreenPortrait;
3189        if (behindNavBar || offscreen) {
3190            return 0;
3191        }
3192        if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
3193            return R.anim.fade_in;
3194        } else if (transit == TRANSIT_EXIT) {
3195            return R.anim.fade_out;
3196        } else {
3197            return 0;
3198        }
3199    }
3200
3201    @Override
3202    public void selectRotationAnimationLw(int anim[]) {
3203        // If the screen is off or non-interactive, force a jumpcut.
3204        final boolean forceJumpcut = !mScreenOnFully || !okToAnimate();
3205        if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
3206                + mTopFullscreenOpaqueWindowState + " rotationAnimation="
3207                + (mTopFullscreenOpaqueWindowState == null ?
3208                        "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation)
3209                + " forceJumpcut=" + forceJumpcut);
3210        if (forceJumpcut) {
3211            anim[0] = R.anim.rotation_animation_jump_exit;
3212            anim[1] = R.anim.rotation_animation_enter;
3213            return;
3214        }
3215        if (mTopFullscreenOpaqueWindowState != null) {
3216            int animationHint = mTopFullscreenOpaqueWindowState.getRotationAnimationHint();
3217            if (animationHint < 0 && mTopIsFullscreen) {
3218                animationHint = mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation;
3219            }
3220            switch (animationHint) {
3221                case ROTATION_ANIMATION_CROSSFADE:
3222                case ROTATION_ANIMATION_SEAMLESS: // Crossfade is fallback for seamless.
3223                    anim[0] = R.anim.rotation_animation_xfade_exit;
3224                    anim[1] = R.anim.rotation_animation_enter;
3225                    break;
3226                case ROTATION_ANIMATION_JUMPCUT:
3227                    anim[0] = R.anim.rotation_animation_jump_exit;
3228                    anim[1] = R.anim.rotation_animation_enter;
3229                    break;
3230                case ROTATION_ANIMATION_ROTATE:
3231                default:
3232                    anim[0] = anim[1] = 0;
3233                    break;
3234            }
3235        } else {
3236            anim[0] = anim[1] = 0;
3237        }
3238    }
3239
3240    @Override
3241    public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId,
3242            boolean forceDefault) {
3243        switch (exitAnimId) {
3244            case R.anim.rotation_animation_xfade_exit:
3245            case R.anim.rotation_animation_jump_exit:
3246                // These are the only cases that matter.
3247                if (forceDefault) {
3248                    return false;
3249                }
3250                int anim[] = new int[2];
3251                selectRotationAnimationLw(anim);
3252                return (exitAnimId == anim[0] && enterAnimId == anim[1]);
3253            default:
3254                return true;
3255        }
3256    }
3257
3258    @Override
3259    public Animation createHiddenByKeyguardExit(boolean onWallpaper,
3260            boolean goingToNotificationShade) {
3261        if (goingToNotificationShade) {
3262            return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
3263        }
3264
3265        AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ?
3266                    R.anim.lock_screen_behind_enter_wallpaper :
3267                    R.anim.lock_screen_behind_enter);
3268
3269        // TODO: Use XML interpolators when we have log interpolators available in XML.
3270        final List<Animation> animations = set.getAnimations();
3271        for (int i = animations.size() - 1; i >= 0; --i) {
3272            animations.get(i).setInterpolator(mLogDecelerateInterpolator);
3273        }
3274
3275        return set;
3276    }
3277
3278
3279    @Override
3280    public Animation createKeyguardWallpaperExit(boolean goingToNotificationShade) {
3281        if (goingToNotificationShade) {
3282            return null;
3283        } else {
3284            return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
3285        }
3286    }
3287
3288    private static void awakenDreams() {
3289        IDreamManager dreamManager = getDreamManager();
3290        if (dreamManager != null) {
3291            try {
3292                dreamManager.awaken();
3293            } catch (RemoteException e) {
3294                // fine, stay asleep then
3295            }
3296        }
3297    }
3298
3299    static IDreamManager getDreamManager() {
3300        return IDreamManager.Stub.asInterface(
3301                ServiceManager.checkService(DreamService.DREAM_SERVICE));
3302    }
3303
3304    TelecomManager getTelecommService() {
3305        return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
3306    }
3307
3308    static IAudioService getAudioService() {
3309        IAudioService audioService = IAudioService.Stub.asInterface(
3310                ServiceManager.checkService(Context.AUDIO_SERVICE));
3311        if (audioService == null) {
3312            Log.w(TAG, "Unable to find IAudioService interface.");
3313        }
3314        return audioService;
3315    }
3316
3317    boolean keyguardOn() {
3318        return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode();
3319    }
3320
3321    private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
3322            WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
3323            WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
3324        };
3325
3326    /** {@inheritDoc} */
3327    @Override
3328    public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
3329        final boolean keyguardOn = keyguardOn();
3330        final int keyCode = event.getKeyCode();
3331        final int repeatCount = event.getRepeatCount();
3332        final int metaState = event.getMetaState();
3333        final int flags = event.getFlags();
3334        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
3335        final boolean canceled = event.isCanceled();
3336
3337        if (DEBUG_INPUT) {
3338            Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
3339                    + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
3340                    + " canceled=" + canceled);
3341        }
3342
3343        // If we think we might have a volume down & power key chord on the way
3344        // but we're not sure, then tell the dispatcher to wait a little while and
3345        // try again later before dispatching.
3346        if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
3347            if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
3348                final long now = SystemClock.uptimeMillis();
3349                final long timeoutTime = mScreenshotChordVolumeDownKeyTime
3350                        + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
3351                if (now < timeoutTime) {
3352                    return timeoutTime - now;
3353                }
3354            }
3355            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3356                    && mScreenshotChordVolumeDownKeyConsumed) {
3357                if (!down) {
3358                    mScreenshotChordVolumeDownKeyConsumed = false;
3359                }
3360                return -1;
3361            }
3362        }
3363
3364        // If an accessibility shortcut might be partially complete, hold off dispatching until we
3365        // know if it is complete or not
3366        if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(false)
3367                && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
3368            if (mScreenshotChordVolumeDownKeyTriggered ^ mA11yShortcutChordVolumeUpKeyTriggered) {
3369                final long now = SystemClock.uptimeMillis();
3370                final long timeoutTime = (mScreenshotChordVolumeDownKeyTriggered
3371                        ? mScreenshotChordVolumeDownKeyTime : mA11yShortcutChordVolumeUpKeyTime)
3372                        + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
3373                if (now < timeoutTime) {
3374                    return timeoutTime - now;
3375                }
3376            }
3377            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && mScreenshotChordVolumeDownKeyConsumed) {
3378                if (!down) {
3379                    mScreenshotChordVolumeDownKeyConsumed = false;
3380                }
3381                return -1;
3382            }
3383            if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mA11yShortcutChordVolumeUpKeyConsumed) {
3384                if (!down) {
3385                    mA11yShortcutChordVolumeUpKeyConsumed = false;
3386                }
3387                return -1;
3388            }
3389        }
3390
3391        // Cancel any pending meta actions if we see any other keys being pressed between the down
3392        // of the meta key and its corresponding up.
3393        if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
3394            mPendingMetaAction = false;
3395        }
3396        // Any key that is not Alt or Meta cancels Caps Lock combo tracking.
3397        if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) {
3398            mPendingCapsLockToggle = false;
3399        }
3400
3401        // First we always handle the home key here, so applications
3402        // can never break it, although if keyguard is on, we do let
3403        // it handle it, because that gives us the correct 5 second
3404        // timeout.
3405        if (keyCode == KeyEvent.KEYCODE_HOME) {
3406
3407            // If we have released the home key, and didn't do anything else
3408            // while it was pressed, then it is time to go home!
3409            if (!down) {
3410                cancelPreloadRecentApps();
3411
3412                mHomePressed = false;
3413                if (mHomeConsumed) {
3414                    mHomeConsumed = false;
3415                    return -1;
3416                }
3417
3418                if (canceled) {
3419                    Log.i(TAG, "Ignoring HOME; event canceled.");
3420                    return -1;
3421                }
3422
3423                // Delay handling home if a double-tap is possible.
3424                if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
3425                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
3426                    mHomeDoubleTapPending = true;
3427                    mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
3428                            ViewConfiguration.getDoubleTapTimeout());
3429                    return -1;
3430                }
3431
3432                handleShortPressOnHome();
3433                return -1;
3434            }
3435
3436            // If a system window has focus, then it doesn't make sense
3437            // right now to interact with applications.
3438            WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
3439            if (attrs != null) {
3440                final int type = attrs.type;
3441                if (type == TYPE_KEYGUARD_DIALOG
3442                        || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
3443                    // the "app" is keyguard, so give it the key
3444                    return 0;
3445                }
3446                final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
3447                for (int i=0; i<typeCount; i++) {
3448                    if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
3449                        // don't do anything, but also don't pass it to the app
3450                        return -1;
3451                    }
3452                }
3453            }
3454
3455            // Remember that home is pressed and handle special actions.
3456            if (repeatCount == 0) {
3457                mHomePressed = true;
3458                if (mHomeDoubleTapPending) {
3459                    mHomeDoubleTapPending = false;
3460                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
3461                    handleDoubleTapOnHome();
3462                } else if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
3463                    preloadRecentApps();
3464                }
3465            } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
3466                if (!keyguardOn) {
3467                    handleLongPressOnHome(event.getDeviceId());
3468                }
3469            }
3470            return -1;
3471        } else if (keyCode == KeyEvent.KEYCODE_MENU) {
3472            // Hijack modified menu keys for debugging features
3473            final int chordBug = KeyEvent.META_SHIFT_ON;
3474
3475            if (down && repeatCount == 0) {
3476                if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
3477                    Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
3478                    mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
3479                            null, null, null, 0, null, null);
3480                    return -1;
3481                }
3482            }
3483        } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
3484            if (down) {
3485                if (repeatCount == 0) {
3486                    mSearchKeyShortcutPending = true;
3487                    mConsumeSearchKeyUp = false;
3488                }
3489            } else {
3490                mSearchKeyShortcutPending = false;
3491                if (mConsumeSearchKeyUp) {
3492                    mConsumeSearchKeyUp = false;
3493                    return -1;
3494                }
3495            }
3496            return 0;
3497        } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
3498            if (!keyguardOn) {
3499                if (down && repeatCount == 0) {
3500                    preloadRecentApps();
3501                } else if (!down) {
3502                    toggleRecentApps();
3503                }
3504            }
3505            return -1;
3506        } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) {
3507            if (down) {
3508                IStatusBarService service = getStatusBarService();
3509                if (service != null) {
3510                    try {
3511                        service.expandNotificationsPanel();
3512                    } catch (RemoteException e) {
3513                        // do nothing.
3514                    }
3515                }
3516            }
3517        } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed()
3518                && event.isCtrlPressed()) {
3519            if (down && repeatCount == 0) {
3520                int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION
3521                        : TAKE_SCREENSHOT_FULLSCREEN;
3522                mScreenshotRunnable.setScreenshotType(type);
3523                mHandler.post(mScreenshotRunnable);
3524                return -1;
3525            }
3526        } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
3527            if (down && repeatCount == 0 && !isKeyguardLocked()) {
3528                toggleKeyboardShortcutsMenu(event.getDeviceId());
3529            }
3530        } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
3531            if (down) {
3532                if (repeatCount == 0) {
3533                    mAssistKeyLongPressed = false;
3534                } else if (repeatCount == 1) {
3535                    mAssistKeyLongPressed = true;
3536                    if (!keyguardOn) {
3537                         launchAssistLongPressAction();
3538                    }
3539                }
3540            } else {
3541                if (mAssistKeyLongPressed) {
3542                    mAssistKeyLongPressed = false;
3543                } else {
3544                    if (!keyguardOn) {
3545                        launchAssistAction(null, event.getDeviceId());
3546                    }
3547                }
3548            }
3549            return -1;
3550        } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
3551            if (!down) {
3552                Intent voiceIntent;
3553                if (!keyguardOn) {
3554                    voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
3555                } else {
3556                    IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
3557                            ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
3558                    if (dic != null) {
3559                        try {
3560                            dic.exitIdle("voice-search");
3561                        } catch (RemoteException e) {
3562                        }
3563                    }
3564                    voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
3565                    voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
3566                }
3567                startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
3568            }
3569        } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
3570            if (down && repeatCount == 0) {
3571                mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
3572                mHandler.post(mScreenshotRunnable);
3573            }
3574            return -1;
3575        } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP
3576                || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) {
3577            if (down) {
3578                int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
3579
3580                // Disable autobrightness if it's on
3581                int auto = Settings.System.getIntForUser(
3582                        mContext.getContentResolver(),
3583                        Settings.System.SCREEN_BRIGHTNESS_MODE,
3584                        Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3585                        UserHandle.USER_CURRENT_OR_SELF);
3586                if (auto != 0) {
3587                    Settings.System.putIntForUser(mContext.getContentResolver(),
3588                            Settings.System.SCREEN_BRIGHTNESS_MODE,
3589                            Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3590                            UserHandle.USER_CURRENT_OR_SELF);
3591                }
3592
3593                int min = mPowerManager.getMinimumScreenBrightnessSetting();
3594                int max = mPowerManager.getMaximumScreenBrightnessSetting();
3595                int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction;
3596                int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
3597                        Settings.System.SCREEN_BRIGHTNESS,
3598                        mPowerManager.getDefaultScreenBrightnessSetting(),
3599                        UserHandle.USER_CURRENT_OR_SELF);
3600                brightness += step;
3601                // Make sure we don't go beyond the limits.
3602                brightness = Math.min(max, brightness);
3603                brightness = Math.max(min, brightness);
3604
3605                Settings.System.putIntForUser(mContext.getContentResolver(),
3606                        Settings.System.SCREEN_BRIGHTNESS, brightness,
3607                        UserHandle.USER_CURRENT_OR_SELF);
3608                startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
3609                        UserHandle.CURRENT_OR_SELF);
3610            }
3611            return -1;
3612        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
3613                || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3614                || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
3615            if (mUseTvRouting || mHandleVolumeKeysInWM) {
3616                // On TVs or when the configuration is enabled, volume keys never
3617                // go to the foreground app.
3618                dispatchDirectAudioEvent(event);
3619                return -1;
3620            }
3621
3622            // If the device is in Vr mode, drop the volume keys and don't
3623            // forward it to the application/dispatch the audio event.
3624            if (mPersistentVrModeEnabled) {
3625                return -1;
3626            }
3627        } else if (keyCode == KeyEvent.KEYCODE_TAB && event.isMetaPressed()) {
3628            // Pass through keyboard navigation keys.
3629            return 0;
3630        } else if (mHasFeatureLeanback && interceptBugreportGestureTv(keyCode, down)) {
3631            return -1;
3632        } else if (mHasFeatureLeanback && interceptAccessibilityGestureTv(keyCode, down)) {
3633            return -1;
3634        } else if (keyCode == KeyEvent.KEYCODE_ALL_APPS) {
3635            if (!down) {
3636                mHandler.removeMessages(MSG_HANDLE_ALL_APPS);
3637                Message msg = mHandler.obtainMessage(MSG_HANDLE_ALL_APPS);
3638                msg.setAsynchronous(true);
3639                msg.sendToTarget();
3640            }
3641            return -1;
3642        }
3643
3644        // Toggle Caps Lock on META-ALT.
3645        boolean actionTriggered = false;
3646        if (KeyEvent.isModifierKey(keyCode)) {
3647            if (!mPendingCapsLockToggle) {
3648                // Start tracking meta state for combo.
3649                mInitialMetaState = mMetaState;
3650                mPendingCapsLockToggle = true;
3651            } else if (event.getAction() == KeyEvent.ACTION_UP) {
3652                int altOnMask = mMetaState & KeyEvent.META_ALT_MASK;
3653                int metaOnMask = mMetaState & KeyEvent.META_META_MASK;
3654
3655                // Check for Caps Lock toggle
3656                if ((metaOnMask != 0) && (altOnMask != 0)) {
3657                    // Check if nothing else is pressed
3658                    if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) {
3659                        // Handle Caps Lock Toggle
3660                        mInputManagerInternal.toggleCapsLock(event.getDeviceId());
3661                        actionTriggered = true;
3662                    }
3663                }
3664
3665                // Always stop tracking when key goes up.
3666                mPendingCapsLockToggle = false;
3667            }
3668        }
3669        // Store current meta state to be able to evaluate it later.
3670        mMetaState = metaState;
3671
3672        if (actionTriggered) {
3673            return -1;
3674        }
3675
3676        if (KeyEvent.isMetaKey(keyCode)) {
3677            if (down) {
3678                mPendingMetaAction = true;
3679            } else if (mPendingMetaAction) {
3680                launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId());
3681            }
3682            return -1;
3683        }
3684
3685        // Shortcuts are invoked through Search+key, so intercept those here
3686        // Any printing key that is chorded with Search should be consumed
3687        // even if no shortcut was invoked.  This prevents text from being
3688        // inadvertently inserted when using a keyboard that has built-in macro
3689        // shortcut keys (that emit Search+x) and some of them are not registered.
3690        if (mSearchKeyShortcutPending) {
3691            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3692            if (kcm.isPrintingKey(keyCode)) {
3693                mConsumeSearchKeyUp = true;
3694                mSearchKeyShortcutPending = false;
3695                if (down && repeatCount == 0 && !keyguardOn) {
3696                    Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
3697                    if (shortcutIntent != null) {
3698                        shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3699                        try {
3700                            startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3701                            dismissKeyboardShortcutsMenu();
3702                        } catch (ActivityNotFoundException ex) {
3703                            Slog.w(TAG, "Dropping shortcut key combination because "
3704                                    + "the activity to which it is registered was not found: "
3705                                    + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);
3706                        }
3707                    } else {
3708                        Slog.i(TAG, "Dropping unregistered shortcut key combination: "
3709                                + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));
3710                    }
3711                }
3712                return -1;
3713            }
3714        }
3715
3716        // Invoke shortcuts using Meta.
3717        if (down && repeatCount == 0 && !keyguardOn
3718                && (metaState & KeyEvent.META_META_ON) != 0) {
3719            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3720            if (kcm.isPrintingKey(keyCode)) {
3721                Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
3722                        metaState & ~(KeyEvent.META_META_ON
3723                                | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
3724                if (shortcutIntent != null) {
3725                    shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3726                    try {
3727                        startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3728                        dismissKeyboardShortcutsMenu();
3729                    } catch (ActivityNotFoundException ex) {
3730                        Slog.w(TAG, "Dropping shortcut key combination because "
3731                                + "the activity to which it is registered was not found: "
3732                                + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
3733                    }
3734                    return -1;
3735                }
3736            }
3737        }
3738
3739        // Handle application launch keys.
3740        if (down && repeatCount == 0 && !keyguardOn) {
3741            String category = sApplicationLaunchKeyCategories.get(keyCode);
3742            if (category != null) {
3743                Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
3744                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3745                try {
3746                    startActivityAsUser(intent, UserHandle.CURRENT);
3747                    dismissKeyboardShortcutsMenu();
3748                } catch (ActivityNotFoundException ex) {
3749                    Slog.w(TAG, "Dropping application launch key because "
3750                            + "the activity to which it is registered was not found: "
3751                            + "keyCode=" + keyCode + ", category=" + category, ex);
3752                }
3753                return -1;
3754            }
3755        }
3756
3757        // Display task switcher for ALT-TAB.
3758        if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
3759            if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
3760                final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
3761                if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
3762                    mRecentAppsHeldModifiers = shiftlessModifiers;
3763                    showRecentApps(true, false);
3764                    return -1;
3765                }
3766            }
3767        } else if (!down && mRecentAppsHeldModifiers != 0
3768                && (metaState & mRecentAppsHeldModifiers) == 0) {
3769            mRecentAppsHeldModifiers = 0;
3770            hideRecentApps(true, false);
3771        }
3772
3773        // Handle input method switching.
3774        if (down && repeatCount == 0
3775                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3776                        || (keyCode == KeyEvent.KEYCODE_SPACE
3777                                && (metaState & KeyEvent.META_META_MASK) != 0))) {
3778            final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0;
3779            mWindowManagerFuncs.switchInputMethod(forwardDirection);
3780            return -1;
3781        }
3782        if (mLanguageSwitchKeyPressed && !down
3783                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3784                        || keyCode == KeyEvent.KEYCODE_SPACE)) {
3785            mLanguageSwitchKeyPressed = false;
3786            return -1;
3787        }
3788
3789        if (isValidGlobalKey(keyCode)
3790                && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
3791            return -1;
3792        }
3793
3794        if (down) {
3795            long shortcutCode = keyCode;
3796            if (event.isCtrlPressed()) {
3797                shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
3798            }
3799
3800            if (event.isAltPressed()) {
3801                shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
3802            }
3803
3804            if (event.isShiftPressed()) {
3805                shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
3806            }
3807
3808            if (event.isMetaPressed()) {
3809                shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE;
3810            }
3811
3812            IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode);
3813            if (shortcutService != null) {
3814                try {
3815                    if (isUserSetupComplete()) {
3816                        shortcutService.notifyShortcutKeyPressed(shortcutCode);
3817                    }
3818                } catch (RemoteException e) {
3819                    mShortcutKeyServices.delete(shortcutCode);
3820                }
3821                return -1;
3822            }
3823        }
3824
3825        // Reserve all the META modifier combos for system behavior
3826        if ((metaState & KeyEvent.META_META_ON) != 0) {
3827            return -1;
3828        }
3829
3830        // Let the application handle the key.
3831        return 0;
3832    }
3833
3834    /**
3835     * TV only: recognizes a remote control gesture for capturing a bug report.
3836     */
3837    private boolean interceptBugreportGestureTv(int keyCode, boolean down) {
3838        // The bugreport capture chord is a long press on DPAD CENTER and BACK simultaneously.
3839        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
3840            mBugreportTvKey1Pressed = down;
3841        } else if (keyCode == KeyEvent.KEYCODE_BACK) {
3842            mBugreportTvKey2Pressed = down;
3843        }
3844
3845        if (mBugreportTvKey1Pressed && mBugreportTvKey2Pressed) {
3846            if (!mBugreportTvScheduled) {
3847                mBugreportTvScheduled = true;
3848                Message msg = Message.obtain(mHandler, MSG_BUGREPORT_TV);
3849                msg.setAsynchronous(true);
3850                mHandler.sendMessageDelayed(msg, BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS);
3851            }
3852        } else if (mBugreportTvScheduled) {
3853            mHandler.removeMessages(MSG_BUGREPORT_TV);
3854            mBugreportTvScheduled = false;
3855        }
3856
3857        return mBugreportTvScheduled;
3858    }
3859
3860    /**
3861     * TV only: recognizes a remote control gesture as Accessibility shortcut.
3862     * Shortcut: Long press (BACK + DPAD_DOWN)
3863     */
3864    private boolean interceptAccessibilityGestureTv(int keyCode, boolean down) {
3865        if (keyCode == KeyEvent.KEYCODE_BACK) {
3866            mAccessibilityTvKey1Pressed = down;
3867        } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
3868            mAccessibilityTvKey2Pressed = down;
3869        }
3870
3871        if (mAccessibilityTvKey1Pressed && mAccessibilityTvKey2Pressed) {
3872            if (!mAccessibilityTvScheduled) {
3873                mAccessibilityTvScheduled = true;
3874                Message msg = Message.obtain(mHandler, MSG_ACCESSIBILITY_TV);
3875                msg.setAsynchronous(true);
3876                mHandler.sendMessageDelayed(msg,
3877                        ViewConfiguration.get(mContext).getAccessibilityShortcutKeyTimeout());
3878            }
3879        } else if (mAccessibilityTvScheduled) {
3880            mHandler.removeMessages(MSG_ACCESSIBILITY_TV);
3881            mAccessibilityTvScheduled = false;
3882        }
3883
3884        return mAccessibilityTvScheduled;
3885    }
3886
3887    private void takeBugreport() {
3888        if ("1".equals(SystemProperties.get("ro.debuggable"))
3889                || Settings.Global.getInt(mContext.getContentResolver(),
3890                        Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) == 1) {
3891            try {
3892                ActivityManager.getService()
3893                        .requestBugReport(ActivityManager.BUGREPORT_OPTION_INTERACTIVE);
3894            } catch (RemoteException e) {
3895                Slog.e(TAG, "Error taking bugreport", e);
3896            }
3897        }
3898    }
3899
3900    /** {@inheritDoc} */
3901    @Override
3902    public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
3903        // Note: This method is only called if the initial down was unhandled.
3904        if (DEBUG_INPUT) {
3905            Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
3906                    + ", flags=" + event.getFlags()
3907                    + ", keyCode=" + event.getKeyCode()
3908                    + ", scanCode=" + event.getScanCode()
3909                    + ", metaState=" + event.getMetaState()
3910                    + ", repeatCount=" + event.getRepeatCount()
3911                    + ", policyFlags=" + policyFlags);
3912        }
3913
3914        KeyEvent fallbackEvent = null;
3915        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3916            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3917            final int keyCode = event.getKeyCode();
3918            final int metaState = event.getMetaState();
3919            final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
3920                    && event.getRepeatCount() == 0;
3921
3922            // Check for fallback actions specified by the key character map.
3923            final FallbackAction fallbackAction;
3924            if (initialDown) {
3925                fallbackAction = kcm.getFallbackAction(keyCode, metaState);
3926            } else {
3927                fallbackAction = mFallbackActions.get(keyCode);
3928            }
3929
3930            if (fallbackAction != null) {
3931                if (DEBUG_INPUT) {
3932                    Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode
3933                            + " metaState=" + Integer.toHexString(fallbackAction.metaState));
3934                }
3935
3936                final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
3937                fallbackEvent = KeyEvent.obtain(
3938                        event.getDownTime(), event.getEventTime(),
3939                        event.getAction(), fallbackAction.keyCode,
3940                        event.getRepeatCount(), fallbackAction.metaState,
3941                        event.getDeviceId(), event.getScanCode(),
3942                        flags, event.getSource(), null);
3943
3944                if (!interceptFallback(win, fallbackEvent, policyFlags)) {
3945                    fallbackEvent.recycle();
3946                    fallbackEvent = null;
3947                }
3948
3949                if (initialDown) {
3950                    mFallbackActions.put(keyCode, fallbackAction);
3951                } else if (event.getAction() == KeyEvent.ACTION_UP) {
3952                    mFallbackActions.remove(keyCode);
3953                    fallbackAction.recycle();
3954                }
3955            }
3956        }
3957
3958        if (DEBUG_INPUT) {
3959            if (fallbackEvent == null) {
3960                Slog.d(TAG, "No fallback.");
3961            } else {
3962                Slog.d(TAG, "Performing fallback: " + fallbackEvent);
3963            }
3964        }
3965        return fallbackEvent;
3966    }
3967
3968    private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
3969        int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
3970        if ((actions & ACTION_PASS_TO_USER) != 0) {
3971            long delayMillis = interceptKeyBeforeDispatching(
3972                    win, fallbackEvent, policyFlags);
3973            if (delayMillis == 0) {
3974                return true;
3975            }
3976        }
3977        return false;
3978    }
3979
3980    @Override
3981    public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
3982            throws RemoteException {
3983        synchronized (mLock) {
3984            IShortcutService service = mShortcutKeyServices.get(shortcutCode);
3985            if (service != null && service.asBinder().pingBinder()) {
3986                throw new RemoteException("Key already exists.");
3987            }
3988
3989            mShortcutKeyServices.put(shortcutCode, shortcutService);
3990        }
3991    }
3992
3993    @Override
3994    public void onKeyguardOccludedChangedLw(boolean occluded) {
3995        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
3996            mPendingKeyguardOccluded = occluded;
3997            mKeyguardOccludedChanged = true;
3998        } else {
3999            setKeyguardOccludedLw(occluded, false /* force */);
4000        }
4001    }
4002
4003    private int handleStartTransitionForKeyguardLw(int transit, @Nullable Animation anim) {
4004        if (mKeyguardOccludedChanged) {
4005            if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded="
4006                    + mPendingKeyguardOccluded);
4007            mKeyguardOccludedChanged = false;
4008            if (setKeyguardOccludedLw(mPendingKeyguardOccluded, false /* force */)) {
4009                return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER;
4010            }
4011        }
4012        if (AppTransition.isKeyguardGoingAwayTransit(transit)) {
4013            if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation");
4014            final long startTime = anim != null
4015                    ? SystemClock.uptimeMillis() + anim.getStartOffset()
4016                    : SystemClock.uptimeMillis();
4017            final long duration = anim != null
4018                    ? anim.getDuration()
4019                    : 0;
4020            startKeyguardExitAnimation(startTime, duration);
4021        }
4022        return 0;
4023    }
4024
4025    private void launchAssistLongPressAction() {
4026        performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
4027        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
4028
4029        // launch the search activity
4030        Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
4031        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
4032        try {
4033            // TODO: This only stops the factory-installed search manager.
4034            // Need to formalize an API to handle others
4035            SearchManager searchManager = getSearchManager();
4036            if (searchManager != null) {
4037                searchManager.stopSearch();
4038            }
4039            startActivityAsUser(intent, UserHandle.CURRENT);
4040        } catch (ActivityNotFoundException e) {
4041            Slog.w(TAG, "No activity to handle assist long press action.", e);
4042        }
4043    }
4044
4045    private void launchAssistAction(String hint, int deviceId) {
4046        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
4047        if (!isUserSetupComplete()) {
4048            // Disable opening assist window during setup
4049            return;
4050        }
4051        Bundle args = null;
4052        if (deviceId > Integer.MIN_VALUE) {
4053            args = new Bundle();
4054            args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
4055        }
4056        if ((mContext.getResources().getConfiguration().uiMode
4057                & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
4058            // On TV, use legacy handling until assistants are implemented in the proper way.
4059            ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
4060                    .launchLegacyAssist(hint, UserHandle.myUserId(), args);
4061        } else {
4062            if (hint != null) {
4063                if (args == null) {
4064                    args = new Bundle();
4065                }
4066                args.putBoolean(hint, true);
4067            }
4068            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4069            if (statusbar != null) {
4070                statusbar.startAssist(args);
4071            }
4072        }
4073    }
4074
4075    private void startActivityAsUser(Intent intent, UserHandle handle) {
4076        if (isUserSetupComplete()) {
4077            mContext.startActivityAsUser(intent, handle);
4078        } else {
4079            Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent);
4080        }
4081    }
4082
4083    private SearchManager getSearchManager() {
4084        if (mSearchManager == null) {
4085            mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
4086        }
4087        return mSearchManager;
4088    }
4089
4090    private void preloadRecentApps() {
4091        mPreloadedRecentApps = true;
4092        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4093        if (statusbar != null) {
4094            statusbar.preloadRecentApps();
4095        }
4096    }
4097
4098    private void cancelPreloadRecentApps() {
4099        if (mPreloadedRecentApps) {
4100            mPreloadedRecentApps = false;
4101            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4102            if (statusbar != null) {
4103                statusbar.cancelPreloadRecentApps();
4104            }
4105        }
4106    }
4107
4108    private void toggleRecentApps() {
4109        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
4110        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4111        if (statusbar != null) {
4112            statusbar.toggleRecentApps();
4113        }
4114    }
4115
4116    @Override
4117    public void showRecentApps(boolean fromHome) {
4118        mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
4119        mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget();
4120    }
4121
4122    private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
4123        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
4124        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4125        if (statusbar != null) {
4126            statusbar.showRecentApps(triggeredFromAltTab, fromHome);
4127        }
4128    }
4129
4130    private void toggleKeyboardShortcutsMenu(int deviceId) {
4131        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4132        if (statusbar != null) {
4133            statusbar.toggleKeyboardShortcutsMenu(deviceId);
4134        }
4135    }
4136
4137    private void dismissKeyboardShortcutsMenu() {
4138        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4139        if (statusbar != null) {
4140            statusbar.dismissKeyboardShortcutsMenu();
4141        }
4142    }
4143
4144    private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
4145        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
4146        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4147        if (statusbar != null) {
4148            statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
4149        }
4150    }
4151
4152    void launchHomeFromHotKey() {
4153        launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/);
4154    }
4155
4156    /**
4157     * A home key -> launch home action was detected.  Take the appropriate action
4158     * given the situation with the keyguard.
4159     */
4160    void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) {
4161        if (respectKeyguard) {
4162            if (isKeyguardShowingAndNotOccluded()) {
4163                // don't launch home if keyguard showing
4164                return;
4165            }
4166
4167            if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) {
4168                // when in keyguard restricted mode, must first verify unlock
4169                // before launching home
4170                mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
4171                    @Override
4172                    public void onKeyguardExitResult(boolean success) {
4173                        if (success) {
4174                            try {
4175                                ActivityManager.getService().stopAppSwitches();
4176                            } catch (RemoteException e) {
4177                            }
4178                            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
4179                            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
4180                        }
4181                    }
4182                });
4183                return;
4184            }
4185        }
4186
4187        // no keyguard stuff to worry about, just launch home!
4188        try {
4189            ActivityManager.getService().stopAppSwitches();
4190        } catch (RemoteException e) {
4191        }
4192        if (mRecentsVisible) {
4193            // Hide Recents and notify it to launch Home
4194            if (awakenFromDreams) {
4195                awakenDreams();
4196            }
4197            hideRecentApps(false, true);
4198        } else {
4199            // Otherwise, just launch Home
4200            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
4201            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
4202        }
4203    }
4204
4205    private final Runnable mClearHideNavigationFlag = new Runnable() {
4206        @Override
4207        public void run() {
4208            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
4209                // Clear flags.
4210                mForceClearedSystemUiFlags &=
4211                        ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
4212            }
4213            mWindowManagerFuncs.reevaluateStatusBarVisibility();
4214        }
4215    };
4216
4217    /**
4218     * Input handler used while nav bar is hidden.  Captures any touch on the screen,
4219     * to determine when the nav bar should be shown and prevent applications from
4220     * receiving those touches.
4221     */
4222    final class HideNavInputEventReceiver extends InputEventReceiver {
4223        public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
4224            super(inputChannel, looper);
4225        }
4226
4227        @Override
4228        public void onInputEvent(InputEvent event, int displayId) {
4229            boolean handled = false;
4230            try {
4231                if (event instanceof MotionEvent
4232                        && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
4233                    final MotionEvent motionEvent = (MotionEvent)event;
4234                    if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
4235                        // When the user taps down, we re-show the nav bar.
4236                        boolean changed = false;
4237                        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
4238                            if (mInputConsumer == null) {
4239                                return;
4240                            }
4241                            // Any user activity always causes us to show the
4242                            // navigation controls, if they had been hidden.
4243                            // We also clear the low profile and only content
4244                            // flags so that tapping on the screen will atomically
4245                            // restore all currently hidden screen decorations.
4246                            int newVal = mResettingSystemUiFlags |
4247                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
4248                                    View.SYSTEM_UI_FLAG_LOW_PROFILE |
4249                                    View.SYSTEM_UI_FLAG_FULLSCREEN;
4250                            if (mResettingSystemUiFlags != newVal) {
4251                                mResettingSystemUiFlags = newVal;
4252                                changed = true;
4253                            }
4254                            // We don't allow the system's nav bar to be hidden
4255                            // again for 1 second, to prevent applications from
4256                            // spamming us and keeping it from being shown.
4257                            newVal = mForceClearedSystemUiFlags |
4258                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
4259                            if (mForceClearedSystemUiFlags != newVal) {
4260                                mForceClearedSystemUiFlags = newVal;
4261                                changed = true;
4262                                mHandler.postDelayed(mClearHideNavigationFlag, 1000);
4263                            }
4264                        }
4265                        if (changed) {
4266                            mWindowManagerFuncs.reevaluateStatusBarVisibility();
4267                        }
4268                    }
4269                }
4270            } finally {
4271                finishInputEvent(event, handled);
4272            }
4273        }
4274    }
4275
4276    @Override
4277    public void setRecentsVisibilityLw(boolean visible) {
4278        mRecentsVisible = visible;
4279    }
4280
4281    @Override
4282    public void setPipVisibilityLw(boolean visible) {
4283        mPictureInPictureVisible = visible;
4284    }
4285
4286    @Override
4287    public int adjustSystemUiVisibilityLw(int visibility) {
4288        mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4289        mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4290
4291        // Reset any bits in mForceClearingStatusBarVisibility that
4292        // are now clear.
4293        mResettingSystemUiFlags &= visibility;
4294        // Clear any bits in the new visibility that are currently being
4295        // force cleared, before reporting it.
4296        return visibility & ~mResettingSystemUiFlags
4297                & ~mForceClearedSystemUiFlags;
4298    }
4299
4300    @Override
4301    public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
4302            int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets,
4303            Rect outStableInsets, Rect outOutsets) {
4304        final int fl = PolicyControl.getWindowFlags(null, attrs);
4305        final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
4306        final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
4307
4308        final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
4309        if (useOutsets) {
4310            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
4311            if (outset > 0) {
4312                if (displayRotation == Surface.ROTATION_0) {
4313                    outOutsets.bottom += outset;
4314                } else if (displayRotation == Surface.ROTATION_90) {
4315                    outOutsets.right += outset;
4316                } else if (displayRotation == Surface.ROTATION_180) {
4317                    outOutsets.top += outset;
4318                } else if (displayRotation == Surface.ROTATION_270) {
4319                    outOutsets.left += outset;
4320                }
4321            }
4322        }
4323
4324        if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4325                == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4326            int availRight, availBottom;
4327            if (canHideNavigationBar() &&
4328                    (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
4329                availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4330                availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4331            } else {
4332                availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
4333                availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4334            }
4335            if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4336                if ((fl & FLAG_FULLSCREEN) != 0) {
4337                    outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop,
4338                            availRight - mStableFullscreenRight,
4339                            availBottom - mStableFullscreenBottom);
4340                } else {
4341                    outContentInsets.set(mStableLeft, mStableTop,
4342                            availRight - mStableRight, availBottom - mStableBottom);
4343                }
4344            } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
4345                outContentInsets.setEmpty();
4346            } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
4347                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
4348                outContentInsets.set(mCurLeft, mCurTop,
4349                        availRight - mCurRight, availBottom - mCurBottom);
4350            } else {
4351                outContentInsets.set(mCurLeft, mCurTop,
4352                        availRight - mCurRight, availBottom - mCurBottom);
4353            }
4354
4355            outStableInsets.set(mStableLeft, mStableTop,
4356                    availRight - mStableRight, availBottom - mStableBottom);
4357            if (taskBounds != null) {
4358                calculateRelevantTaskInsets(taskBounds, outContentInsets,
4359                        displayWidth, displayHeight);
4360                calculateRelevantTaskInsets(taskBounds, outStableInsets,
4361                        displayWidth, displayHeight);
4362            }
4363            return mForceShowSystemBars;
4364        }
4365        outContentInsets.setEmpty();
4366        outStableInsets.setEmpty();
4367        return mForceShowSystemBars;
4368    }
4369
4370    /**
4371     * For any given task bounds, the insets relevant for these bounds given the insets relevant
4372     * for the entire display.
4373     */
4374    private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth,
4375            int displayHeight) {
4376        mTmpRect.set(0, 0, displayWidth, displayHeight);
4377        mTmpRect.inset(inOutInsets);
4378        mTmpRect.intersect(taskBounds);
4379        int leftInset = mTmpRect.left - taskBounds.left;
4380        int topInset = mTmpRect.top - taskBounds.top;
4381        int rightInset = taskBounds.right - mTmpRect.right;
4382        int bottomInset = taskBounds.bottom - mTmpRect.bottom;
4383        inOutInsets.set(leftInset, topInset, rightInset, bottomInset);
4384    }
4385
4386    private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
4387        return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
4388                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
4389    }
4390
4391    /** {@inheritDoc} */
4392    @Override
4393    public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
4394                              int displayRotation, int uiMode) {
4395        mDisplayRotation = displayRotation;
4396        final int overscanLeft, overscanTop, overscanRight, overscanBottom;
4397        if (isDefaultDisplay) {
4398            switch (displayRotation) {
4399                case Surface.ROTATION_90:
4400                    overscanLeft = mOverscanTop;
4401                    overscanTop = mOverscanRight;
4402                    overscanRight = mOverscanBottom;
4403                    overscanBottom = mOverscanLeft;
4404                    break;
4405                case Surface.ROTATION_180:
4406                    overscanLeft = mOverscanRight;
4407                    overscanTop = mOverscanBottom;
4408                    overscanRight = mOverscanLeft;
4409                    overscanBottom = mOverscanTop;
4410                    break;
4411                case Surface.ROTATION_270:
4412                    overscanLeft = mOverscanBottom;
4413                    overscanTop = mOverscanLeft;
4414                    overscanRight = mOverscanTop;
4415                    overscanBottom = mOverscanRight;
4416                    break;
4417                default:
4418                    overscanLeft = mOverscanLeft;
4419                    overscanTop = mOverscanTop;
4420                    overscanRight = mOverscanRight;
4421                    overscanBottom = mOverscanBottom;
4422                    break;
4423            }
4424        } else {
4425            overscanLeft = 0;
4426            overscanTop = 0;
4427            overscanRight = 0;
4428            overscanBottom = 0;
4429        }
4430        mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0;
4431        mOverscanScreenTop = mRestrictedOverscanScreenTop = 0;
4432        mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth;
4433        mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight;
4434        mSystemLeft = 0;
4435        mSystemTop = 0;
4436        mSystemRight = displayWidth;
4437        mSystemBottom = displayHeight;
4438        mUnrestrictedScreenLeft = overscanLeft;
4439        mUnrestrictedScreenTop = overscanTop;
4440        mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight;
4441        mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom;
4442        mRestrictedScreenLeft = mUnrestrictedScreenLeft;
4443        mRestrictedScreenTop = mUnrestrictedScreenTop;
4444        mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth;
4445        mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight;
4446        mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft
4447                = mCurLeft = mUnrestrictedScreenLeft;
4448        mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop
4449                = mCurTop = mUnrestrictedScreenTop;
4450        mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight
4451                = mCurRight = displayWidth - overscanRight;
4452        mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom
4453                = mCurBottom = displayHeight - overscanBottom;
4454        mDockLayer = 0x10000000;
4455        mStatusBarLayer = -1;
4456
4457        // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
4458        final Rect pf = mTmpParentFrame;
4459        final Rect df = mTmpDisplayFrame;
4460        final Rect of = mTmpOverscanFrame;
4461        final Rect vf = mTmpVisibleFrame;
4462        final Rect dcf = mTmpDecorFrame;
4463        pf.left = df.left = of.left = vf.left = mDockLeft;
4464        pf.top = df.top = of.top = vf.top = mDockTop;
4465        pf.right = df.right = of.right = vf.right = mDockRight;
4466        pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom;
4467        dcf.setEmpty();  // Decor frame N/A for system bars.
4468
4469        if (isDefaultDisplay) {
4470            // For purposes of putting out fake window up to steal focus, we will
4471            // drive nav being hidden only by whether it is requested.
4472            final int sysui = mLastSystemUiFlags;
4473            boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
4474            boolean navTranslucent = (sysui
4475                    & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
4476            boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
4477            boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
4478            boolean navAllowedHidden = immersive || immersiveSticky;
4479            navTranslucent &= !immersiveSticky;  // transient trumps translucent
4480            boolean isKeyguardShowing = isStatusBarKeyguard() && !mKeyguardOccluded;
4481            if (!isKeyguardShowing) {
4482                navTranslucent &= areTranslucentBarsAllowed();
4483            }
4484            boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null
4485                    && mStatusBar.getAttrs().height == MATCH_PARENT
4486                    && mStatusBar.getAttrs().width == MATCH_PARENT;
4487
4488            // When the navigation bar isn't visible, we put up a fake
4489            // input window to catch all touch events.  This way we can
4490            // detect when the user presses anywhere to bring back the nav
4491            // bar and ensure the application doesn't see the event.
4492            if (navVisible || navAllowedHidden) {
4493                if (mInputConsumer != null) {
4494                    mHandler.sendMessage(
4495                            mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
4496                    mInputConsumer = null;
4497                }
4498            } else if (mInputConsumer == null) {
4499                mInputConsumer = mWindowManagerFuncs.createInputConsumer(mHandler.getLooper(),
4500                        INPUT_CONSUMER_NAVIGATION,
4501                        (channel, looper) -> new HideNavInputEventReceiver(channel, looper));
4502                // As long as mInputConsumer is active, hover events are not dispatched to the app
4503                // and the pointer icon is likely to become stale. Hide it to avoid confusion.
4504                InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL);
4505            }
4506
4507            // For purposes of positioning and showing the nav bar, if we have
4508            // decided that it can't be hidden (because of the screen aspect ratio),
4509            // then take that into account.
4510            navVisible |= !canHideNavigationBar();
4511
4512            boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight,
4513                    displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom, dcf, navVisible, navTranslucent,
4514                    navAllowedHidden, statusBarExpandedNotKeyguard);
4515            if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
4516                    mDockLeft, mDockTop, mDockRight, mDockBottom));
4517            updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing);
4518            if (updateSysUiVisibility) {
4519                updateSystemUiVisibilityLw();
4520            }
4521        }
4522    }
4523
4524    private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui,
4525            boolean isKeyguardShowing) {
4526        // decide where the status bar goes ahead of time
4527        if (mStatusBar != null) {
4528            // apply any navigation bar insets
4529            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4530            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4531            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4532            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
4533                    + mUnrestrictedScreenTop;
4534            vf.left = mStableLeft;
4535            vf.top = mStableTop;
4536            vf.right = mStableRight;
4537            vf.bottom = mStableBottom;
4538
4539            mStatusBarLayer = mStatusBar.getSurfaceLayer();
4540
4541            // Let the status bar determine its size.
4542            mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
4543                    vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
4544                    dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */);
4545
4546            // For layout, the status bar is always at the top with our fixed height.
4547            mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
4548
4549            boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
4550            boolean statusBarTranslucent = (sysui
4551                    & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
4552            if (!isKeyguardShowing) {
4553                statusBarTranslucent &= areTranslucentBarsAllowed();
4554            }
4555
4556            // If the status bar is hidden, we don't want to cause
4557            // windows behind it to scroll.
4558            if (mStatusBar.isVisibleLw() && !statusBarTransient) {
4559                // Status bar may go away, so the screen area it occupies
4560                // is available to apps but just covering them when the
4561                // status bar is visible.
4562                mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
4563
4564                mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4565                mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4566                mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4567                mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4568
4569                if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " +
4570                        String.format(
4571                                "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
4572                                mDockLeft, mDockTop, mDockRight, mDockBottom,
4573                                mContentLeft, mContentTop, mContentRight, mContentBottom,
4574                                mCurLeft, mCurTop, mCurRight, mCurBottom));
4575            }
4576            if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
4577                    && !statusBarTransient && !statusBarTranslucent
4578                    && !mStatusBarController.wasRecentlyTranslucent()) {
4579                // If the opaque status bar is currently requested to be visible,
4580                // and not in the process of animating on or off, then
4581                // we can tell the app that it is covered by it.
4582                mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
4583            }
4584            if (mStatusBarController.checkHiddenLw()) {
4585                return true;
4586            }
4587        }
4588        return false;
4589    }
4590
4591    private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation,
4592            int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf,
4593            boolean navVisible, boolean navTranslucent, boolean navAllowedHidden,
4594            boolean statusBarExpandedNotKeyguard) {
4595        if (mNavigationBar != null) {
4596            boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
4597            // Force the navigation bar to its appropriate place and
4598            // size.  We need to do this directly, instead of relying on
4599            // it to bubble up from the nav bar, because this needs to
4600            // change atomically with screen rotations.
4601            mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight,
4602                    displayRotation);
4603            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
4604                // It's a system nav bar or a portrait screen; nav bar goes on bottom.
4605                int top = displayHeight - overscanBottom
4606                        - getNavigationBarHeight(displayRotation, uiMode);
4607                mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
4608                mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
4609                if (transientNavBarShowing) {
4610                    mNavigationBarController.setBarShowingLw(true);
4611                } else if (navVisible) {
4612                    mNavigationBarController.setBarShowingLw(true);
4613                    mDockBottom = mTmpNavigationFrame.top;
4614                    mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
4615                    mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
4616                } else {
4617                    // We currently want to hide the navigation UI - unless we expanded the status
4618                    // bar.
4619                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4620                }
4621                if (navVisible && !navTranslucent && !navAllowedHidden
4622                        && !mNavigationBar.isAnimatingLw()
4623                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4624                    // If the opaque nav bar is currently requested to be visible,
4625                    // and not in the process of animating on or off, then
4626                    // we can tell the app that it is covered by it.
4627                    mSystemBottom = mTmpNavigationFrame.top;
4628                }
4629            } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4630                // Landscape screen; nav bar goes to the right.
4631                int left = displayWidth - overscanRight
4632                        - getNavigationBarWidth(displayRotation, uiMode);
4633                mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
4634                mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
4635                if (transientNavBarShowing) {
4636                    mNavigationBarController.setBarShowingLw(true);
4637                } else if (navVisible) {
4638                    mNavigationBarController.setBarShowingLw(true);
4639                    mDockRight = mTmpNavigationFrame.left;
4640                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4641                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4642                } else {
4643                    // We currently want to hide the navigation UI - unless we expanded the status
4644                    // bar.
4645                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4646                }
4647                if (navVisible && !navTranslucent && !navAllowedHidden
4648                        && !mNavigationBar.isAnimatingLw()
4649                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4650                    // If the nav bar is currently requested to be visible,
4651                    // and not in the process of animating on or off, then
4652                    // we can tell the app that it is covered by it.
4653                    mSystemRight = mTmpNavigationFrame.left;
4654                }
4655            } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4656                // Seascape screen; nav bar goes to the left.
4657                int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode);
4658                mTmpNavigationFrame.set(overscanLeft, 0, right, displayHeight);
4659                mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right;
4660                if (transientNavBarShowing) {
4661                    mNavigationBarController.setBarShowingLw(true);
4662                } else if (navVisible) {
4663                    mNavigationBarController.setBarShowingLw(true);
4664                    mDockLeft = mTmpNavigationFrame.right;
4665                    // TODO: not so sure about those:
4666                    mRestrictedScreenLeft = mRestrictedOverscanScreenLeft = mDockLeft;
4667                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4668                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4669                } else {
4670                    // We currently want to hide the navigation UI - unless we expanded the status
4671                    // bar.
4672                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4673                }
4674                if (navVisible && !navTranslucent && !navAllowedHidden
4675                        && !mNavigationBar.isAnimatingLw()
4676                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4677                    // If the nav bar is currently requested to be visible,
4678                    // and not in the process of animating on or off, then
4679                    // we can tell the app that it is covered by it.
4680                    mSystemLeft = mTmpNavigationFrame.right;
4681                }
4682            }
4683            // Make sure the content and current rectangles are updated to
4684            // account for the restrictions from the navigation bar.
4685            mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4686            mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4687            mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4688            mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4689            mStatusBarLayer = mNavigationBar.getSurfaceLayer();
4690            // And compute the final frame.
4691            mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
4692                    mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
4693                    mTmpNavigationFrame, mTmpNavigationFrame);
4694            if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
4695            if (mNavigationBarController.checkHiddenLw()) {
4696                return true;
4697            }
4698        }
4699        return false;
4700    }
4701
4702    private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
4703        if (mNavigationBarCanMove && displayWidth > displayHeight) {
4704            if (displayRotation == Surface.ROTATION_270) {
4705                return NAV_BAR_LEFT;
4706            } else {
4707                return NAV_BAR_RIGHT;
4708            }
4709        }
4710        return NAV_BAR_BOTTOM;
4711    }
4712
4713    /** {@inheritDoc} */
4714    @Override
4715    public int getSystemDecorLayerLw() {
4716        if (mStatusBar != null && mStatusBar.isVisibleLw()) {
4717            return mStatusBar.getSurfaceLayer();
4718        }
4719
4720        if (mNavigationBar != null && mNavigationBar.isVisibleLw()) {
4721            return mNavigationBar.getSurfaceLayer();
4722        }
4723
4724        return 0;
4725    }
4726
4727    @Override
4728    public void getContentRectLw(Rect r) {
4729        r.set(mContentLeft, mContentTop, mContentRight, mContentBottom);
4730    }
4731
4732    void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
4733            boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
4734        if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
4735            // Here's a special case: if this attached window is a panel that is
4736            // above the dock window, and the window it is attached to is below
4737            // the dock window, then the frames we computed for the window it is
4738            // attached to can not be used because the dock is effectively part
4739            // of the underlying window and the attached window is floating on top
4740            // of the whole thing.  So, we ignore the attached window and explicitly
4741            // compute the frames that would be appropriate without the dock.
4742            df.left = of.left = cf.left = vf.left = mDockLeft;
4743            df.top = of.top = cf.top = vf.top = mDockTop;
4744            df.right = of.right = cf.right = vf.right = mDockRight;
4745            df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom;
4746        } else {
4747            // The effective display frame of the attached window depends on
4748            // whether it is taking care of insetting its content.  If not,
4749            // we need to use the parent's content frame so that the entire
4750            // window is positioned within that content.  Otherwise we can use
4751            // the overscan frame and let the attached window take care of
4752            // positioning its content appropriately.
4753            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4754                // Set the content frame of the attached window to the parent's decor frame
4755                // (same as content frame when IME isn't present) if specifically requested by
4756                // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
4757                // Otherwise, use the overscan frame.
4758                cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
4759                        ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
4760            } else {
4761                // If the window is resizing, then we want to base the content
4762                // frame on our attached content frame to resize...  however,
4763                // things can be tricky if the attached window is NOT in resize
4764                // mode, in which case its content frame will be larger.
4765                // Ungh.  So to deal with that, make sure the content frame
4766                // we end up using is not covering the IM dock.
4767                cf.set(attached.getContentFrameLw());
4768                if (attached.isVoiceInteraction()) {
4769                    if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft;
4770                    if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop;
4771                    if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight;
4772                    if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom;
4773                } else if (attached.getSurfaceLayer() < mDockLayer) {
4774                    if (cf.left < mContentLeft) cf.left = mContentLeft;
4775                    if (cf.top < mContentTop) cf.top = mContentTop;
4776                    if (cf.right > mContentRight) cf.right = mContentRight;
4777                    if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
4778                }
4779            }
4780            df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
4781            of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
4782            vf.set(attached.getVisibleFrameLw());
4783        }
4784        // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
4785        // window should be positioned relative to its parent or the entire
4786        // screen.
4787        pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
4788                ? attached.getFrameLw() : df);
4789    }
4790
4791    private void applyStableConstraints(int sysui, int fl, Rect r) {
4792        if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4793            // If app is requesting a stable layout, don't let the
4794            // content insets go below the stable values.
4795            if ((fl & FLAG_FULLSCREEN) != 0) {
4796                if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft;
4797                if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop;
4798                if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight;
4799                if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom;
4800            } else {
4801                if (r.left < mStableLeft) r.left = mStableLeft;
4802                if (r.top < mStableTop) r.top = mStableTop;
4803                if (r.right > mStableRight) r.right = mStableRight;
4804                if (r.bottom > mStableBottom) r.bottom = mStableBottom;
4805            }
4806        }
4807    }
4808
4809    private boolean canReceiveInput(WindowState win) {
4810        boolean notFocusable =
4811                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
4812        boolean altFocusableIm =
4813                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
4814        boolean notFocusableForIm = notFocusable ^ altFocusableIm;
4815        return !notFocusableForIm;
4816    }
4817
4818    /** {@inheritDoc} */
4819    @Override
4820    public void layoutWindowLw(WindowState win, WindowState attached) {
4821        // We've already done the navigation bar and status bar. If the status bar can receive
4822        // input, we need to layout it again to accomodate for the IME window.
4823        if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) {
4824            return;
4825        }
4826        final WindowManager.LayoutParams attrs = win.getAttrs();
4827        final boolean isDefaultDisplay = win.isDefaultDisplay();
4828        final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
4829                (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
4830        if (needsToOffsetInputMethodTarget) {
4831            if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
4832            offsetInputMethodWindowLw(mLastInputMethodWindow);
4833        }
4834
4835        final int fl = PolicyControl.getWindowFlags(win, attrs);
4836        final int pfl = attrs.privateFlags;
4837        final int sim = attrs.softInputMode;
4838        final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
4839
4840        final Rect pf = mTmpParentFrame;
4841        final Rect df = mTmpDisplayFrame;
4842        final Rect of = mTmpOverscanFrame;
4843        final Rect cf = mTmpContentFrame;
4844        final Rect vf = mTmpVisibleFrame;
4845        final Rect dcf = mTmpDecorFrame;
4846        final Rect sf = mTmpStableFrame;
4847        Rect osf = null;
4848        dcf.setEmpty();
4849
4850        final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
4851                && mNavigationBar != null && mNavigationBar.isVisibleLw());
4852
4853        final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
4854
4855        if (isDefaultDisplay) {
4856            sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom);
4857        } else {
4858            sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom);
4859        }
4860
4861        if (!isDefaultDisplay) {
4862            if (attached != null) {
4863                // If this window is attached to another, our display
4864                // frame is the same as the one we are attached to.
4865                setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4866            } else {
4867                // Give the window full screen.
4868                pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4869                pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4870                pf.right = df.right = of.right = cf.right
4871                        = mOverscanScreenLeft + mOverscanScreenWidth;
4872                pf.bottom = df.bottom = of.bottom = cf.bottom
4873                        = mOverscanScreenTop + mOverscanScreenHeight;
4874            }
4875        } else if (attrs.type == TYPE_INPUT_METHOD) {
4876            pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
4877            pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
4878            pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
4879            // IM dock windows layout below the nav bar...
4880            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4881            // ...with content insets above the nav bar
4882            cf.bottom = vf.bottom = mStableBottom;
4883            if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
4884                // The status bar forces the navigation bar while it's visible. Make sure the IME
4885                // avoids the navigation bar in that case.
4886                if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4887                    pf.right = df.right = of.right = cf.right = vf.right = mStableRight;
4888                } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4889                    pf.left = df.left = of.left = cf.left = vf.left = mStableLeft;
4890                }
4891            }
4892            // IM dock windows always go to the bottom of the screen.
4893            attrs.gravity = Gravity.BOTTOM;
4894            mDockLayer = win.getSurfaceLayer();
4895        } else if (attrs.type == TYPE_VOICE_INTERACTION) {
4896            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4897            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4898            pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4899            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4900            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4901                cf.left = mDockLeft;
4902                cf.top = mDockTop;
4903                cf.right = mDockRight;
4904                cf.bottom = mDockBottom;
4905            } else {
4906                cf.left = mContentLeft;
4907                cf.top = mContentTop;
4908                cf.right = mContentRight;
4909                cf.bottom = mContentBottom;
4910            }
4911            if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4912                vf.left = mCurLeft;
4913                vf.top = mCurTop;
4914                vf.right = mCurRight;
4915                vf.bottom = mCurBottom;
4916            } else {
4917                vf.set(cf);
4918            }
4919        } else if (attrs.type == TYPE_WALLPAPER) {
4920           layoutWallpaper(win, pf, df, of, cf);
4921        } else if (win == mStatusBar) {
4922            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4923            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4924            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4925            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop;
4926