/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.policy;

import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW;
import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
import static android.Manifest.permission.SYSTEM_APPLICATION_OVERLAY;
import static android.app.AppOpsManager.OP_CREATE_ACCESSIBILITY_OVERLAY;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
import static android.app.AppOpsManager.OP_TOAST_WINDOW;
import static android.content.PermissionChecker.PID_UNKNOWN;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE;
import static android.content.pm.PackageManager.FEATURE_HDMI_CEC;
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
import static android.content.pm.PackageManager.FEATURE_WATCH;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Build.VERSION_CODES.M;
import static android.os.Build.VERSION_CODES.O;
import static android.os.IInputConstants.INVALID_INPUT_DEVICE_ID;
import static android.provider.Settings.Secure.VOLUME_HUSH_OFF;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.Display.STATE_OFF;
import static android.view.KeyEvent.KEYCODE_BACK;
import static android.view.KeyEvent.KEYCODE_DPAD_CENTER;
import static android.view.KeyEvent.KEYCODE_DPAD_DOWN;
import static android.view.KeyEvent.KEYCODE_HOME;
import static android.view.KeyEvent.KEYCODE_POWER;
import static android.view.KeyEvent.KEYCODE_STEM_PRIMARY;
import static android.view.KeyEvent.KEYCODE_UNKNOWN;
import static android.view.KeyEvent.KEYCODE_VOLUME_DOWN;
import static android.view.KeyEvent.KEYCODE_VOLUME_UP;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_SYSTEM_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD;
import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_OTHER;
import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
import static android.view.WindowManagerGlobal.ADD_OKAY;
import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED;
import static android.view.contentprotection.flags.Flags.createAccessibilityOverlayAppOpEnabled;

import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_BEHAVIOR_LOCK;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_BEHAVIOR_NONE;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_BEHAVIOR_SLEEP;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
import static com.android.server.wm.WindowManagerPolicyProto.KEYGUARD_DELEGATE;
import static com.android.server.wm.WindowManagerPolicyProto.KEYGUARD_DRAW_COMPLETE;
import static com.android.server.wm.WindowManagerPolicyProto.KEYGUARD_OCCLUDED;
import static com.android.server.wm.WindowManagerPolicyProto.KEYGUARD_OCCLUDED_CHANGED;
import static com.android.server.wm.WindowManagerPolicyProto.KEYGUARD_OCCLUDED_PENDING;
import static com.android.server.wm.WindowManagerPolicyProto.ORIENTATION;
import static com.android.server.wm.WindowManagerPolicyProto.ROTATION;
import static com.android.server.wm.WindowManagerPolicyProto.ROTATION_MODE;
import static com.android.server.wm.WindowManagerPolicyProto.SCREEN_ON_FULLY;
import static com.android.server.wm.WindowManagerPolicyProto.WINDOW_MANAGER_DRAW_COMPLETE;

import android.accessibilityservice.AccessibilityService;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.ActivityManager.RecentTaskInfo;
import android.app.ActivityManagerInternal;
import android.app.ActivityTaskManager;
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.IUiModeManager;
import android.app.NotificationManager;
import android.app.ProgressDialog;
import android.app.SearchManager;
import android.app.UiModeManager;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.PermissionChecker;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.Rect;
import android.hardware.SensorPrivacyManager;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.hdmi.HdmiAudioSystemClient;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPlaybackClient;
import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback;
import android.hardware.input.InputManager;
import android.media.AudioManager;
import android.media.AudioManagerInternal;
import android.media.AudioSystem;
import android.media.IAudioService;
import android.media.session.MediaSessionLegacyHelper;
import android.os.Binder;
import android.os.Bundle;
import android.os.DeviceIdleManager;
import android.os.FactoryTest;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeReason;
import android.os.PowerManagerInternal;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StrictMode;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UEventObserver;
import android.os.UserHandle;
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.DeviceConfig;
import android.provider.MediaStore;
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.service.dreams.DreamManagerInternal;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
import android.service.vr.IPersistentVrStateCallbacks;
import android.speech.RecognizerIntent;
import android.telecom.TelecomManager;
import android.util.FeatureFlagUtils;
import android.util.Log;
import android.util.MathUtils;
import android.util.MutableBoolean;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
import android.view.HapticFeedbackConstants;
import android.view.IDisplayFoldListener;
import android.view.InputDevice;
import android.view.KeyCharacterMap;
import android.view.KeyCharacterMap.FallbackAction;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerPolicyConstants;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.autofill.AutofillManagerInternal;
import android.widget.Toast;

import com.android.internal.R;
import com.android.internal.accessibility.AccessibilityShortcutController;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.AssistUtils;
import com.android.internal.display.BrightnessUtils;
import com.android.internal.inputmethod.SoftInputShowHideReason;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.os.RoSystemProperties;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
import com.android.internal.policy.KeyInterceptionInfo;
import com.android.internal.policy.LogDecelerateInterpolator;
import com.android.internal.policy.PhoneWindow;
import com.android.internal.policy.TransitionAnimation;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.AccessibilityManagerInternal;
import com.android.server.ExtconStateObserver;
import com.android.server.ExtconUEventObserver;
import com.android.server.GestureLauncherService;
import com.android.server.LocalServices;
import com.android.server.SystemServiceManager;
import com.android.server.UiThread;
import com.android.server.input.InputManagerInternal;
import com.android.server.input.KeyboardMetricsCollector;
import com.android.server.input.KeyboardMetricsCollector.KeyboardLogEvent;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.pm.UserManagerInternal;
import com.android.server.policy.KeyCombinationManager.TwoKeysCombinationRule;
import com.android.server.policy.keyguard.KeyguardServiceDelegate;
import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener;
import com.android.server.policy.keyguard.KeyguardStateMonitor.StateCallback;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.vibrator.HapticFeedbackVibrationProvider;
import com.android.server.vr.VrManagerInternal;
import com.android.server.wallpaper.WallpaperManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.DisplayPolicy;
import com.android.server.wm.DisplayRotation;
import com.android.server.wm.WindowManagerInternal;
import com.android.server.wm.WindowManagerInternal.AppTransitionListener;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Supplier;

/**
 * WindowManagerPolicy implementation for the Android phone UI.  This
 * introduces a new method suffix, Lp, for an internal lock of the
 * PhoneWindowManager.  This is used to protect some internal state, and
 * can be acquired with either the Lw and Li lock held, so has the restrictions
 * of both of those when held.
 */
public class PhoneWindowManager implements WindowManagerPolicy {
    static final String TAG = "WindowManager";
    static final boolean localLOGV = false;
    static final boolean DEBUG_INPUT = false;
    static final boolean DEBUG_KEYGUARD = false;
    static final boolean DEBUG_WAKEUP = false;

    // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
    // No longer recommended for desk docks;
    static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;

    // Whether to allow devices placed in vr headset viewers to have an alternative Home intent.
    static final boolean ENABLE_VR_HEADSET_HOME_CAPTURE = true;

    // --------- Key behavior definitions below. ---------
    // NOTE: When updating the valid range of any of these behaviors, and if that behavior has a
    // Settings key associated to it for dynamic update, update its valid Settings value range in
    // android.provider.settings.validators.GlobalSettingsValidators.

    // must match: config_shortPressOnPowerBehavior in config.xml
    // The config value can be overridden using Settings.Global.POWER_BUTTON_SHORT_PRESS
    static final int SHORT_PRESS_POWER_NOTHING = 0;
    static final int SHORT_PRESS_POWER_GO_TO_SLEEP = 1;
    static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2;
    static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3;
    static final int SHORT_PRESS_POWER_GO_HOME = 4;
    static final int SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME = 5;
    static final int SHORT_PRESS_POWER_LOCK_OR_SLEEP = 6;
    static final int SHORT_PRESS_POWER_DREAM_OR_SLEEP = 7;

    // must match: config_LongPressOnPowerBehavior in config.xml
    // The config value can be overridden using Settings.Global.POWER_BUTTON_LONG_PRESS
    static final int LONG_PRESS_POWER_NOTHING = 0;
    static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
    static final int LONG_PRESS_POWER_SHUT_OFF = 2;
    static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
    static final int LONG_PRESS_POWER_GO_TO_VOICE_ASSIST = 4;
    static final int LONG_PRESS_POWER_ASSISTANT = 5; // Settings.Secure.ASSISTANT

    // must match: config_veryLongPresOnPowerBehavior in config.xml
    // The config value can be overridden using Settings.Global.POWER_BUTTON_VERY_LONG_PRESS
    static final int VERY_LONG_PRESS_POWER_NOTHING = 0;
    static final int VERY_LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;

    // must match: config_keyChordPowerVolumeUp in config.xml
    static final int POWER_VOLUME_UP_BEHAVIOR_NOTHING = 0;
    static final int POWER_VOLUME_UP_BEHAVIOR_MUTE = 1;
    static final int POWER_VOLUME_UP_BEHAVIOR_GLOBAL_ACTIONS = 2;

    // must match: config_doublePressOnPowerBehavior in config.xml
    // The config value can be overridden using Settings.Global.POWER_BUTTON_DOUBLE_PRESS and/or
    // Settings.Global.POWER_BUTTON_TRIPLE_PRESS
    static final int MULTI_PRESS_POWER_NOTHING = 0;
    static final int MULTI_PRESS_POWER_THEATER_MODE = 1;
    static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2;
    static final int MULTI_PRESS_POWER_LAUNCH_TARGET_ACTIVITY = 3;

    // must match: config_longPressOnBackBehavior in config.xml
    static final int LONG_PRESS_BACK_NOTHING = 0;
    static final int LONG_PRESS_BACK_GO_TO_VOICE_ASSIST = 1;

    // must match: config_longPressOnHomeBehavior in config.xml
    static final int LONG_PRESS_HOME_NOTHING = 0;
    static final int LONG_PRESS_HOME_ALL_APPS = 1;
    static final int LONG_PRESS_HOME_ASSIST = 2;
    static final int LONG_PRESS_HOME_NOTIFICATION_PANEL = 3;
    static final int LAST_LONG_PRESS_HOME_BEHAVIOR = LONG_PRESS_HOME_NOTIFICATION_PANEL;

    // must match: config_doubleTapOnHomeBehavior in config.xml
    static final int DOUBLE_TAP_HOME_NOTHING = 0;
    static final int DOUBLE_TAP_HOME_RECENT_SYSTEM_UI = 1;
    static final int DOUBLE_TAP_HOME_PIP_MENU = 2;

    static final int SHORT_PRESS_WINDOW_NOTHING = 0;
    static final int SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE = 1;

    static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP = 0;
    static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME = 1;

    // must match: config_shortPressOnSettingsBehavior in config.xml
    static final int SHORT_PRESS_SETTINGS_NOTHING = 0;
    static final int SHORT_PRESS_SETTINGS_NOTIFICATION_PANEL = 1;
    static final int LAST_SHORT_PRESS_SETTINGS_BEHAVIOR = SHORT_PRESS_SETTINGS_NOTIFICATION_PANEL;

    static final int PENDING_KEY_NULL = -1;

    // Must match: config_shortPressOnStemPrimaryBehavior in config.xml
    // The config value can be overridden using Settings.Global.STEM_PRIMARY_BUTTON_SHORT_PRESS
    static final int SHORT_PRESS_PRIMARY_NOTHING = 0;
    static final int SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS = 1;
    static final int SHORT_PRESS_PRIMARY_LAUNCH_TARGET_ACTIVITY = 2;

    // Must match: config_longPressOnStemPrimaryBehavior in config.xml
    // The config value can be overridden using Settings.Global.STEM_PRIMARY_BUTTON_LONG_PRESS
    static final int LONG_PRESS_PRIMARY_NOTHING = 0;
    static final int LONG_PRESS_PRIMARY_LAUNCH_VOICE_ASSISTANT = 1;

    // Must match: config_doublePressOnStemPrimaryBehavior in config.xml
    //The config value can be overridden using Settings.Global.STEM_PRIMARY_BUTTON_DOUBLE_PRESS
    static final int DOUBLE_PRESS_PRIMARY_NOTHING = 0;
    static final int DOUBLE_PRESS_PRIMARY_SWITCH_RECENT_APP = 1;

    // Must match: config_triplePressOnStemPrimaryBehavior in config.xml
    // The config value can be overridden using Settings.Global.STEM_PRIMARY_BUTTON_TRIPLE_PRESS
    static final int TRIPLE_PRESS_PRIMARY_NOTHING = 0;
    static final int TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY = 1;

    // Must match: config_searchKeyBehavior in config.xml
    static final int SEARCH_BEHAVIOR_DEFAULT_SEARCH = 0;
    static final int SEARCH_BEHAVIOR_TARGET_ACTIVITY = 1;

    static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
    static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
    static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
    static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
    static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";
    static public final String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot";
    static public final String SYSTEM_DIALOG_REASON_GESTURE_NAV = "gestureNav";

    public static final String TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD = "waitForAllWindowsDrawn";

    private static final int POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS = 800;

    /**
     * Keyguard stuff
     */
    private boolean mKeyguardDrawnOnce;

    /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
    static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;

    /**
      * Extra time for additional SystemUI animations.
      * <p>Since legacy apps can add Toast windows directly instead of using Toast APIs,
      * {@link DisplayPolicy} ensures that the window manager removes toast windows after
      * TOAST_WINDOW_TIMEOUT. We increase this timeout by TOAST_WINDOW_ANIM_BUFFER to account for
      * SystemUI's in/out toast animations, so that the toast text is still shown for a minimum
      * of 3.5 seconds and the animations are finished before window manager removes the window.
      */
    public static final int TOAST_WINDOW_ANIM_BUFFER = 600;

    /**
      * Amount of time (in milliseconds) a toast window can be shown before it's automatically
      * removed by window manager.
      */
    public static final int TOAST_WINDOW_TIMEOUT = 3500 + TOAST_WINDOW_ANIM_BUFFER;

    /**
     * Action for launching assistant in retail mode
     */
    private static final String ACTION_VOICE_ASSIST_RETAIL =
            "android.intent.action.VOICE_ASSIST_RETAIL";

    /**
     * Lock protecting internal state.  Must not call out into window
     * manager with lock held.  (This lock will be acquired in places
     * where the window manager is calling in with its own lock held.)
     */
    private final Object mLock = new Object();

    /** List of {@link ScreenOnListener}s which do not belong to the default display. */
    private final SparseArray<ScreenOnListener> mScreenOnListeners = new SparseArray<>();

    Context mContext;
    WindowManagerFuncs mWindowManagerFuncs;
    WindowManagerInternal mWindowManagerInternal;
    PowerManager mPowerManager;
    ActivityManagerInternal mActivityManagerInternal;
    IActivityManager mActivityManagerService;
    ActivityTaskManagerInternal mActivityTaskManagerInternal;
    AutofillManagerInternal mAutofillManagerInternal;
    InputManager mInputManager;
    InputManagerInternal mInputManagerInternal;
    DreamManagerInternal mDreamManagerInternal;
    PowerManagerInternal mPowerManagerInternal;
    IStatusBarService mStatusBarService;
    StatusBarManagerInternal mStatusBarManagerInternal;
    AudioManagerInternal mAudioManagerInternal;
    SensorPrivacyManager mSensorPrivacyManager;
    DisplayManager mDisplayManager;
    DisplayManagerInternal mDisplayManagerInternal;
    UserManagerInternal mUserManagerInternal;

    private WallpaperManagerInternal mWallpaperManagerInternal;

    boolean mPreloadedRecentApps;
    final Object mServiceAcquireLock = new Object();
    Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
    AccessibilityManager mAccessibilityManager;
    AccessibilityManagerInternal mAccessibilityManagerInternal;
    BurnInProtectionHelper mBurnInProtectionHelper;
    private DisplayFoldController mDisplayFoldController;
    AppOpsManager mAppOpsManager;
    PackageManager mPackageManager;
    SideFpsEventHandler mSideFpsEventHandler;
    LockPatternUtils mLockPatternUtils;
    private HapticFeedbackVibrationProvider mHapticFeedbackVibrationProvider;
    private boolean mHasFeatureAuto;
    private boolean mHasFeatureWatch;
    private boolean mHasFeatureLeanback;
    private boolean mHasFeatureHdmiCec;

    // Assigned on main thread, accessed on UI thread
    volatile VrManagerInternal mVrManagerInternal;

    /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
    boolean mEnableShiftMenuBugReports = false;

    /** Controller that supports enabling an AccessibilityService by holding down the volume keys */
    private AccessibilityShortcutController mAccessibilityShortcutController;

    private TalkbackShortcutController mTalkbackShortcutController;

    boolean mSafeMode;

    // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
    // This is for car dock and this is updated from resource.
    private boolean mEnableCarDockHomeCapture = true;

    boolean mBootMessageNeedsHiding;
    volatile boolean mBootAnimationDismissable;
    private KeyguardServiceDelegate mKeyguardDelegate;
    private boolean mKeyguardBound;
    final DrawnListener mKeyguardDrawnCallback = new DrawnListener() {
        @Override
        public void onDrawn() {
            if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn.");
            mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
        }
    };

    private Supplier<GlobalActions> mGlobalActionsFactory;
    private GlobalActions mGlobalActions;
    private Handler mHandler;

    // FIXME This state is shared between the input reader and handler thread.
    // Technically it's broken and buggy but it has been like this for many years
    // and we have not yet seen any problems.  Someday we'll rewrite this logic
    // so that only one thread is involved in handling input policy.  Unfortunately
    // it's on a critical path for power management so we can't just post the work to the
    // handler thread.  We'll need to resolve this someday by teaching the input dispatcher
    // to hold wakelocks during dispatch and eliminating the critical path.
    volatile boolean mPowerKeyHandled;
    volatile boolean mBackKeyHandled;
    volatile boolean mEndCallKeyHandled;
    volatile boolean mCameraGestureTriggered;
    volatile boolean mCameraGestureTriggeredDuringGoingToSleep;

    /**
     * {@code true} if the device is entering a low-power state; {@code false otherwise}.
     *
     * <p>This differs from {@link #mRequestedOrSleepingDefaultDisplay} which tracks the power state
     * of the {@link #mDefaultDisplay default display} versus the power state of the entire device.
     */
    volatile boolean mDeviceGoingToSleep;

    /**
     * {@code true} if the {@link #mDefaultDisplay default display} is entering or was requested to
     * enter a low-power state; {@code false otherwise}.
     *
     * <p>This differs from {@link #mDeviceGoingToSleep} which tracks the power state of the entire
     * device versus the power state of the {@link #mDefaultDisplay default display}.
     */
    // TODO(b/178103325): Track sleep/requested sleep for every display.
    volatile boolean mRequestedOrSleepingDefaultDisplay;

    volatile boolean mRecentsVisible;
    volatile boolean mNavBarVirtualKeyHapticFeedbackEnabled = true;
    volatile boolean mPictureInPictureVisible;
    volatile private boolean mDismissImeOnBackKeyPressed;

    // Used to hold the last user key used to wake the device.  This helps us prevent up events
    // from being passed to the foregrounded app without a corresponding down event
    volatile int mPendingWakeKey = PENDING_KEY_NULL;

    int mRecentAppsHeldModifiers;

    int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT;
    boolean mHaveBuiltInKeyboard;

    boolean mSystemReady;
    boolean mSystemBooted;
    HdmiControl mHdmiControl;
    IUiModeManager mUiModeManager;
    int mUiMode;

    boolean mWakeGestureEnabledSetting;
    MyWakeGestureListener mWakeGestureListener;

    int mLidKeyboardAccessibility;
    int mLidNavigationAccessibility;
    int mShortPressOnPowerBehavior;
    private boolean mShouldEarlyShortPressOnPower;
    boolean mShouldEarlyShortPressOnStemPrimary;
    int mLongPressOnPowerBehavior;
    long mLongPressOnPowerAssistantTimeoutMs;
    int mVeryLongPressOnPowerBehavior;
    int mDoublePressOnPowerBehavior;
    ComponentName mPowerDoublePressTargetActivity;
    int mTriplePressOnPowerBehavior;
    int mLongPressOnBackBehavior;
    int mShortPressOnSleepBehavior;
    int mShortPressOnWindowBehavior;
    int mPowerVolUpBehavior;
    boolean mStylusButtonsEnabled = true;
    boolean mKidsModeEnabled;
    boolean mHasSoftInput = false;
    boolean mUseTvRouting;
    boolean mAllowStartActivityForLongPressOnPowerDuringSetup;
    MetricsLogger mLogger;
    boolean mWakeOnDpadKeyPress;
    boolean mWakeOnAssistKeyPress;
    boolean mWakeOnBackKeyPress;
    boolean mSilenceRingerOnSleepKey;
    long mWakeUpToLastStateTimeout;
    int mSearchKeyBehavior;
    ComponentName mSearchKeyTargetActivity;

    // Key Behavior - Stem Primary
    private int mShortPressOnStemPrimaryBehavior;
    private int mDoublePressOnStemPrimaryBehavior;
    private int mTriplePressOnStemPrimaryBehavior;
    private int mLongPressOnStemPrimaryBehavior;
    private RecentTaskInfo mBackgroundRecentTaskInfoOnStemPrimarySingleKeyUp;

    private boolean mHandleVolumeKeysInWM;

    private boolean mPendingKeyguardOccluded;
    private boolean mKeyguardOccludedChanged;

    private ActivityTaskManagerInternal.SleepTokenAcquirer mScreenOffSleepTokenAcquirer;
    Intent mHomeIntent;
    Intent mCarDockIntent;
    Intent mDeskDockIntent;
    Intent mVrHeadsetHomeIntent;
    boolean mPendingMetaAction;
    boolean mPendingCapsLockToggle;

    // support for activating the lock screen while the screen is on
    private HashSet<Integer> mAllowLockscreenWhenOnDisplays = new HashSet<>();
    int mLockScreenTimeout;
    boolean mLockScreenTimerActive;

    // Behavior of ENDCALL Button.  (See Settings.System.END_BUTTON_BEHAVIOR.)
    int mEndcallBehavior;

    // Behavior of POWER button while in-call and screen on.
    // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
    int mIncallPowerBehavior;

    // Behavior of Back button while in-call and screen on
    int mIncallBackBehavior;

    // Whether system navigation keys are enabled
    boolean mSystemNavigationKeysEnabled;

    // TODO(b/111361251): Remove default when the dependencies are multi-display ready.
    Display mDefaultDisplay;
    DisplayRotation mDefaultDisplayRotation;
    DisplayPolicy mDefaultDisplayPolicy;

    // What we do when the user long presses on home
    int mLongPressOnHomeBehavior;

    // What we do when the user double-taps on home
    int mDoubleTapOnHomeBehavior;

    // What we do when the user presses on settings
    int mShortPressOnSettingsBehavior;

    // Must match config_primaryShortPressTargetActivity in config.xml
    ComponentName mPrimaryShortPressTargetActivity;

    // Whether to lock the device after the next dreaming transition has finished.
    private boolean mLockAfterDreamingTransitionFinished;

    // Allowed theater mode wake actions
    private boolean mAllowTheaterModeWakeFromKey;
    private boolean mAllowTheaterModeWakeFromPowerKey;
    private boolean mAllowTheaterModeWakeFromMotion;
    private boolean mAllowTheaterModeWakeFromMotionWhenNotDreaming;
    private boolean mAllowTheaterModeWakeFromCameraLens;
    private boolean mAllowTheaterModeWakeFromLidSwitch;
    private boolean mAllowTheaterModeWakeFromWakeGesture;

    // If true, the power button long press behavior will be invoked even if the default display is
    // non-interactive. If false, the power button long press behavior will be skipped if the
    // default display is non-interactive.
    private boolean mSupportLongPressPowerWhenNonInteractive;

    // If true, the power button short press behavior will be always invoked as long as the default
    // display is on, even if the display is not interactive. If false, the power button short press
    // behavior will be skipped if the default display is non-interactive.
    private boolean mSupportShortPressPowerWhenDefaultDisplayOn;

    // Whether to go to sleep entering theater mode from power button
    private boolean mGoToSleepOnButtonPressTheaterMode;

    // Screenshot trigger states
    // Increase the chord delay when taking a screenshot from the keyguard
    private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f;

    // Ringer toggle should reuse timing and triggering from screenshot power and a11y vol up
    int mRingerToggleChord = VOLUME_HUSH_OFF;

    private static final long BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS = 1000;

    /* The number of steps between min and max brightness */
    private static final int BRIGHTNESS_STEPS = 10;

    SettingsObserver mSettingsObserver;
    ModifierShortcutManager mModifierShortcutManager;
    /** Currently fully consumed key codes per device */
    private final SparseArray<Set<Integer>> mConsumedKeysForDevice = new SparseArray<>();
    PowerManager.WakeLock mBroadcastWakeLock;
    PowerManager.WakeLock mPowerKeyWakeLock;
    boolean mHavePendingMediaKeyRepeatWithWakeLock;

    private int mCurrentUserId;

    // Maps global key codes to the components that will handle them.
    private GlobalKeyManager mGlobalKeyManager;

    // Fallback actions by key code.
    private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions =
            new SparseArray<KeyCharacterMap.FallbackAction>();

    private final com.android.internal.policy.LogDecelerateInterpolator mLogDecelerateInterpolator
            = new LogDecelerateInterpolator(100, 0);
    private final DeferredKeyActionExecutor mDeferredKeyActionExecutor =
            new DeferredKeyActionExecutor();

    private volatile int mTopFocusedDisplayId = INVALID_DISPLAY;

    private int mPowerButtonSuppressionDelayMillis = POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS;

    private KeyCombinationManager mKeyCombinationManager;
    private SingleKeyGestureDetector mSingleKeyGestureDetector;
    private GestureLauncherService mGestureLauncherService;
    private ButtonOverridePermissionChecker mButtonOverridePermissionChecker;

    private boolean mLockNowPending = false;

    // Timeout for showing the keyguard after the screen is on, in case no "ready" is received.
    private int mKeyguardDrawnTimeout = 1000;

    private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
    private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
    private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
    private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6;
    private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7;
    private static final int MSG_DISPATCH_SHOW_RECENTS = 9;
    private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10;
    private static final int MSG_HIDE_BOOT_MESSAGE = 11;
    private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12;
    private static final int MSG_SHOW_PICTURE_IN_PICTURE_MENU = 15;
    private static final int MSG_SCREENSHOT_CHORD = 16;
    private static final int MSG_ACCESSIBILITY_SHORTCUT = 17;
    private static final int MSG_BUGREPORT_TV = 18;
    private static final int MSG_ACCESSIBILITY_TV = 19;
    private static final int MSG_DISPATCH_BACK_KEY_TO_AUTOFILL = 20;
    private static final int MSG_SYSTEM_KEY_PRESS = 21;
    private static final int MSG_HANDLE_ALL_APPS = 22;
    private static final int MSG_LAUNCH_ASSIST = 23;
    private static final int MSG_RINGER_TOGGLE_CHORD = 24;
    private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 25;
    private static final int MSG_LOG_KEYBOARD_SYSTEM_EVENT = 26;
    private static final int MSG_SET_DEFERRED_KEY_ACTIONS_EXECUTABLE = 27;

    private class PolicyHandler extends Handler {

        private PolicyHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK:
                    dispatchMediaKeyWithWakeLock((KeyEvent)msg.obj);
                    break;
                case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK:
                    dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj);
                    break;
                case MSG_DISPATCH_SHOW_RECENTS:
                    showRecentApps(false);
                    break;
                case MSG_DISPATCH_SHOW_GLOBAL_ACTIONS:
                    showGlobalActionsInternal();
                    break;
                case MSG_KEYGUARD_DRAWN_COMPLETE:
                    if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete");
                    finishKeyguardDrawn();
                    break;
                case MSG_KEYGUARD_DRAWN_TIMEOUT:
                    Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete");
                    finishKeyguardDrawn();
                    break;
                case MSG_WINDOW_MANAGER_DRAWN_COMPLETE:
                    final int displayId = msg.arg1;
                    if (DEBUG_WAKEUP) Slog.w(TAG, "All windows drawn on display " + displayId);
                    Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER,
                            TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD, displayId /* cookie */);
                    finishWindowsDrawn(displayId);
                    break;
                case MSG_HIDE_BOOT_MESSAGE:
                    handleHideBootMessage();
                    break;
                case MSG_LAUNCH_ASSIST:
                    final int deviceId = msg.arg1;
                    final Long eventTime = (Long) msg.obj;
                    launchAssistAction(null /* hint */, deviceId, eventTime,
                            AssistUtils.INVOCATION_TYPE_ASSIST_BUTTON);
                    break;
                case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK:
                    launchVoiceAssistWithWakeLock();
                    break;
                case MSG_SHOW_PICTURE_IN_PICTURE_MENU:
                    showPictureInPictureMenuInternal();
                    break;
                case MSG_ACCESSIBILITY_SHORTCUT:
                    accessibilityShortcutActivated();
                    break;
                case MSG_BUGREPORT_TV:
                    requestBugreportForTv();
                    break;
                case MSG_ACCESSIBILITY_TV:
                    if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(false)) {
                        accessibilityShortcutActivated();
                    }
                    break;
                case MSG_DISPATCH_BACK_KEY_TO_AUTOFILL:
                    mAutofillManagerInternal.onBackKeyPressed();
                    break;
                case MSG_SYSTEM_KEY_PRESS:
                    KeyEvent event = (KeyEvent) msg.obj;
                    sendSystemKeyToStatusBar(event);
                    event.recycle();
                    break;
                case MSG_HANDLE_ALL_APPS:
                    launchAllAppsAction();
                    break;
                case MSG_RINGER_TOGGLE_CHORD:
                    handleRingerChordGesture();
                    break;
                case MSG_SCREENSHOT_CHORD:
                    handleScreenShot(msg.arg1);
                    break;
                case MSG_SWITCH_KEYBOARD_LAYOUT:
                    SwitchKeyboardLayoutMessageObject object =
                            (SwitchKeyboardLayoutMessageObject) msg.obj;
                    handleSwitchKeyboardLayout(object.keyEvent, object.direction,
                            object.focusedToken);
                    break;
                case MSG_LOG_KEYBOARD_SYSTEM_EVENT:
                    handleKeyboardSystemEvent(KeyboardLogEvent.from(msg.arg1), (KeyEvent) msg.obj);
                    break;
                case MSG_SET_DEFERRED_KEY_ACTIONS_EXECUTABLE:
                    final int keyCode = msg.arg1;
                    final long downTime = (Long) msg.obj;
                    mDeferredKeyActionExecutor.setActionsExecutable(keyCode, downTime);
                    break;
            }
        }
    }

    private UEventObserver mHDMIObserver = new UEventObserver() {
        @Override
        public void onUEvent(UEventObserver.UEvent event) {
            mDefaultDisplayPolicy.setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
        }
    };

    class SettingsObserver extends ContentObserver {
        SettingsObserver(Handler handler) {
            super(handler);
        }

        void observe() {
            // Observe all users' changes
            ContentResolver resolver = mContext.getContentResolver();
            resolver.registerContentObserver(Settings.System.getUriFor(
                    Settings.System.END_BUTTON_BEHAVIOR), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Secure.getUriFor(
                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Secure.getUriFor(
                    Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Secure.getUriFor(
                    Settings.Secure.WAKE_GESTURE_ENABLED), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.System.getUriFor(
                    Settings.System.SCREEN_OFF_TIMEOUT), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Secure.getUriFor(
                    Settings.Secure.DEFAULT_INPUT_METHOD), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Secure.getUriFor(
                    Settings.Secure.VOLUME_HUSH_GESTURE), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Secure.getUriFor(
                    Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Global.getUriFor(
                    Settings.Global.POWER_BUTTON_SHORT_PRESS), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Global.getUriFor(
                    Settings.Global.POWER_BUTTON_DOUBLE_PRESS), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Global.getUriFor(
                    Settings.Global.POWER_BUTTON_TRIPLE_PRESS), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Global.getUriFor(
                    Settings.Global.POWER_BUTTON_LONG_PRESS), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Global.getUriFor(
                    Settings.Global.POWER_BUTTON_LONG_PRESS_DURATION_MS), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Global.getUriFor(
                    Settings.Global.POWER_BUTTON_VERY_LONG_PRESS), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Global.getUriFor(
                    Settings.Global.STEM_PRIMARY_BUTTON_SHORT_PRESS), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Global.getUriFor(
                    Settings.Global.STEM_PRIMARY_BUTTON_DOUBLE_PRESS), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Global.getUriFor(
                    Settings.Global.STEM_PRIMARY_BUTTON_TRIPLE_PRESS), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Global.getUriFor(
                    Settings.Global.STEM_PRIMARY_BUTTON_LONG_PRESS), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Global.getUriFor(
                    Settings.Global.KEY_CHORD_POWER_VOLUME_UP), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Global.getUriFor(
                    Settings.Global.POWER_BUTTON_SUPPRESSION_DELAY_AFTER_GESTURE_WAKE), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Secure.getUriFor(
                    Settings.Secure.STYLUS_BUTTONS_ENABLED), false, this,
                    UserHandle.USER_ALL);
            resolver.registerContentObserver(Settings.Secure.getUriFor(
                    Settings.Secure.NAV_BAR_KIDS_MODE), false, this,
                    UserHandle.USER_ALL);
            updateSettings();
        }

        @Override public void onChange(boolean selfChange) {
            updateSettings();
        }
    }

    class MyWakeGestureListener extends WakeGestureListener {
        MyWakeGestureListener(Context context, Handler handler) {
            super(context, handler);
        }

        @Override
        public void onWakeUp() {
            synchronized (mLock) {
                if (shouldEnableWakeGestureLp()) {
                    performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, false,
                            "Wake Up");
                    wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture,
                            PowerManager.WAKE_REASON_GESTURE, "android.policy:GESTURE");
                }
            }
        }
    }

    private record SwitchKeyboardLayoutMessageObject(KeyEvent keyEvent, IBinder focusedToken,
                                                     int direction) {
    }

    final IPersistentVrStateCallbacks mPersistentVrModeListener =
            new IPersistentVrStateCallbacks.Stub() {
        @Override
        public void onPersistentVrStateChanged(boolean enabled) {
            mDefaultDisplayPolicy.setPersistentVrModeEnabled(enabled);
        }
    };

    private void handleRingerChordGesture() {
        if (mRingerToggleChord == VOLUME_HUSH_OFF) {
            return;
        }
        getAudioManagerInternal();
        mAudioManagerInternal.silenceRingerModeInternal("volume_hush");
        Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.HUSH_GESTURE_USED, 1);
        mLogger.action(MetricsProto.MetricsEvent.ACTION_HUSH_GESTURE, mRingerToggleChord);
    }

    IStatusBarService getStatusBarService() {
        synchronized (mServiceAcquireLock) {
            if (mStatusBarService == null) {
                mStatusBarService = IStatusBarService.Stub.asInterface(
                        ServiceManager.getService("statusbar"));
            }
            return mStatusBarService;
        }
    }

    StatusBarManagerInternal getStatusBarManagerInternal() {
        synchronized (mServiceAcquireLock) {
            if (mStatusBarManagerInternal == null) {
                mStatusBarManagerInternal =
                        LocalServices.getService(StatusBarManagerInternal.class);
            }
            return mStatusBarManagerInternal;
        }
    }

    AudioManagerInternal getAudioManagerInternal() {
        synchronized (mServiceAcquireLock) {
            if (mAudioManagerInternal == null) {
                mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
            }
            return mAudioManagerInternal;
        }
    }

    AccessibilityManagerInternal getAccessibilityManagerInternal() {
        synchronized (mServiceAcquireLock) {
            if (mAccessibilityManagerInternal == null) {
                mAccessibilityManagerInternal =
                        LocalServices.getService(AccessibilityManagerInternal.class);
            }
            return mAccessibilityManagerInternal;
        }
    }

    // returns true if the key was handled and should not be passed to the user
    private boolean backKeyPress() {
        mLogger.count("key_back_press", 1);
        // Cache handled state
        boolean handled = mBackKeyHandled;

        if (mHasFeatureWatch) {
            TelecomManager telecomManager = getTelecommService();

            if (telecomManager != null) {
                if (telecomManager.isRinging()) {
                    // Pressing back while there's a ringing incoming
                    // call should silence the ringer.
                    telecomManager.silenceRinger();

                    // It should not prevent navigating away
                    return false;
                } else if (
                    (mIncallBackBehavior & Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_HANGUP) != 0
                        && telecomManager.isInCall()) {
                    // Otherwise, if "Back button ends call" is enabled,
                    // the Back button will hang up any current active call.
                    return telecomManager.endCall();
                }
            }
        }

        if (mAutofillManagerInternal != null) {
            mHandler.sendMessage(mHandler.obtainMessage(MSG_DISPATCH_BACK_KEY_TO_AUTOFILL));
        }
        return handled;
    }

    private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
        // Hold a wake lock until the power key is released.
        if (!mPowerKeyWakeLock.isHeld()) {
            mPowerKeyWakeLock.acquire();
        }

        mWindowManagerFuncs.onPowerKeyDown(interactive);

        // Stop ringing or end call if configured to do so when power is pressed.
        TelecomManager telecomManager = getTelecommService();
        boolean hungUp = false;
        if (telecomManager != null) {
            if (telecomManager.isRinging()) {
                // Pressing Power while there's a ringing incoming
                // call should silence the ringer.
                telecomManager.silenceRinger();
            } else if ((mIncallPowerBehavior
                    & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
                    && telecomManager.isInCall() && interactive) {
                // Otherwise, if "Power button ends call" is enabled,
                // the Power button will hang up any current active call.
                hungUp = telecomManager.endCall();
            }
        }

        final boolean handledByPowerManager = mPowerManagerInternal.interceptPowerKeyDown(event);

        // Inform the StatusBar; but do not allow it to consume the event.
        sendSystemKeyToStatusBarAsync(event);

        // If the power key has still not yet been handled, then detect short
        // press, long press, or multi press and decide what to do.
        mPowerKeyHandled = mPowerKeyHandled || hungUp
                || handledByPowerManager || mKeyCombinationManager.isPowerKeyIntercepted();
        if (!mPowerKeyHandled) {
            if (!interactive) {
                wakeUpFromPowerKey(event.getDownTime());
            }
        } else {
            // handled by another power key policy.
            if (mSingleKeyGestureDetector.isKeyIntercepted(KEYCODE_POWER)) {
                Slog.d(TAG, "Skip power key gesture for other policy has handled it.");
                mSingleKeyGestureDetector.reset();
            }
        }
    }

    private void interceptPowerKeyUp(KeyEvent event, boolean canceled) {
        // Inform the StatusBar; but do not allow it to consume the event.
        sendSystemKeyToStatusBarAsync(event);

        final boolean handled = canceled || mPowerKeyHandled;

        if (!handled) {
            if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) == 0) {
                // Abort possibly stuck animations only when power key up without long press case.
                mHandler.post(mWindowManagerFuncs::triggerAnimationFailsafe);
            }
        }

        finishPowerKeyPress();
    }

    private void finishPowerKeyPress() {
        mPowerKeyHandled = false;
        if (mPowerKeyWakeLock.isHeld()) {
            mPowerKeyWakeLock.release();
        }
    }

    private void powerPress(long eventTime, int count, int displayId) {
        // SideFPS still needs to know about suppressed power buttons, in case it needs to block
        // an auth attempt.
        if (count == 1) {
            mSideFpsEventHandler.notifyPowerPressed();
        }
        if (mDefaultDisplayPolicy.isScreenOnEarly() && !mDefaultDisplayPolicy.isScreenOnFully()) {
            Slog.i(TAG, "Suppressed redundant power key press while "
                    + "already in the process of turning the screen on.");
            return;
        }

        final boolean interactive = mDefaultDisplayPolicy.isAwake();

        Slog.d(
                TAG,
                "powerPress: eventTime="
                        + eventTime
                        + " interactive="
                        + interactive
                        + " count="
                        + count
                        + " mShortPressOnPowerBehavior="
                        + mShortPressOnPowerBehavior);

        if (count == 2) {
            powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
        } else if (count == 3) {
            powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
        } else if (count > 3 && count <= getMaxMultiPressPowerCount()) {
            Slog.d(TAG, "No behavior defined for power press count " + count);
        } else if (count == 1 && shouldHandleShortPressPowerAction(interactive, eventTime)) {
            switch (mShortPressOnPowerBehavior) {
                case SHORT_PRESS_POWER_NOTHING:
                    break;
                case SHORT_PRESS_POWER_GO_TO_SLEEP:
                    sleepDefaultDisplayFromPowerButton(eventTime, 0);
                    break;
                case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
                    sleepDefaultDisplayFromPowerButton(eventTime,
                            PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
                    break;
                case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
                    if (sleepDefaultDisplayFromPowerButton(eventTime,
                            PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE)) {
                        launchHomeFromHotKey(DEFAULT_DISPLAY);
                    }
                    break;
                case SHORT_PRESS_POWER_GO_HOME:
                    shortPressPowerGoHome();
                    break;
                case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME: {
                    if (mDismissImeOnBackKeyPressed) {
                        // TODO(b/308479256): Check if hiding "all" IMEs is OK or not.
                        InputMethodManagerInternal.get().hideAllInputMethods(
                                SoftInputShowHideReason.HIDE_POWER_BUTTON_GO_HOME, displayId);
                    } else {
                        shortPressPowerGoHome();
                    }
                    break;
                }
                case SHORT_PRESS_POWER_LOCK_OR_SLEEP: {
                    if (mKeyguardDelegate == null || !mKeyguardDelegate.hasKeyguard()
                            || !mKeyguardDelegate.isSecure(mCurrentUserId) || keyguardOn()) {
                        sleepDefaultDisplayFromPowerButton(eventTime, 0);
                    } else {
                        lockNow(null /*options*/);
                    }
                    break;
                }
                case SHORT_PRESS_POWER_DREAM_OR_SLEEP: {
                    attemptToDreamFromShortPowerButtonPress(
                            true,
                            () -> sleepDefaultDisplayFromPowerButton(eventTime, 0));
                    break;
                }
            }
        }
    }

    private boolean shouldHandleShortPressPowerAction(boolean interactive, long eventTime) {
        if (mSupportShortPressPowerWhenDefaultDisplayOn) {
            final boolean defaultDisplayOn = Display.isOnState(mDefaultDisplay.getState());
            final boolean beganFromDefaultDisplayOn =
                    mSingleKeyGestureDetector.beganFromDefaultDisplayOn();
            if (!defaultDisplayOn || !beganFromDefaultDisplayOn) {
                Slog.v(
                        TAG,
                        "Ignoring short press of power button because the default display is not"
                                + " on. defaultDisplayOn="
                                + defaultDisplayOn
                                + ", beganFromDefaultDisplayOn="
                                + beganFromDefaultDisplayOn);
                return false;
            }
            return true;
        }
        final boolean beganFromNonInteractive = mSingleKeyGestureDetector.beganFromNonInteractive();
        if (!interactive || beganFromNonInteractive) {
            Slog.v(
                    TAG,
                    "Ignoring short press of power button because the device is not interactive."
                            + " interactive="
                            + interactive
                            + ", beganFromNonInteractive="
                            + beganFromNonInteractive);
            return false;
        }
        if (mSideFpsEventHandler.shouldConsumeSinglePress(eventTime)) {
            Slog.i(
                    TAG,
                    "Suppressing power key because the user is interacting with the "
                            + "fingerprint sensor");
            return false;
        }
        return true;
    }

    /**
     * Attempt to dream from a power button press.
     *
     * @param isScreenOn Whether the screen is currently on.
     * @param noDreamAction The action to perform if dreaming is not possible.
     */
    private void attemptToDreamFromShortPowerButtonPress(
            boolean isScreenOn, Runnable noDreamAction) {
        if (mShortPressOnPowerBehavior != SHORT_PRESS_POWER_DREAM_OR_SLEEP) {
            noDreamAction.run();
            return;
        }

        final DreamManagerInternal dreamManagerInternal = getDreamManagerInternal();
        if (dreamManagerInternal == null || !dreamManagerInternal.canStartDreaming(isScreenOn)) {
            Slog.d(TAG, "Can't start dreaming when attempting to dream from short power"
                    + " press (isScreenOn=" + isScreenOn + ")");
            noDreamAction.run();
            return;
        }

        synchronized (mLock) {
            // If the setting to lock instantly on power button press is true, then set the flag to
            // lock after the dream transition has finished.
            mLockAfterDreamingTransitionFinished =
                    mLockPatternUtils.getPowerButtonInstantlyLocks(mCurrentUserId);
        }

        dreamManagerInternal.requestDream();
    }

    /**
     * Sends the default display to sleep as a result of a power button press.
     *
     * @return {@code true} if the device was sent to sleep, {@code false} if the device did not
     * sleep.
     */
    private boolean sleepDefaultDisplayFromPowerButton(long eventTime, int flags) {
        // Before we actually go to sleep, we check the last wakeup reason.
        // If the device very recently woke up from a gesture (like user lifting their device)
        // then ignore the sleep instruction. This is because users have developed
        // a tendency to hit the power button immediately when they pick up their device, and we
        // don't want to put the device back to sleep in those cases.
        final PowerManager.WakeData lastWakeUp = mPowerManagerInternal.getLastWakeup();
        if (lastWakeUp != null && (lastWakeUp.wakeReason == PowerManager.WAKE_REASON_GESTURE
                || lastWakeUp.wakeReason == PowerManager.WAKE_REASON_LIFT
                || lastWakeUp.wakeReason == PowerManager.WAKE_REASON_BIOMETRIC)) {
            final long now = SystemClock.uptimeMillis();
            if (mPowerButtonSuppressionDelayMillis > 0
                    && (now < lastWakeUp.wakeTime + mPowerButtonSuppressionDelayMillis)) {
                Slog.i(TAG, "Sleep from power button suppressed. Time since gesture: "
                        + (now - lastWakeUp.wakeTime) + "ms");
                return false;
            }
        }

        sleepDefaultDisplay(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, flags);
        return true;
    }

    private void sleepDefaultDisplay(long eventTime, int reason, int flags) {
        mRequestedOrSleepingDefaultDisplay = true;
        mPowerManager.goToSleep(eventTime, reason, flags);
    }

    private void shortPressPowerGoHome() {
        launchHomeFromHotKey(DEFAULT_DISPLAY, true /* awakenFromDreams */,
                false /*respectKeyguard*/);
        if (isKeyguardShowingAndNotOccluded()) {
            // Notify keyguard so it can do any special handling for the power button since the
            // device will not power off and only launch home.
            mKeyguardDelegate.onShortPowerPressedGoHome();
        }
    }

    private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) {
        switch (behavior) {
            case MULTI_PRESS_POWER_NOTHING:
                break;
            case MULTI_PRESS_POWER_THEATER_MODE:
                if (!isUserSetupComplete()) {
                    Slog.i(TAG, "Ignoring toggling theater mode - device not setup.");
                    break;
                }

                if (isTheaterModeEnabled()) {
                    Slog.i(TAG, "Toggling theater mode off.");
                    Settings.Global.putInt(mContext.getContentResolver(),
                            Settings.Global.THEATER_MODE_ON, 0);
                    if (!interactive) {
                        wakeUpFromPowerKey(eventTime);
                    }
                } else {
                    Slog.i(TAG, "Toggling theater mode on.");
                    Settings.Global.putInt(mContext.getContentResolver(),
                            Settings.Global.THEATER_MODE_ON, 1);

                    if (mGoToSleepOnButtonPressTheaterMode && interactive) {
                        sleepDefaultDisplay(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
                                0);
                    }
                }
                break;
            case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
                Slog.i(TAG, "Starting brightness boost.");
                if (!interactive) {
                    wakeUpFromPowerKey(eventTime);
                }
                mPowerManager.boostScreenBrightness(eventTime);
                break;
            case MULTI_PRESS_POWER_LAUNCH_TARGET_ACTIVITY:
                launchTargetActivityOnMultiPressPower();
                break;
        }
    }

    private void launchTargetActivityOnMultiPressPower() {
        if (DEBUG_INPUT) {
            Slog.d(TAG, "Executing the double press power action.");
        }
        if (mPowerDoublePressTargetActivity != null) {
            Intent intent = new Intent();
            intent.setComponent(mPowerDoublePressTargetActivity);
            ResolveInfo resolveInfo = mContext.getPackageManager().resolveActivity(
                    intent, /* flags= */0);
            if (resolveInfo != null) {
                final boolean keyguardActive =
                        mKeyguardDelegate != null && mKeyguardDelegate.isShowing();
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
                if (!keyguardActive) {
                    startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
                } else {
                    mKeyguardDelegate.dismissKeyguardToLaunch(intent);
                }
            } else {
                Slog.e(TAG, "Could not resolve activity with : "
                        + mPowerDoublePressTargetActivity.flattenToString()
                        + " name.");
            }
        }
    }

    private int getLidBehavior() {
        return Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.LID_BEHAVIOR, LID_BEHAVIOR_NONE);
    }

    private int getMaxMultiPressPowerCount() {
        // The actual max power button press count is 5
        // (EMERGENCY_GESTURE_POWER_TAP_COUNT_THRESHOLD), which is coming from
        // GestureLauncherService.
        // To speed up the handling of single-press of power button inside SingleKeyGestureDetector,
        // however, we limit the max count to the number of button presses actually handled by the
        // SingleKeyGestureDetector except for wearable devices, where we want to de-dup the double
        // press gesture with the emergency gesture.
        if (mHasFeatureWatch
                && GestureLauncherService.isEmergencyGestureSettingEnabled(
                        mContext, ActivityManager.getCurrentUser())) {
            return 5;
        }
        if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
            return 3;
        }
        if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
            return 2;
        }
        return 1;
    }

    private void powerLongPress(long eventTime) {
        final int behavior = getResolvedLongPressOnPowerBehavior();
        Slog.d(TAG, "powerLongPress: eventTime=" + eventTime
                + " mLongPressOnPowerBehavior=" + mLongPressOnPowerBehavior);

        switch (behavior) {
            case LONG_PRESS_POWER_NOTHING:
                break;
            case LONG_PRESS_POWER_GLOBAL_ACTIONS:
                mPowerKeyHandled = true;
                performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false,
                        "Power - Long Press - Global Actions");
                showGlobalActions();
                break;
            case LONG_PRESS_POWER_SHUT_OFF:
            case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
                mPowerKeyHandled = true;
                // don't actually trigger the shutdown if we are running stability
                // tests via monkey
                if (ActivityManager.isUserAMonkey()) {
                    break;
                }
                performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false,
                        "Power - Long Press - Shut Off");
                sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
                mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
                break;
            case LONG_PRESS_POWER_GO_TO_VOICE_ASSIST:
                mPowerKeyHandled = true;
                performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false,
                        "Power - Long Press - Go To Voice Assist");
                // Some devices allow the voice assistant intent during setup (and use that intent
                // to launch something else, like Settings). So we explicitly allow that via the
                // config_allowStartActivityForLongPressOnPowerInSetup resource in config.xml.
                launchVoiceAssist(mAllowStartActivityForLongPressOnPowerDuringSetup);
                break;
            case LONG_PRESS_POWER_ASSISTANT:
                mPowerKeyHandled = true;
                performHapticFeedback(HapticFeedbackConstants.ASSISTANT_BUTTON, false,
                        "Power - Long Press - Go To Assistant");
                final int powerKeyDeviceId = INVALID_INPUT_DEVICE_ID;
                launchAssistAction(null, powerKeyDeviceId, eventTime,
                        AssistUtils.INVOCATION_TYPE_POWER_BUTTON_LONG_PRESS);
                break;
        }
    }

    private void powerVeryLongPress() {
        switch (mVeryLongPressOnPowerBehavior) {
            case VERY_LONG_PRESS_POWER_NOTHING:
                break;
            case VERY_LONG_PRESS_POWER_GLOBAL_ACTIONS:
                mPowerKeyHandled = true;
                performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false,
                        "Power - Very Long Press - Show Global Actions");
                showGlobalActions();
                break;
        }
    }

    private void backLongPress() {
        mBackKeyHandled = true;

        switch (mLongPressOnBackBehavior) {
            case LONG_PRESS_BACK_NOTHING:
                break;
            case LONG_PRESS_BACK_GO_TO_VOICE_ASSIST:
                launchVoiceAssist(false /* allowDuringSetup */);
                break;
        }
    }

    private void accessibilityShortcutActivated() {
        mAccessibilityShortcutController.performAccessibilityShortcut();
    }

    private void sleepPress() {
        if (mShortPressOnSleepBehavior == SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME) {
            launchHomeFromHotKey(DEFAULT_DISPLAY, false /* awakenDreams */,
                    true /*respectKeyguard*/);
        }
    }

    private void sleepRelease(long eventTime) {
        if (mSilenceRingerOnSleepKey) {
            TelecomManager telecomManager = getTelecommService();
            if (telecomManager != null && telecomManager.isRinging()) {
                telecomManager.silenceRinger();
                Slog.i(TAG, "sleepRelease() silence ringer");
                return;
            }
        }

        switch (mShortPressOnSleepBehavior) {
            case SHORT_PRESS_SLEEP_GO_TO_SLEEP:
            case SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME:
                Slog.i(TAG, "sleepRelease() calling goToSleep(GO_TO_SLEEP_REASON_SLEEP_BUTTON)");
                sleepDefaultDisplay(eventTime, PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON, 0);
                break;
        }
    }

    private int getResolvedLongPressOnPowerBehavior() {
        if (FactoryTest.isLongPressOnPowerOffEnabled()) {
            return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
        }

        // If the config indicates the assistant behavior but the device isn't yet provisioned, show
        // global actions instead.
        if (mLongPressOnPowerBehavior == LONG_PRESS_POWER_ASSISTANT && !isDeviceProvisioned()) {
            return LONG_PRESS_POWER_GLOBAL_ACTIONS;
        }

        // If long press to launch assistant is disabled in settings, do nothing.
        if (mLongPressOnPowerBehavior == LONG_PRESS_POWER_GO_TO_VOICE_ASSIST
                && !isLongPressToAssistantEnabled(mContext)) {
            return LONG_PRESS_POWER_NOTHING;
        }

        return mLongPressOnPowerBehavior;
    }

    private void stemPrimaryPress(int count) {
        if (DEBUG_INPUT) {
            Slog.d(TAG, "stemPrimaryPress: " + count);
        }
        if (count == 3) {
            stemPrimaryTriplePressAction(mTriplePressOnStemPrimaryBehavior);
        } else if (count == 2) {
            stemPrimaryDoublePressAction(mDoublePressOnStemPrimaryBehavior);
        } else if (count == 1) {
            stemPrimarySinglePressAction(mShortPressOnStemPrimaryBehavior);
        }
    }

    private void stemPrimarySinglePressAction(int behavior) {
        if (DEBUG_INPUT) {
            Slog.d(TAG, "stemPrimarySinglePressAction: behavior=" + behavior);
        }
        if (behavior == SHORT_PRESS_PRIMARY_NOTHING) return;

        final boolean keyguardActive = mKeyguardDelegate != null && mKeyguardDelegate.isShowing();
        if (keyguardActive) {
            // If keyguarded then notify the keyguard.
            mKeyguardDelegate.onSystemKeyPressed(KeyEvent.KEYCODE_STEM_PRIMARY);
            return;
        }
        switch (behavior) {
            case SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS:
                if (DEBUG_INPUT) {
                    Slog.d(TAG, "Executing stem primary short press action behavior.");
                }
                Intent allAppsIntent = new Intent(Intent.ACTION_ALL_APPS);
                allAppsIntent.addFlags(
                        Intent.FLAG_ACTIVITY_NEW_TASK
                                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
                startActivityAsUser(allAppsIntent, UserHandle.CURRENT_OR_SELF);
                break;
            case SHORT_PRESS_PRIMARY_LAUNCH_TARGET_ACTIVITY:
                if (DEBUG_INPUT) {
                    Slog.d(
                            TAG,
                            "Executing stem primary short press action behavior for launching "
                                    + "target activity.");
                }
                if (mPrimaryShortPressTargetActivity != null) {
                    Intent targetActivityIntent = new Intent();
                    targetActivityIntent.setComponent(mPrimaryShortPressTargetActivity);
                    ResolveInfo resolveInfo =
                            mContext.getPackageManager()
                                    .resolveActivity(targetActivityIntent, /* flags= */ 0);
                    if (resolveInfo != null) {
                        targetActivityIntent.addFlags(
                                Intent.FLAG_ACTIVITY_NEW_TASK
                                        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                                        | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
                        startActivityAsUser(targetActivityIntent, UserHandle.CURRENT_OR_SELF);
                    } else {
                        Slog.wtf(
                                TAG,
                                "Could not resolve activity with : "
                                        + mPrimaryShortPressTargetActivity.flattenToString()
                                        + " name.");
                    }
                } else {
                    Slog.wtf(
                            TAG,
                            "mPrimaryShortPressTargetActivity must not be null and correctly"
                                + " specified");
                }
                break;
        }
    }

    private void stemPrimaryDoublePressAction(int behavior) {
        switch (behavior) {
            case DOUBLE_PRESS_PRIMARY_NOTHING:
                break;
            case DOUBLE_PRESS_PRIMARY_SWITCH_RECENT_APP:
                if (DEBUG_INPUT) {
                    Slog.d(TAG, "Executing stem primary double press action behavior.");
                }
                final boolean keyguardActive = mKeyguardDelegate == null
                        ? false
                        : mKeyguardDelegate.isShowing();
                if (!keyguardActive) {
                    performStemPrimaryDoublePressSwitchToRecentTask();
                }
                break;
        }
    }

    private void stemPrimaryTriplePressAction(int behavior) {
        switch (behavior) {
            case TRIPLE_PRESS_PRIMARY_NOTHING:
                break;
            case TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY:
                if (DEBUG_INPUT) {
                    Slog.d(TAG, "Executing stem primary triple press action behavior.");
                }
                mTalkbackShortcutController.toggleTalkback(mCurrentUserId);
                if (mTalkbackShortcutController.isTalkBackShortcutGestureEnabled()) {
                    performHapticFeedback(HapticFeedbackConstants.CONFIRM, /* always = */
                            false, /* reason = */
                            "Stem primary - Triple Press - Toggle Accessibility");
                }
                break;
        }
    }

    private void stemPrimaryLongPress(long eventTime) {
        if (DEBUG_INPUT) {
            Slog.d(TAG, "Executing stem primary long press action behavior.");
        }

        switch (mLongPressOnStemPrimaryBehavior) {
            case LONG_PRESS_PRIMARY_NOTHING:
                break;
            case LONG_PRESS_PRIMARY_LAUNCH_VOICE_ASSISTANT:
                final int stemPrimaryKeyDeviceId = INVALID_INPUT_DEVICE_ID;
                launchAssistAction(
                        null,
                        stemPrimaryKeyDeviceId,
                        eventTime,
                        AssistUtils.INVOCATION_TYPE_UNKNOWN);
                break;
        }
    }

    /**
     * Load most recent task (expect current task) and bring it to the front.
     */
    void performStemPrimaryDoublePressSwitchToRecentTask() {
        RecentTaskInfo targetTask = mBackgroundRecentTaskInfoOnStemPrimarySingleKeyUp;
        if (targetTask == null) {
            if (DEBUG_INPUT) {
                Slog.w(TAG, "No recent task available! Show wallpaper.");
            }
            goHome();
            return;
        }

        if (DEBUG_INPUT) {
            Slog.d(
                    TAG,
                    "Starting task from recents. id="
                            + targetTask.id
                            + ", persistentId="
                            + targetTask.persistentId
                            + ", topActivity="
                            + targetTask.topActivity
                            + ", baseIntent="
                            + targetTask.baseIntent);
        }
        try {
            mActivityManagerService.startActivityFromRecents(targetTask.persistentId, null);
        } catch (RemoteException | IllegalArgumentException e) {
            Slog.e(TAG, "Failed to start task " + targetTask.persistentId + " from recents", e);
        }
    }

    private int getMaxMultiPressStemPrimaryCount() {
        switch (mTriplePressOnStemPrimaryBehavior) {
            case TRIPLE_PRESS_PRIMARY_NOTHING:
                break;
            case TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY:
                if (mTalkbackShortcutController.isTalkBackShortcutGestureEnabled()) {
                    return 3;
                }
                break;
        }
        if (mDoublePressOnStemPrimaryBehavior != DOUBLE_PRESS_PRIMARY_NOTHING) {
            return 2;
        }
        return 1;
    }

    private boolean hasLongPressOnPowerBehavior() {
        return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;
    }

    private boolean hasVeryLongPressOnPowerBehavior() {
        return mVeryLongPressOnPowerBehavior != VERY_LONG_PRESS_POWER_NOTHING;
    }

    private boolean hasLongPressOnBackBehavior() {
        return mLongPressOnBackBehavior != LONG_PRESS_BACK_NOTHING;
    }

    private boolean hasLongPressOnStemPrimaryBehavior() {
        return mLongPressOnStemPrimaryBehavior != LONG_PRESS_PRIMARY_NOTHING;
    }

    private boolean hasStemPrimaryBehavior() {
        return getMaxMultiPressStemPrimaryCount() > 1
                || hasLongPressOnStemPrimaryBehavior()
                || mShortPressOnStemPrimaryBehavior != SHORT_PRESS_PRIMARY_NOTHING;
    }

    private void interceptScreenshotChord(int source, long pressDelay) {
        mHandler.removeMessages(MSG_SCREENSHOT_CHORD);
        // arg2 is unused, but necessary to insure we call the correct method signature
        // since the screenshot source is read from message.arg1
        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SCREENSHOT_CHORD, source, 0),
                pressDelay);
    }

    private void interceptAccessibilityShortcutChord() {
        mHandler.removeMessages(MSG_ACCESSIBILITY_SHORTCUT);
        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_ACCESSIBILITY_SHORTCUT),
                getAccessibilityShortcutTimeout());
    }

    private void interceptRingerToggleChord() {
        mHandler.removeMessages(MSG_RINGER_TOGGLE_CHORD);
        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RINGER_TOGGLE_CHORD),
                getRingerToggleChordDelay());
    }

    private long getAccessibilityShortcutTimeout() {
        final ViewConfiguration config = ViewConfiguration.get(mContext);
        final boolean hasDialogShown = Settings.Secure.getIntForUser(mContext.getContentResolver(),
                Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0, mCurrentUserId) != 0;
        final boolean skipTimeoutRestriction =
                Settings.Secure.getIntForUser(mContext.getContentResolver(),
                        Settings.Secure.SKIP_ACCESSIBILITY_SHORTCUT_DIALOG_TIMEOUT_RESTRICTION, 0,
                        mCurrentUserId) != 0;

        // If users manually set the volume key shortcut for any accessibility service, the
        // system would bypass the timeout restriction of the shortcut dialog.
        return hasDialogShown || skipTimeoutRestriction
                ? config.getAccessibilityShortcutKeyTimeoutAfterConfirmation()
                : config.getAccessibilityShortcutKeyTimeout();
    }

    private long getScreenshotChordLongPressDelay() {
        long delayMs = DeviceConfig.getLong(
                DeviceConfig.NAMESPACE_SYSTEMUI, SCREENSHOT_KEYCHORD_DELAY,
                ViewConfiguration.get(mContext).getScreenshotChordKeyTimeout());
        if (mKeyguardDelegate.isShowing()) {
            // Double the time it takes to take a screenshot from the keyguard
            return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER * delayMs);
        }
        return delayMs;
    }

    private long getRingerToggleChordDelay() {
        // Always timeout like a tap
        return ViewConfiguration.getTapTimeout();
    }

    private void cancelPendingScreenshotChordAction() {
        mHandler.removeMessages(MSG_SCREENSHOT_CHORD);
    }

    private void cancelPendingAccessibilityShortcutAction() {
        mHandler.removeMessages(MSG_ACCESSIBILITY_SHORTCUT);
    }

    private void cancelPendingRingerToggleChordAction() {
        mHandler.removeMessages(MSG_RINGER_TOGGLE_CHORD);
    }

    private final Runnable mEndCallLongPress = new Runnable() {
        @Override
        public void run() {
            mEndCallKeyHandled = true;
            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
                    "End Call - Long Press - Show Global Actions");
            showGlobalActionsInternal();
        }
    };

    private void handleScreenShot(@WindowManager.ScreenshotSource int source) {
        mDefaultDisplayPolicy.takeScreenshot(TAKE_SCREENSHOT_FULLSCREEN, source);
    }

    @Override
    public void showGlobalActions() {
        mHandler.removeMessages(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
        mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
    }

    void showGlobalActionsInternal() {
        if (mGlobalActions == null) {
            mGlobalActions = mGlobalActionsFactory.get();
        }
        final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();
        mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
        // since it took two seconds of long press to bring this up,
        // poke the wake lock so they have some time to see the dialog.
        mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
    }

    private void cancelGlobalActionsAction() {
        mHandler.removeMessages(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
    }

    boolean isDeviceProvisioned() {
        return Settings.Global.getInt(
                mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
    }

    @Override
    public boolean isUserSetupComplete() {
        boolean isSetupComplete = Settings.Secure.getIntForUser(mContext.getContentResolver(),
                Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
        if (mHasFeatureLeanback) {
            isSetupComplete &= isTvUserSetupComplete();
        } else if (mHasFeatureAuto) {
            isSetupComplete &= isAutoUserSetupComplete();
        }
        return isSetupComplete;
    }

    private boolean isAutoUserSetupComplete() {
        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
                "android.car.SETUP_WIZARD_IN_PROGRESS", 0, UserHandle.USER_CURRENT) == 0;
    }

    private boolean isTvUserSetupComplete() {
        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
                Settings.Secure.TV_USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
    }

    private void handleShortPressOnHome(KeyEvent event) {
        logKeyboardSystemsEvent(event, KeyboardLogEvent.HOME);

        // Turn on the connected TV and switch HDMI input if we're a HDMI playback device.
        final HdmiControl hdmiControl = getHdmiControl();
        if (hdmiControl != null) {
            hdmiControl.turnOnTv();
        }

        // If there's a dream running then use home to escape the dream
        // but don't actually go home.
        final DreamManagerInternal dreamManagerInternal = getDreamManagerInternal();
        if (dreamManagerInternal != null && dreamManagerInternal.isDreaming()) {
            mDreamManagerInternal.stopDream(false /*immediate*/, "short press on home" /*reason*/);
            return;
        }

        // Go home!
        launchHomeFromHotKey(event.getDisplayId());
    }

    /**
     * Creates an accessor to HDMI control service that performs the operation of
     * turning on TV (optional) and switching input to us. If HDMI control service
     * is not available or we're not a HDMI playback device, the operation is no-op.
     * @return {@link HdmiControl} instance if available, null otherwise.
     */
    private HdmiControl getHdmiControl() {
        if (null == mHdmiControl) {
            if (!mHasFeatureHdmiCec) {
                return null;
            }
            HdmiControlManager manager = (HdmiControlManager) mContext.getSystemService(
                        Context.HDMI_CONTROL_SERVICE);
            HdmiPlaybackClient client = null;
            if (manager != null) {
                client = manager.getPlaybackClient();
            }
            mHdmiControl = new HdmiControl(client);
        }
        return mHdmiControl;
    }

    private static class HdmiControl {
        private final HdmiPlaybackClient mClient;

        private HdmiControl(HdmiPlaybackClient client) {
            mClient = client;
        }

        public void turnOnTv() {
            if (mClient == null) {
                return;
            }
            mClient.oneTouchPlay(new OneTouchPlayCallback() {
                @Override
                public void onComplete(int result) {
                    if (result != HdmiControlManager.RESULT_SUCCESS) {
                        Log.w(TAG, "One touch play failed: " + result);
                    }
                }
            });
        }
    }

    private void launchAllAppsAction() {
        Intent intent = new Intent(Intent.ACTION_ALL_APPS);
        if (mHasFeatureLeanback) {
            Intent intentLauncher = new Intent(Intent.ACTION_MAIN);
            intentLauncher.addCategory(Intent.CATEGORY_HOME);
            ResolveInfo resolveInfo = mPackageManager.resolveActivityAsUser(intentLauncher,
                    PackageManager.MATCH_SYSTEM_ONLY,
                    mCurrentUserId);
            if (resolveInfo != null) {
                intent.setPackage(resolveInfo.activityInfo.packageName);
            }
        }
        startActivityAsUser(intent, UserHandle.CURRENT);
    }

    private void launchAllAppsViaA11y() {
        AccessibilityManagerInternal accessibilityManager = getAccessibilityManagerInternal();
        if (accessibilityManager != null) {
            accessibilityManager.performSystemAction(
                    AccessibilityService.GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS);
        }
    }

    private void toggleNotificationPanel() {
        IStatusBarService statusBarService = getStatusBarService();
        if (isUserSetupComplete() && statusBarService != null) {
            try {
                statusBarService.togglePanel();
            } catch (RemoteException e) {
                // do nothing.
            }
        }
    }

    private void showSystemSettings() {
        startActivityAsUser(new Intent(android.provider.Settings.ACTION_SETTINGS),
                UserHandle.CURRENT_OR_SELF);
    }

    private void showPictureInPictureMenu(KeyEvent event) {
        if (DEBUG_INPUT) Log.d(TAG, "showPictureInPictureMenu event=" + event);
        mHandler.removeMessages(MSG_SHOW_PICTURE_IN_PICTURE_MENU);
        Message msg = mHandler.obtainMessage(MSG_SHOW_PICTURE_IN_PICTURE_MENU);
        msg.setAsynchronous(true);
        msg.sendToTarget();
    }

    private void showPictureInPictureMenuInternal() {
        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
        if (statusbar != null) {
            statusbar.showPictureInPictureMenu();
        }
    }

    /** A handler to handle home keys per display */
    private class DisplayHomeButtonHandler {

        private final int mDisplayId;
        private boolean mHomePressed;
        private boolean mHomeConsumed;
        private KeyEvent mPendingHomeKeyEvent;
        private final Runnable mHomeDoubleTapTimeoutRunnable = new Runnable() {
            @Override
            public void run() {
                if (mPendingHomeKeyEvent != null) {
                    handleShortPressOnHome(mPendingHomeKeyEvent);
                    mPendingHomeKeyEvent = null;
                }
            }
        };

        DisplayHomeButtonHandler(int displayId) {
            mDisplayId = displayId;
        }

        boolean handleHomeButton(IBinder focusedToken, KeyEvent event) {
            final boolean keyguardOn = keyguardOn();
            final int repeatCount = event.getRepeatCount();
            final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
            final boolean canceled = event.isCanceled();

            if (DEBUG_INPUT) {
                Log.d(TAG, String.format("handleHomeButton in display#%d mHomePressed = %b",
                        mDisplayId, mHomePressed));
            }

            // If we have released the home key, and didn't do anything else
            // while it was pressed, then it is time to go home!
            if (!down) {
                if (mDisplayId == DEFAULT_DISPLAY) {
                    cancelPreloadRecentApps();
                }

                mHomePressed = false;
                if (mHomeConsumed) {
                    mHomeConsumed = false;
                    return true;
                }

                if (canceled) {
                    Log.i(TAG, "Ignoring HOME; event canceled.");
                    return true;
                }

                // Delay handling home if a double-tap is possible.
                if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
                    // For the picture-in-picture menu, only add the delay if a pip is there.
                    if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_PIP_MENU
                            || mPictureInPictureVisible) {
                        mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
                        mPendingHomeKeyEvent = event;
                        mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
                                ViewConfiguration.getDoubleTapTimeout());
                        return true;
                    }
                }

                // Post to main thread to avoid blocking input pipeline.
                mHandler.post(() -> handleShortPressOnHome(event));
                return true;
            }

            final KeyInterceptionInfo info =
                    mWindowManagerInternal.getKeyInterceptionInfoFromToken(focusedToken);
            if (info != null) {
                // If a system window has focus, then it doesn't make sense
                // right now to interact with applications.
                if (info.layoutParamsType == TYPE_KEYGUARD_DIALOG
                        || (info.layoutParamsType == TYPE_NOTIFICATION_SHADE
                        && isKeyguardShowing())) {
                    // the "app" is keyguard, so give it the key
                    return false;
                }
                for (int t : WINDOW_TYPES_WHERE_HOME_DOESNT_WORK) {
                    if (info.layoutParamsType == t) {
                        // don't do anything, but also don't pass it to the app
                        return true;
                    }
                }
            }

            // Remember that home is pressed and handle special actions.
            if (repeatCount == 0) {
                mHomePressed = true;
                if (mPendingHomeKeyEvent != null) {
                    mPendingHomeKeyEvent = null;
                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
                    mHandler.post(() -> handleDoubleTapOnHome(event));
                // TODO(multi-display): Remove display id check once we support recents on
                // multi-display
                } else if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI
                        && mDisplayId == DEFAULT_DISPLAY) {
                    preloadRecentApps();
                }
            } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
                if (!keyguardOn) {
                    // Post to main thread to avoid blocking input pipeline.
                    mHandler.post(() -> handleLongPressOnHome(event));
                }
            }
            return true;
        }

        private void handleDoubleTapOnHome(KeyEvent event) {
            if (mHomeConsumed) {
                return;
            }
            switch (mDoubleTapOnHomeBehavior) {
                case DOUBLE_TAP_HOME_RECENT_SYSTEM_UI:
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.APP_SWITCH);
                    mHomeConsumed = true;
                    toggleRecentApps();
                    break;
                case DOUBLE_TAP_HOME_PIP_MENU:
                    mHomeConsumed = true;
                    showPictureInPictureMenuInternal();
                    break;
                default:
                    Log.w(TAG, "No action or undefined behavior for double tap home: "
                            + mDoubleTapOnHomeBehavior);
                    break;
            }
        }

        private void handleLongPressOnHome(KeyEvent event) {
            if (mHomeConsumed) {
                return;
            }
            if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_NOTHING) {
                return;
            }
            mHomeConsumed = true;
            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
                    "Home - Long Press");
            switch (mLongPressOnHomeBehavior) {
                case LONG_PRESS_HOME_ALL_APPS:
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.ALL_APPS);
                    launchAllAppsAction();
                    break;
                case LONG_PRESS_HOME_ASSIST:
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_ASSISTANT);
                    launchAssistAction(null, event.getDeviceId(), event.getEventTime(),
                            AssistUtils.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS);
                    break;
                case LONG_PRESS_HOME_NOTIFICATION_PANEL:
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL);
                    toggleNotificationPanel();
                    break;
                default:
                    Log.w(TAG, "Undefined long press on home behavior: "
                            + mLongPressOnHomeBehavior);
                    break;
            }
        }

        @Override
        public String toString() {
            return String.format("mDisplayId = %d, mHomePressed = %b", mDisplayId, mHomePressed);
        }
    }

    /** A DisplayHomeButtonHandler map indexed by display id */
    private final SparseArray<DisplayHomeButtonHandler> mDisplayHomeButtonHandlers =
            new SparseArray<>();

    private boolean isRoundWindow() {
        return mContext.getResources().getConfiguration().isScreenRound();
    }

    @Override
    public void setDefaultDisplay(DisplayContentInfo displayContentInfo) {
        mDefaultDisplay = displayContentInfo.getDisplay();
        mDefaultDisplayRotation = displayContentInfo.getDisplayRotation();
        mDefaultDisplayPolicy = mDefaultDisplayRotation.getDisplayPolicy();
    }

    /** Point of injection for test dependencies. */
    @VisibleForTesting
    static class Injector {
        private final Context mContext;
        private final WindowManagerFuncs mWindowManagerFuncs;
        private final Looper mLooper;

        Injector(Context context, WindowManagerFuncs funcs, Looper looper) {
            mContext = context;
            mWindowManagerFuncs = funcs;
            mLooper = looper;
        }

        Context getContext() {
            return mContext;
        }

        WindowManagerFuncs getWindowManagerFuncs() {
            return mWindowManagerFuncs;
        }

        Looper getLooper() {
            return mLooper;
        }

        AccessibilityShortcutController getAccessibilityShortcutController(
                Context context, Handler handler, int initialUserId) {
            return new AccessibilityShortcutController(context, handler, initialUserId);
        }

        Supplier<GlobalActions> getGlobalActionsFactory() {
            return () -> new GlobalActions(mContext, mWindowManagerFuncs);
        }

        KeyguardServiceDelegate getKeyguardServiceDelegate() {
            return new KeyguardServiceDelegate(mContext,
                    new StateCallback() {
                        @Override
                        public void onTrustedChanged() {
                            mWindowManagerFuncs.notifyKeyguardTrustedChanged();
                        }

                        @Override
                        public void onShowingChanged() {
                            mWindowManagerFuncs.onKeyguardShowingAndNotOccludedChanged();
                        }
                    });
        }

        IActivityManager getActivityManagerService() {
            return ActivityManager.getService();
        }

        ButtonOverridePermissionChecker getButtonOverridePermissionChecker() {
            return new ButtonOverridePermissionChecker();
        }

        TalkbackShortcutController getTalkbackShortcutController() {
            return new TalkbackShortcutController(mContext);
        }
    }

    /** {@inheritDoc} */
    @Override
    public void init(Context context, WindowManagerFuncs funcs) {
        init(new Injector(context, funcs, Looper.myLooper()));
    }

    @VisibleForTesting
    void init(Injector injector) {
        mContext = injector.getContext();
        mWindowManagerFuncs = injector.getWindowManagerFuncs();
        mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
        mActivityManagerService = injector.getActivityManagerService();
        mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
        mInputManager = mContext.getSystemService(InputManager.class);
        mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
        mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
        mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
        mSensorPrivacyManager = mContext.getSystemService(SensorPrivacyManager.class);
        mDisplayManager = mContext.getSystemService(DisplayManager.class);
        mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
        mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
        mPackageManager = mContext.getPackageManager();
        mHasFeatureWatch = mPackageManager.hasSystemFeature(FEATURE_WATCH);
        mHasFeatureLeanback = mPackageManager.hasSystemFeature(FEATURE_LEANBACK);
        mHasFeatureAuto = mPackageManager.hasSystemFeature(FEATURE_AUTOMOTIVE);
        mHasFeatureHdmiCec = mPackageManager.hasSystemFeature(FEATURE_HDMI_CEC);
        mAccessibilityShortcutController = injector.getAccessibilityShortcutController(
                mContext, new Handler(), mCurrentUserId);
        mGlobalActionsFactory = injector.getGlobalActionsFactory();
        mLockPatternUtils = new LockPatternUtils(mContext);
        mLogger = new MetricsLogger();

        mScreenOffSleepTokenAcquirer = mActivityTaskManagerInternal
                .createSleepTokenAcquirer("ScreenOff");

        Resources res = mContext.getResources();
        mWakeOnDpadKeyPress =
                res.getBoolean(com.android.internal.R.bool.config_wakeOnDpadKeyPress);
        mWakeOnAssistKeyPress =
                res.getBoolean(com.android.internal.R.bool.config_wakeOnAssistKeyPress);
        mWakeOnBackKeyPress =
                res.getBoolean(com.android.internal.R.bool.config_wakeOnBackKeyPress);

        // Init display burn-in protection
        boolean burnInProtectionEnabled = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_enableBurnInProtection);
        // Allow a system property to override this. Used by developer settings.
        boolean burnInProtectionDevMode =
                SystemProperties.getBoolean("persist.debug.force_burn_in", false);
        if (burnInProtectionEnabled || burnInProtectionDevMode) {
            final int minHorizontal;
            final int maxHorizontal;
            final int minVertical;
            final int maxVertical;
            final int maxRadius;
            if (burnInProtectionDevMode) {
                minHorizontal = -8;
                maxHorizontal = 8;
                minVertical = -8;
                maxVertical = -4;
                maxRadius = (isRoundWindow()) ? 6 : -1;
            } else {
                Resources resources = mContext.getResources();
                minHorizontal = resources.getInteger(
                        com.android.internal.R.integer.config_burnInProtectionMinHorizontalOffset);
                maxHorizontal = resources.getInteger(
                        com.android.internal.R.integer.config_burnInProtectionMaxHorizontalOffset);
                minVertical = resources.getInteger(
                        com.android.internal.R.integer.config_burnInProtectionMinVerticalOffset);
                maxVertical = resources.getInteger(
                        com.android.internal.R.integer.config_burnInProtectionMaxVerticalOffset);
                maxRadius = resources.getInteger(
                        com.android.internal.R.integer.config_burnInProtectionMaxRadius);
            }
            mBurnInProtectionHelper = new BurnInProtectionHelper(
                    mContext, minHorizontal, maxHorizontal, minVertical, maxVertical, maxRadius);
        }

        mHandler = new PolicyHandler(injector.getLooper());
        mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
        mSettingsObserver = new SettingsObserver(mHandler);
        mSettingsObserver.observe();
        mModifierShortcutManager = new ModifierShortcutManager(mContext, mHandler);
        mUiMode = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_defaultUiModeType);
        mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
        mHomeIntent.addCategory(Intent.CATEGORY_HOME);
        mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
        mEnableCarDockHomeCapture = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_enableCarDockHomeLaunch);
        mCarDockIntent =  new Intent(Intent.ACTION_MAIN, null);
        mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
        mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
        mDeskDockIntent =  new Intent(Intent.ACTION_MAIN, null);
        mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
        mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
        mVrHeadsetHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
        mVrHeadsetHomeIntent.addCategory(Intent.CATEGORY_VR_HOME);
        mVrHeadsetHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                "PhoneWindowManager.mBroadcastWakeLock");
        mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                "PhoneWindowManager.mPowerKeyWakeLock");
        mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
        mLidKeyboardAccessibility = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_lidKeyboardAccessibility);
        mLidNavigationAccessibility = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_lidNavigationAccessibility);

        mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
        mAllowTheaterModeWakeFromPowerKey = mAllowTheaterModeWakeFromKey
                || mContext.getResources().getBoolean(
                    com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey);
        mAllowTheaterModeWakeFromMotion = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_allowTheaterModeWakeFromMotion);
        mAllowTheaterModeWakeFromMotionWhenNotDreaming = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_allowTheaterModeWakeFromMotionWhenNotDreaming);
        mAllowTheaterModeWakeFromCameraLens = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_allowTheaterModeWakeFromCameraLens);
        mAllowTheaterModeWakeFromLidSwitch = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch);
        mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture);

        mGoToSleepOnButtonPressTheaterMode = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_goToSleepOnButtonPressTheaterMode);

        mSupportLongPressPowerWhenNonInteractive = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_supportLongPressPowerWhenNonInteractive);
        mSupportShortPressPowerWhenDefaultDisplayOn =
                mContext.getResources()
                        .getBoolean(
                                com.android.internal.R.bool
                                        .config_supportShortPressPowerWhenDefaultDisplayOn);

        mLongPressOnBackBehavior = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_longPressOnBackBehavior);

        mLongPressOnPowerBehavior = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_longPressOnPowerBehavior);
        mLongPressOnPowerAssistantTimeoutMs = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_longPressOnPowerDurationMs);
        mVeryLongPressOnPowerBehavior = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_veryLongPressOnPowerBehavior);
        mPowerDoublePressTargetActivity = ComponentName.unflattenFromString(
            mContext.getResources().getString(
                com.android.internal.R.string.config_doublePressOnPowerTargetActivity));
        mPrimaryShortPressTargetActivity = ComponentName.unflattenFromString(
            mContext.getResources().getString(
                com.android.internal.R.string.config_primaryShortPressTargetActivity));
        mShortPressOnSleepBehavior = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_shortPressOnSleepBehavior);
        mSilenceRingerOnSleepKey = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_silenceRingerOnSleepKey);
        mAllowStartActivityForLongPressOnPowerDuringSetup = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_allowStartActivityForLongPressOnPowerInSetup);

        mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION;

        mHandleVolumeKeysInWM = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_handleVolumeKeysInWindowManager);

        mWakeUpToLastStateTimeout = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_wakeUpToLastStateTimeoutMillis);

        mSearchKeyBehavior = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_searchKeyBehavior);

        mSearchKeyTargetActivity = ComponentName.unflattenFromString(
            mContext.getResources().getString(
                com.android.internal.R.string.config_searchKeyTargetActivity));
        readConfigurationDependentBehaviors();

        mDisplayFoldController = DisplayFoldController.create(mContext, DEFAULT_DISPLAY);

        mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(
                Context.ACCESSIBILITY_SERVICE);

        // register for dock events
        IntentFilter filter = new IntentFilter();
        filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
        filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
        filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
        filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
        filter.addAction(Intent.ACTION_DOCK_EVENT);
        Intent intent = mContext.registerReceiver(mDockReceiver, filter);
        if (intent != null) {
            // Retrieve current sticky dock event broadcast.
            mDefaultDisplayPolicy.setDockMode(intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
                    Intent.EXTRA_DOCK_STATE_UNDOCKED));
        }

        // register for multiuser-relevant broadcasts
        filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
        mContext.registerReceiver(mMultiuserReceiver, filter);

        mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
        mHapticFeedbackVibrationProvider =
                new HapticFeedbackVibrationProvider(mContext.getResources(), mVibrator);

        mGlobalKeyManager = new GlobalKeyManager(mContext);

        // Controls rotation and the like.
        initializeHdmiState();

        // Match current screen state.
        if (!mPowerManager.isInteractive()) {
            startedGoingToSleep(Display.DEFAULT_DISPLAY_GROUP,
                    PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
            finishedGoingToSleep(Display.DEFAULT_DISPLAY_GROUP,
                    PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
        }

        mWindowManagerInternal.registerAppTransitionListener(new AppTransitionListener() {
            @Override
            public int onAppTransitionStartingLocked(long statusBarAnimationStartTime,
                    long statusBarAnimationDuration) {
                return handleTransitionForKeyguardLw(false /* startKeyguardExitAnimation */,
                        false /* notifyOccluded */);
            }

            @Override
            public void onAppTransitionCancelledLocked(boolean keyguardGoingAwayCancelled) {
                // When KEYGUARD_GOING_AWAY app transition is canceled, we need to trigger relevant
                // IKeyguardService calls to sync keyguard status in WindowManagerService and SysUI.
                handleTransitionForKeyguardLw(
                        keyguardGoingAwayCancelled /* startKeyguardExitAnimation */,
                        true /* notifyOccluded */);

                synchronized (mLock) {
                    mLockAfterDreamingTransitionFinished = false;
                }
            }

            @Override
            public void onAppTransitionFinishedLocked(IBinder token) {
                synchronized (mLock) {
                    final DreamManagerInternal dreamManagerInternal = getDreamManagerInternal();
                    // check both isDreaming and mLockAfterDreamingTransitionFinished before lockNow
                    // so it won't relock after dreaming has stopped
                    if (dreamManagerInternal != null && dreamManagerInternal.isDreaming()
                            && mLockAfterDreamingTransitionFinished) {
                        lockNow(null);
                    }
                    mLockAfterDreamingTransitionFinished = false;
                }
            }
        });

        mKeyguardDrawnTimeout = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_keyguardDrawnTimeout);
        mKeyguardDelegate = injector.getKeyguardServiceDelegate();
        mTalkbackShortcutController = injector.getTalkbackShortcutController();
        initKeyCombinationRules();
        initSingleKeyGestureRules(injector.getLooper());
        mButtonOverridePermissionChecker = injector.getButtonOverridePermissionChecker();
        mSideFpsEventHandler = new SideFpsEventHandler(mContext, mHandler, mPowerManager);
    }

    private void initKeyCombinationRules() {
        mKeyCombinationManager = new KeyCombinationManager(mHandler);
        final boolean screenshotChordEnabled = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_enableScreenshotChord);

        if (screenshotChordEnabled) {
            mKeyCombinationManager.addRule(
                    new TwoKeysCombinationRule(KEYCODE_VOLUME_DOWN, KEYCODE_POWER) {
                        @Override
                        void execute() {
                            mPowerKeyHandled = true;
                            interceptScreenshotChord(
                                    SCREENSHOT_KEY_CHORD, getScreenshotChordLongPressDelay());
                        }
                        @Override
                        void cancel() {
                            cancelPendingScreenshotChordAction();
                        }
                    });

            if (mHasFeatureWatch) {
                mKeyCombinationManager.addRule(
                        new TwoKeysCombinationRule(KEYCODE_POWER, KEYCODE_STEM_PRIMARY) {
                            @Override
                            void execute() {
                                mPowerKeyHandled = true;
                                interceptScreenshotChord(SCREENSHOT_KEY_CHORD,
                                        getScreenshotChordLongPressDelay());
                            }
                            @Override
                            void cancel() {
                                cancelPendingScreenshotChordAction();
                            }
                        });
            }
        }

        mKeyCombinationManager.addRule(
                new TwoKeysCombinationRule(KEYCODE_VOLUME_DOWN, KEYCODE_VOLUME_UP) {
                    @Override
                    boolean preCondition() {
                        return mAccessibilityShortcutController
                                .isAccessibilityShortcutAvailable(isKeyguardLocked());
                    }
                    @Override
                    void execute() {
                        interceptAccessibilityShortcutChord();
                    }
                    @Override
                    void cancel() {
                        cancelPendingAccessibilityShortcutAction();
                    }
                });

        // Volume up + power can either be the "ringer toggle chord" or as another way to
        // launch GlobalActions. This behavior can change at runtime so we must check behavior
        // inside the TwoKeysCombinationRule.
        mKeyCombinationManager.addRule(
                new TwoKeysCombinationRule(KEYCODE_VOLUME_UP, KEYCODE_POWER) {
                    @Override
                    boolean preCondition() {
                        switch (mPowerVolUpBehavior) {
                            case POWER_VOLUME_UP_BEHAVIOR_MUTE:
                                return mRingerToggleChord != VOLUME_HUSH_OFF;
                            default:
                                return true;
                        }
                    }
                    @Override
                    void execute() {
                        switch (mPowerVolUpBehavior) {
                            case POWER_VOLUME_UP_BEHAVIOR_MUTE:
                                // no haptic feedback here since
                                interceptRingerToggleChord();
                                mPowerKeyHandled = true;
                                break;
                            case POWER_VOLUME_UP_BEHAVIOR_GLOBAL_ACTIONS:
                                performHapticFeedback(
                                        HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false,
                                        "Power + Volume Up - Global Actions");
                                showGlobalActions();
                                mPowerKeyHandled = true;
                                break;
                            default:
                                break;
                        }
                    }
                    @Override
                    void cancel() {
                        switch (mPowerVolUpBehavior) {
                            case POWER_VOLUME_UP_BEHAVIOR_MUTE:
                                cancelPendingRingerToggleChordAction();
                                break;
                            case POWER_VOLUME_UP_BEHAVIOR_GLOBAL_ACTIONS:
                                cancelGlobalActionsAction();
                                break;
                        }
                    }
                });

        if (mHasFeatureLeanback) {
            mKeyCombinationManager.addRule(
                    new TwoKeysCombinationRule(KEYCODE_BACK, KEYCODE_DPAD_DOWN) {
                        @Override
                        void execute() {
                            mBackKeyHandled = true;
                            interceptAccessibilityGestureTv();
                        }
                        @Override
                        void cancel() {
                            cancelAccessibilityGestureTv();
                        }
                        @Override
                        long getKeyInterceptDelayMs() {
                            // Use a timeout of 0 to prevent additional latency in processing of
                            // this key. This will potentially cause some unwanted UI actions if the
                            // user does end up triggering the key combination later, but in most
                            // cases, the user will simply hit a single key, and this will allow us
                            // to process it without first waiting to see if the combination is
                            // going to be triggered.
                            return 0;
                        }
                    });

            mKeyCombinationManager.addRule(
                    new TwoKeysCombinationRule(KEYCODE_DPAD_CENTER, KEYCODE_BACK) {
                        @Override
                        void execute() {
                            mBackKeyHandled = true;
                            interceptBugreportGestureTv();
                        }
                        @Override
                        void cancel() {
                            cancelBugreportGestureTv();
                        }
                        @Override
                        long getKeyInterceptDelayMs() {
                            return 0;
                        }
                    });
        }
    }

    /**
     * Rule for single power key gesture.
     */
    private final class PowerKeyRule extends SingleKeyGestureDetector.SingleKeyRule {
        PowerKeyRule() {
            super(KEYCODE_POWER);
        }

        @Override
        boolean supportLongPress() {
            return hasLongPressOnPowerBehavior();
        }

        @Override
        boolean supportVeryLongPress() {
            return hasVeryLongPressOnPowerBehavior();
        }


        @Override
        int getMaxMultiPressCount() {
            return getMaxMultiPressPowerCount();
        }

        @Override
        void onPress(long downTime, int displayId) {
            if (mShouldEarlyShortPressOnPower) {
                return;
            }
            powerPress(downTime, 1 /*count*/, displayId);
        }

        @Override
        long getLongPressTimeoutMs() {
            if (getResolvedLongPressOnPowerBehavior() == LONG_PRESS_POWER_ASSISTANT) {
                return mLongPressOnPowerAssistantTimeoutMs;
            } else {
                return super.getLongPressTimeoutMs();
            }
        }

        @Override
        void onLongPress(long eventTime) {
            if (mSingleKeyGestureDetector.beganFromNonInteractive()
                    && !mSupportLongPressPowerWhenNonInteractive) {
                Slog.v(TAG, "Not support long press power when device is not interactive.");
                return;
            }

            powerLongPress(eventTime);
        }

        @Override
        void onVeryLongPress(long eventTime) {
            mActivityManagerInternal.prepareForPossibleShutdown();
            powerVeryLongPress();
        }

        @Override
        void onMultiPress(long downTime, int count, int displayId) {
            powerPress(downTime, count, displayId);
        }

        @Override
        void onKeyUp(long eventTime, int count, int displayId) {
            if (mShouldEarlyShortPressOnPower && count == 1) {
                powerPress(eventTime, 1 /*pressCount*/, displayId);
            }
        }
    }

    /**
     * Rule for single back key gesture.
     */
    private final class BackKeyRule extends SingleKeyGestureDetector.SingleKeyRule {
        BackKeyRule() {
            super(KEYCODE_BACK);
        }

        @Override
        boolean supportLongPress() {
            return hasLongPressOnBackBehavior();
        }

        @Override
        int getMaxMultiPressCount() {
            return 1;
        }

        @Override
        void onPress(long downTime, int unusedDisplayId) {
            mBackKeyHandled |= backKeyPress();
        }

        @Override
        void onLongPress(long downTime) {
            backLongPress();
        }
    }

    /**
     * Rule for single stem primary key gesture.
     */
    private final class StemPrimaryKeyRule extends SingleKeyGestureDetector.SingleKeyRule {
        StemPrimaryKeyRule() {
            super(KeyEvent.KEYCODE_STEM_PRIMARY);
        }

        @Override
        boolean supportLongPress() {
            return hasLongPressOnStemPrimaryBehavior();
        }

        @Override
        int getMaxMultiPressCount() {
            return getMaxMultiPressStemPrimaryCount();
        }

        @Override
        void onPress(long downTime, int unusedDisplayId) {
            if (mShouldEarlyShortPressOnStemPrimary) {
                return;
            }
            // Short-press should be triggered only if app doesn't handle it.
            mDeferredKeyActionExecutor.queueKeyAction(
                    KeyEvent.KEYCODE_STEM_PRIMARY, downTime, () -> stemPrimaryPress(1 /*count*/));
        }

        @Override
        void onLongPress(long eventTime) {
            // Long-press should be triggered only if app doesn't handle it.
            mDeferredKeyActionExecutor.queueKeyAction(
                    KeyEvent.KEYCODE_STEM_PRIMARY,
                    eventTime,
                    () -> stemPrimaryLongPress(eventTime));
        }

        @Override
        void onMultiPress(long downTime, int count, int unusedDisplayId) {
            // Triple-press stem to toggle accessibility gesture should always be triggered
            // regardless of if app handles it.
            if (count == 3
                    && mTriplePressOnStemPrimaryBehavior
                    == TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY) {
                stemPrimaryPress(count);
            } else {
                // Other multi-press gestures should be triggered only if app doesn't handle it.
                mDeferredKeyActionExecutor.queueKeyAction(
                        KeyEvent.KEYCODE_STEM_PRIMARY, downTime, () -> stemPrimaryPress(count));
            }
        }

        @Override
        void onKeyUp(long eventTime, int count, int unusedDisplayId) {
            if (count == 1) {
                // Save info about the most recent task on the first press of the stem key. This
                // may be used later to switch to the most recent app using double press gesture.
                // It is possible that we may navigate away from this task before the double
                // press is detected, as a result of the first press, so we save the  current
                // most recent task before that happens.
                mBackgroundRecentTaskInfoOnStemPrimarySingleKeyUp =
                        mActivityTaskManagerInternal.getMostRecentTaskFromBackground();
                if (mShouldEarlyShortPressOnStemPrimary) {
                    // Key-up gesture should be triggered only if app doesn't handle it.
                    mDeferredKeyActionExecutor.queueKeyAction(
                            KeyEvent.KEYCODE_STEM_PRIMARY, eventTime, () -> stemPrimaryPress(1));
                }
            }
        }
    }

    private void initSingleKeyGestureRules(Looper looper) {
        mSingleKeyGestureDetector = SingleKeyGestureDetector.get(mContext, looper);
        mSingleKeyGestureDetector.addRule(new PowerKeyRule());
        if (hasLongPressOnBackBehavior()) {
            mSingleKeyGestureDetector.addRule(new BackKeyRule());
        }
        if (hasStemPrimaryBehavior()) {
            mSingleKeyGestureDetector.addRule(new StemPrimaryKeyRule());
        }
    }

    /**
     * Read values from config.xml that may be overridden depending on
     * the configuration of the device.
     * eg. Disable long press on home goes to recents on sw600dp.
     */
    private void readConfigurationDependentBehaviors() {
        final Resources res = mContext.getResources();

        mLongPressOnHomeBehavior = res.getInteger(
                com.android.internal.R.integer.config_longPressOnHomeBehavior);
        if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||
                mLongPressOnHomeBehavior > LAST_LONG_PRESS_HOME_BEHAVIOR) {
            mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
        }

        mDoubleTapOnHomeBehavior = res.getInteger(
                com.android.internal.R.integer.config_doubleTapOnHomeBehavior);
        if (mDoubleTapOnHomeBehavior < DOUBLE_TAP_HOME_NOTHING ||
                mDoubleTapOnHomeBehavior > DOUBLE_TAP_HOME_PIP_MENU) {
            mDoubleTapOnHomeBehavior = DOUBLE_TAP_HOME_NOTHING;
        }

        mShortPressOnWindowBehavior = SHORT_PRESS_WINDOW_NOTHING;
        if (mPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
            mShortPressOnWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE;
        }

        mShortPressOnSettingsBehavior = res.getInteger(
                com.android.internal.R.integer.config_shortPressOnSettingsBehavior);
        if (mShortPressOnSettingsBehavior < SHORT_PRESS_SETTINGS_NOTHING
                || mShortPressOnSettingsBehavior > LAST_SHORT_PRESS_SETTINGS_BEHAVIOR) {
            mShortPressOnSettingsBehavior = SHORT_PRESS_SETTINGS_NOTHING;
        }
    }

    private void updateSettings() {
        updateSettings(null);
    }

    /**
     * Update provider Setting values on a given {@code handler}, or synchronously if {@code null}
     * is passed for handler.
     */
    void updateSettings(Handler handler) {
        if (handler != null) {
            handler.post(() -> updateSettings(null));
            return;
        }
        ContentResolver resolver = mContext.getContentResolver();
        boolean updateRotation = false;
        synchronized (mLock) {
            mEndcallBehavior = Settings.System.getIntForUser(resolver,
                    Settings.System.END_BUTTON_BEHAVIOR,
                    Settings.System.END_BUTTON_BEHAVIOR_DEFAULT,
                    UserHandle.USER_CURRENT);
            mIncallPowerBehavior = Settings.Secure.getIntForUser(resolver,
                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT,
                    UserHandle.USER_CURRENT);
            mIncallBackBehavior = Settings.Secure.getIntForUser(resolver,
                    Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR,
                    Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_DEFAULT,
                    UserHandle.USER_CURRENT);
            mSystemNavigationKeysEnabled = Settings.Secure.getIntForUser(resolver,
                    Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED,
                    0, UserHandle.USER_CURRENT) == 1;
            mRingerToggleChord = Settings.Secure.getIntForUser(resolver,
                    Settings.Secure.VOLUME_HUSH_GESTURE, VOLUME_HUSH_OFF,
                    UserHandle.USER_CURRENT);
            mPowerButtonSuppressionDelayMillis = Settings.Global.getInt(resolver,
                    Settings.Global.POWER_BUTTON_SUPPRESSION_DELAY_AFTER_GESTURE_WAKE,
                    POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS);
            if (!mContext.getResources()
                    .getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled)) {
                mRingerToggleChord = VOLUME_HUSH_OFF;
            }

            // Configure wake gesture.
            boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver,
                    Settings.Secure.WAKE_GESTURE_ENABLED, 0,
                    UserHandle.USER_CURRENT) != 0;
            if (mWakeGestureEnabledSetting != wakeGestureEnabledSetting) {
                mWakeGestureEnabledSetting = wakeGestureEnabledSetting;
                updateWakeGestureListenerLp();
            }

            // use screen off timeout setting as the timeout for the lockscreen
            mLockScreenTimeout = Settings.System.getIntForUser(resolver,
                    Settings.System.SCREEN_OFF_TIMEOUT, 0, UserHandle.USER_CURRENT);
            String imId = Settings.Secure.getStringForUser(resolver,
                    Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.USER_CURRENT);
            boolean hasSoftInput = imId != null && imId.length() > 0;
            if (mHasSoftInput != hasSoftInput) {
                mHasSoftInput = hasSoftInput;
                updateRotation = true;
            }

            mShortPressOnPowerBehavior = Settings.Global.getInt(resolver,
                    Settings.Global.POWER_BUTTON_SHORT_PRESS,
                    mContext.getResources().getInteger(
                            com.android.internal.R.integer.config_shortPressOnPowerBehavior));
            mDoublePressOnPowerBehavior = Settings.Global.getInt(resolver,
                    Settings.Global.POWER_BUTTON_DOUBLE_PRESS,
                    mContext.getResources().getInteger(
                            com.android.internal.R.integer.config_doublePressOnPowerBehavior));
            mTriplePressOnPowerBehavior = Settings.Global.getInt(resolver,
                    Settings.Global.POWER_BUTTON_TRIPLE_PRESS,
                    mContext.getResources().getInteger(
                            com.android.internal.R.integer.config_triplePressOnPowerBehavior));

            final int longPressOnPowerBehavior = Settings.Global.getInt(resolver,
                    Settings.Global.POWER_BUTTON_LONG_PRESS,
                    mContext.getResources().getInteger(
                            com.android.internal.R.integer.config_longPressOnPowerBehavior));
            final int veryLongPressOnPowerBehavior = Settings.Global.getInt(resolver,
                    Settings.Global.POWER_BUTTON_VERY_LONG_PRESS,
                    mContext.getResources().getInteger(
                            com.android.internal.R.integer.config_veryLongPressOnPowerBehavior));
            if (mLongPressOnPowerBehavior != longPressOnPowerBehavior
                    || mVeryLongPressOnPowerBehavior != veryLongPressOnPowerBehavior) {
                mLongPressOnPowerBehavior = longPressOnPowerBehavior;
                mVeryLongPressOnPowerBehavior = veryLongPressOnPowerBehavior;
            }

            mLongPressOnPowerAssistantTimeoutMs = Settings.Global.getLong(
                    mContext.getContentResolver(),
                    Settings.Global.POWER_BUTTON_LONG_PRESS_DURATION_MS,
                    mContext.getResources().getInteger(
                            com.android.internal.R.integer.config_longPressOnPowerDurationMs));

            mPowerVolUpBehavior = Settings.Global.getInt(resolver,
                    Settings.Global.KEY_CHORD_POWER_VOLUME_UP,
                    mContext.getResources().getInteger(
                            com.android.internal.R.integer.config_keyChordPowerVolumeUp));

            mShortPressOnStemPrimaryBehavior = Settings.Global.getInt(resolver,
                    Settings.Global.STEM_PRIMARY_BUTTON_SHORT_PRESS,
                    mContext.getResources().getInteger(
                            com.android.internal.R.integer.config_shortPressOnStemPrimaryBehavior));
            mDoublePressOnStemPrimaryBehavior = Settings.Global.getInt(resolver,
                    Settings.Global.STEM_PRIMARY_BUTTON_DOUBLE_PRESS,
                    mContext.getResources().getInteger(
                            com.android.internal.R.integer
                                    .config_doublePressOnStemPrimaryBehavior));
            mTriplePressOnStemPrimaryBehavior = Settings.Global.getInt(resolver,
                    Settings.Global.STEM_PRIMARY_BUTTON_TRIPLE_PRESS,
                    mContext.getResources().getInteger(
                            com.android.internal.R.integer
                                    .config_triplePressOnStemPrimaryBehavior));
            mLongPressOnStemPrimaryBehavior = Settings.Global.getInt(resolver,
                    Settings.Global.STEM_PRIMARY_BUTTON_LONG_PRESS,
                    mContext.getResources().getInteger(
                            com.android.internal.R.integer.config_longPressOnStemPrimaryBehavior));
            mShouldEarlyShortPressOnPower =
                    mContext.getResources()
                            .getBoolean(com.android.internal.R.bool.config_shortPressEarlyOnPower);
            mShouldEarlyShortPressOnStemPrimary = mContext.getResources().getBoolean(
                    com.android.internal.R.bool.config_shortPressEarlyOnStemPrimary);

            mStylusButtonsEnabled = Settings.Secure.getIntForUser(resolver,
                    Secure.STYLUS_BUTTONS_ENABLED, 1, UserHandle.USER_CURRENT) == 1;
            mInputManagerInternal.setStylusButtonMotionEventsEnabled(mStylusButtonsEnabled);

            final boolean kidsModeEnabled = Settings.Secure.getIntForUser(resolver,
                    Settings.Secure.NAV_BAR_KIDS_MODE, 0, UserHandle.USER_CURRENT) == 1;
            if (mKidsModeEnabled != kidsModeEnabled) {
                mKidsModeEnabled = kidsModeEnabled;
                updateKidsModeSettings();
            }
        }
        if (updateRotation) {
            updateRotation(true);
        }
    }

    private void updateKidsModeSettings() {
        if (mKidsModeEnabled) {
            // Needed since many Kids apps aren't optimised to support both orientations and it
            // will be hard for kids to understand the app compat mode.
            // TODO(229961548): Remove ignoreOrientationRequest exception for Kids Mode once
            //                  possible.
            if (mContext.getResources().getBoolean(R.bool.config_reverseDefaultRotation)) {
                mWindowManagerInternal.setOrientationRequestPolicy(
                        true /* isIgnoreOrientationRequestDisabled */,
                        new int[]{SCREEN_ORIENTATION_LANDSCAPE,
                                SCREEN_ORIENTATION_REVERSE_LANDSCAPE},
                        new int[]{SCREEN_ORIENTATION_SENSOR_LANDSCAPE,
                                SCREEN_ORIENTATION_SENSOR_LANDSCAPE});
            } else {
                mWindowManagerInternal.setOrientationRequestPolicy(
                        true /* isIgnoreOrientationRequestDisabled */,
                        null /* fromOrientations */, null /* toOrientations */);
            }
        } else {
            mWindowManagerInternal.setOrientationRequestPolicy(
                    false /* isIgnoreOrientationRequestDisabled */,
                    null /* fromOrientations */, null /* toOrientations */);
        }
    }

    private DreamManagerInternal getDreamManagerInternal() {
        if (mDreamManagerInternal == null) {
            // If mDreamManagerInternal is null, attempt to re-fetch it.
            mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
        }

        return mDreamManagerInternal;
    }

    private void updateWakeGestureListenerLp() {
        if (shouldEnableWakeGestureLp()) {
            mWakeGestureListener.requestWakeUpTrigger();
        } else {
            mWakeGestureListener.cancelWakeUpTrigger();
        }
    }

    private boolean shouldEnableWakeGestureLp() {
        return mWakeGestureEnabledSetting && !mDefaultDisplayPolicy.isAwake()
                && (getLidBehavior() != LID_BEHAVIOR_SLEEP
                || mDefaultDisplayPolicy.getLidState() != LID_CLOSED)
                && mWakeGestureListener.isSupported();
    }

    /** {@inheritDoc} */
    @Override
    public int checkAddPermission(int type, boolean isRoundedCornerOverlay, String packageName,
            int[] outAppOp) {
        if (isRoundedCornerOverlay && mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
                != PERMISSION_GRANTED) {
            return ADD_PERMISSION_DENIED;
        }

        outAppOp[0] = AppOpsManager.OP_NONE;

        if (!((type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW)
                || (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW)
                || (type >= FIRST_SYSTEM_WINDOW && type <= LAST_SYSTEM_WINDOW))) {
            return WindowManagerGlobal.ADD_INVALID_TYPE;
        }

        if (type < FIRST_SYSTEM_WINDOW || type > LAST_SYSTEM_WINDOW) {
            // Window manager will make sure these are okay.
            return ADD_OKAY;
        }

        if (!isSystemAlertWindowType(type)) {
            switch (type) {
                case TYPE_TOAST:
                    // Only apps that target older than O SDK can add window without a token, after
                    // that we require a token so apps cannot add toasts directly as the token is
                    // added by the notification system.
                    // Window manager does the checking for this.
                    outAppOp[0] = OP_TOAST_WINDOW;
                    return ADD_OKAY;
                case TYPE_ACCESSIBILITY_OVERLAY:
                    if (createAccessibilityOverlayAppOpEnabled()) {
                        outAppOp[0] = OP_CREATE_ACCESSIBILITY_OVERLAY;
                        return ADD_OKAY;
                    }
                case TYPE_INPUT_METHOD:
                case TYPE_WALLPAPER:
                case TYPE_PRESENTATION:
                case TYPE_PRIVATE_PRESENTATION:
                case TYPE_VOICE_INTERACTION:
                case TYPE_QS_DIALOG:
                case TYPE_NAVIGATION_BAR_PANEL:
                    // The window manager will check these.
                    return ADD_OKAY;
            }

            return (mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
                    == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
        }

        // Things get a little more interesting for alert windows...
        outAppOp[0] = OP_SYSTEM_ALERT_WINDOW;

        final int callingUid = Binder.getCallingUid();
        // system processes will be automatically granted privilege to draw
        if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
            return ADD_OKAY;
        }

        ApplicationInfo appInfo;
        try {
            appInfo = mPackageManager.getApplicationInfoAsUser(
                            packageName,
                            0 /* flags */,
                            UserHandle.getUserId(callingUid));
        } catch (PackageManager.NameNotFoundException e) {
            appInfo = null;
        }

        if (appInfo == null || (type != TYPE_APPLICATION_OVERLAY && appInfo.targetSdkVersion >= O)) {
            /**
             * Apps targeting >= {@link Build.VERSION_CODES#O} are required to hold
             * {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW} (system signature apps)
             * permission to add alert windows that aren't
             * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY}.
             */
            return (mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
                    == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
        }

        if (mContext.checkCallingOrSelfPermission(SYSTEM_APPLICATION_OVERLAY)
                == PERMISSION_GRANTED) {
            return ADD_OKAY;
        }

        // check if user has enabled this operation. SecurityException will be thrown if this app
        // has not been allowed by the user. The reason to use "noteOp" (instead of checkOp) is to
        // make sure the usage is logged.
        final int mode = mAppOpsManager.noteOpNoThrow(outAppOp[0], callingUid, packageName,
                null /* featureId */, "check-add");
        switch (mode) {
            case AppOpsManager.MODE_ALLOWED:
            case AppOpsManager.MODE_IGNORED:
                // although we return ADD_OKAY for MODE_IGNORED, the added window will
                // actually be hidden in WindowManagerService
                return ADD_OKAY;
            case AppOpsManager.MODE_ERRORED:
                // Don't crash legacy apps
                if (appInfo.targetSdkVersion < M) {
                    return ADD_OKAY;
                }
                return ADD_PERMISSION_DENIED;
            default:
                // in the default mode, we will make a decision here based on
                // checkCallingPermission()
                return (mContext.checkCallingOrSelfPermission(SYSTEM_ALERT_WINDOW)
                        == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
        }
    }

    void readLidState() {
        mDefaultDisplayPolicy.setLidState(mWindowManagerFuncs.getLidState());
    }

    private void readCameraLensCoverState() {
        mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState();
    }

    private boolean isHidden(int accessibilityMode) {
        final int lidState = mDefaultDisplayPolicy.getLidState();
        switch (accessibilityMode) {
            case 1:
                return lidState == LID_CLOSED;
            case 2:
                return lidState == LID_OPEN;
            default:
                return false;
        }
    }

    /** {@inheritDoc} */
    @Override
    public void adjustConfigurationLw(Configuration config, int keyboardPresence,
            int navigationPresence) {
        mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0;

        readConfigurationDependentBehaviors();
        readLidState();

        if (config.keyboard == Configuration.KEYBOARD_NOKEYS
                || (keyboardPresence == PRESENCE_INTERNAL
                        && isHidden(mLidKeyboardAccessibility))) {
            config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
            if (!mHasSoftInput) {
                config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
            }
        }

        if (config.navigation == Configuration.NAVIGATION_NONAV
                || (navigationPresence == PRESENCE_INTERNAL
                        && isHidden(mLidNavigationAccessibility))) {
            config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
        }
    }

    @Override
    public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) {
        return attrs.type == TYPE_NOTIFICATION_SHADE;
    }

    @Override
    public Animation createHiddenByKeyguardExit(boolean onWallpaper,
            boolean goingToNotificationShade, boolean subtleAnimation) {
        return TransitionAnimation.createHiddenByKeyguardExit(mContext,
                mLogDecelerateInterpolator, onWallpaper, goingToNotificationShade, subtleAnimation);
    }


    @Override
    public Animation createKeyguardWallpaperExit(boolean goingToNotificationShade) {
        if (goingToNotificationShade) {
            return null;
        } else {
            return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
        }
    }

    private static void awakenDreams() {
        IDreamManager dreamManager = getDreamManager();
        if (dreamManager != null) {
            try {
                dreamManager.awaken();
            } catch (RemoteException e) {
                // fine, stay asleep then
            }
        }
    }

    static IDreamManager getDreamManager() {
        return IDreamManager.Stub.asInterface(
                ServiceManager.checkService(DreamService.DREAM_SERVICE));
    }

    TelecomManager getTelecommService() {
        return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
    }

    NotificationManager getNotificationService() {
        return mContext.getSystemService(NotificationManager.class);
    }

    static IAudioService getAudioService() {
        IAudioService audioService = IAudioService.Stub.asInterface(
                ServiceManager.checkService(Context.AUDIO_SERVICE));
        if (audioService == null) {
            Log.w(TAG, "Unable to find IAudioService interface.");
        }
        return audioService;
    }

    boolean keyguardOn() {
        return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode();
    }

    private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
            WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
            WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
        };

    /**
     * Log the keyboard shortcuts without blocking the current thread.
     *
     * We won't log keyboard events when the input device is null
     * or when it is virtual.
     */
    private void handleKeyboardSystemEvent(KeyboardLogEvent keyboardLogEvent, KeyEvent event) {
        final InputDevice inputDevice = mInputManager.getInputDevice(event.getDeviceId());
        KeyboardMetricsCollector.logKeyboardSystemsEventReportedAtom(inputDevice,
                keyboardLogEvent, event.getMetaState(), event.getKeyCode());
        event.recycle();
    }

    private void logKeyboardSystemsEventOnActionUp(KeyEvent event,
            KeyboardLogEvent keyboardSystemEvent) {
        if (event.getAction() != KeyEvent.ACTION_UP) {
            return;
        }
        logKeyboardSystemsEvent(event, keyboardSystemEvent);
    }

    private void logKeyboardSystemsEventOnActionDown(KeyEvent event,
            KeyboardLogEvent keyboardSystemEvent) {
        if (event.getAction() != KeyEvent.ACTION_DOWN) {
            return;
        }
        logKeyboardSystemsEvent(event, keyboardSystemEvent);
    }

    private void logKeyboardSystemsEvent(KeyEvent event, KeyboardLogEvent keyboardSystemEvent) {
        KeyEvent eventToLog = KeyEvent.obtain(event);
        mHandler.obtainMessage(MSG_LOG_KEYBOARD_SYSTEM_EVENT, keyboardSystemEvent.getIntValue(), 0,
                eventToLog).sendToTarget();
    }

    // TODO(b/117479243): handle it in InputPolicy
    // TODO (b/283241997): Add the remaining keyboard shortcut logging after refactoring
    /** {@inheritDoc} */
    @Override
    public long interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event,
            int policyFlags) {
        final int keyCode = event.getKeyCode();
        final int flags = event.getFlags();
        final long keyConsumed = -1;
        final long keyNotConsumed = 0;
        final int deviceId = event.getDeviceId();

        if (DEBUG_INPUT) {
            Log.d(TAG,
                    "interceptKeyTi keyCode=" + keyCode + " action=" + event.getAction()
                            + " repeatCount=" + event.getRepeatCount() + " keyguardOn="
                            + keyguardOn() + " canceled=" + event.isCanceled());
        }

        if (mKeyCombinationManager.isKeyConsumed(event)) {
            return keyConsumed;
        }

        if ((flags & KeyEvent.FLAG_FALLBACK) == 0) {
            final long now = SystemClock.uptimeMillis();
            final long interceptTimeout = mKeyCombinationManager.getKeyInterceptTimeout(keyCode);
            if (now < interceptTimeout) {
                return interceptTimeout - now;
            }
        }

        Set<Integer> consumedKeys = mConsumedKeysForDevice.get(deviceId);
        if (consumedKeys == null) {
            consumedKeys = new HashSet<>();
            mConsumedKeysForDevice.put(deviceId, consumedKeys);
        }

        if (interceptSystemKeysAndShortcuts(focusedToken, event)
                && event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
            consumedKeys.add(keyCode);
            return keyConsumed;
        }

        boolean needToConsumeKey = consumedKeys.contains(keyCode);
        if (event.getAction() == KeyEvent.ACTION_UP || event.isCanceled()) {
            consumedKeys.remove(keyCode);
            if (consumedKeys.isEmpty()) {
                mConsumedKeysForDevice.remove(deviceId);
            }
        }

        return needToConsumeKey ? keyConsumed : keyNotConsumed;
    }

    // You can only start consuming the key gesture if ACTION_DOWN and repeat count
    // is 0. If you start intercepting the key halfway, then key will not be consumed
    // and will be sent to apps for processing too.
    // e.g. If a certain combination is only handled on ACTION_UP (i.e.
    // interceptShortcut() returns true only for ACTION_UP), then since we already
    // sent the ACTION_DOWN events to the application, we MUST also send the
    // ACTION_UP to the application.
    // So, to ensure that your intercept logic works properly, and we don't send any
    // conflicting events to application, make sure to consume the event on
    // ACTION_DOWN even if you want to do something on ACTION_UP. This is essential
    // to maintain event parity and to not have incomplete key gestures.
    @SuppressLint("MissingPermission")
    private boolean interceptSystemKeysAndShortcuts(IBinder focusedToken, KeyEvent event) {
        final boolean keyguardOn = keyguardOn();
        final int keyCode = event.getKeyCode();
        final int repeatCount = event.getRepeatCount();
        final int metaState = event.getMetaState();
        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
        final boolean canceled = event.isCanceled();
        final int displayId = event.getDisplayId();
        final int deviceId = event.getDeviceId();
        final boolean firstDown = down && repeatCount == 0;

        // Cancel any pending meta actions if we see any other keys being pressed between the
        // down of the meta key and its corresponding up.
        if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
            mPendingMetaAction = false;
        }
        // Any key that is not Alt or Meta cancels Caps Lock combo tracking.
        if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) {
            mPendingCapsLockToggle = false;
        }

        if (isUserSetupComplete() && !keyguardOn) {
            if (mModifierShortcutManager.interceptKey(event)) {
                dismissKeyboardShortcutsMenu();
                mPendingMetaAction = false;
                mPendingCapsLockToggle = false;
                return true;
            }
        }

        switch (keyCode) {
            case KeyEvent.KEYCODE_HOME:
                return handleHomeShortcuts(focusedToken, event);
            case KeyEvent.KEYCODE_MENU:
                // Hijack modified menu keys for debugging features
                final int chordBug = KeyEvent.META_SHIFT_ON;

                if (mEnableShiftMenuBugReports && firstDown
                        && (metaState & chordBug) == chordBug) {
                    Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
                    mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
                            null, null, null, 0, null, null);
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.TRIGGER_BUG_REPORT);
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_RECENT_APPS:
                if (firstDown) {
                    showRecentApps(false /* triggeredFromAltTab */);
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.RECENT_APPS);
                }
                return true;
            case KeyEvent.KEYCODE_APP_SWITCH:
                if (!keyguardOn) {
                    if (firstDown) {
                        preloadRecentApps();
                    } else if (!down) {
                        toggleRecentApps();
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.APP_SWITCH);
                    }
                }
                return true;
            case KeyEvent.KEYCODE_A:
                if (firstDown && event.isMetaPressed()) {
                    launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD,
                            deviceId, event.getEventTime(),
                            AssistUtils.INVOCATION_TYPE_UNKNOWN);
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_ASSISTANT);
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_H:
            case KeyEvent.KEYCODE_ENTER:
                if (event.isMetaPressed()) {
                    return handleHomeShortcuts(focusedToken, event);
                }
                break;
            case KeyEvent.KEYCODE_I:
                if (firstDown && event.isMetaPressed()) {
                    showSystemSettings();
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_SYSTEM_SETTINGS);
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_L:
                if (firstDown && event.isMetaPressed()) {
                    lockNow(null /* options */);
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.LOCK_SCREEN);
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_N:
                if (firstDown && event.isMetaPressed()) {
                    if (event.isCtrlPressed()) {
                        sendSystemKeyToStatusBarAsync(event);
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.OPEN_NOTES);
                    } else {
                        toggleNotificationPanel();
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL);
                    }
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_S:
                if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
                    interceptScreenshotChord(SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/);
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.TAKE_SCREENSHOT);
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_T:
                if (firstDown && event.isMetaPressed()) {
                    toggleTaskbar();
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_TASKBAR);
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_DEL:
            case KeyEvent.KEYCODE_ESCAPE:
                if (firstDown && event.isMetaPressed()) {
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.BACK);
                    injectBackGesture(event.getDownTime());
                    return true;
                }
            case KeyEvent.KEYCODE_DPAD_UP:
                if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
                    StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
                    if (statusbar != null) {
                        statusbar.goToFullscreenFromSplit();
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION);
                        return true;
                    }
                }
                break;
            case KeyEvent.KEYCODE_DPAD_LEFT:
                if (firstDown && event.isMetaPressed()) {
                    if (event.isCtrlPressed()) {
                        enterStageSplitFromRunningApp(true /* leftOrTop */);
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION);
                    } else {
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.BACK);
                        injectBackGesture(event.getDownTime());
                    }
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_DPAD_RIGHT:
                if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
                    enterStageSplitFromRunningApp(false /* leftOrTop */);
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION);
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_SLASH:
                if (firstDown && event.isMetaPressed() && !keyguardOn) {
                    toggleKeyboardShortcutsMenu(event.getDeviceId());
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.OPEN_SHORTCUT_HELPER);
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_ASSIST:
                Slog.wtf(TAG, "KEYCODE_ASSIST should be handled in interceptKeyBeforeQueueing");
                return true;
            case KeyEvent.KEYCODE_VOICE_ASSIST:
                Slog.wtf(TAG, "KEYCODE_VOICE_ASSIST should be handled in"
                        + " interceptKeyBeforeQueueing");
                return true;
            case KeyEvent.KEYCODE_VIDEO_APP_1:
            case KeyEvent.KEYCODE_VIDEO_APP_2:
            case KeyEvent.KEYCODE_VIDEO_APP_3:
            case KeyEvent.KEYCODE_VIDEO_APP_4:
            case KeyEvent.KEYCODE_VIDEO_APP_5:
            case KeyEvent.KEYCODE_VIDEO_APP_6:
            case KeyEvent.KEYCODE_VIDEO_APP_7:
            case KeyEvent.KEYCODE_VIDEO_APP_8:
            case KeyEvent.KEYCODE_FEATURED_APP_1:
            case KeyEvent.KEYCODE_FEATURED_APP_2:
            case KeyEvent.KEYCODE_FEATURED_APP_3:
            case KeyEvent.KEYCODE_FEATURED_APP_4:
            case KeyEvent.KEYCODE_DEMO_APP_1:
            case KeyEvent.KEYCODE_DEMO_APP_2:
            case KeyEvent.KEYCODE_DEMO_APP_3:
            case KeyEvent.KEYCODE_DEMO_APP_4:
                Slog.wtf(TAG, "KEYCODE_APP_X should be handled in interceptKeyBeforeQueueing");
                return true;
            case KeyEvent.KEYCODE_BRIGHTNESS_UP:
            case KeyEvent.KEYCODE_BRIGHTNESS_DOWN:
                if (down) {
                    int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;

                    // Disable autobrightness if it's on
                    int auto = Settings.System.getIntForUser(
                            mContext.getContentResolver(),
                            Settings.System.SCREEN_BRIGHTNESS_MODE,
                            Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
                            UserHandle.USER_CURRENT_OR_SELF);
                    if (auto != 0) {
                        Settings.System.putIntForUser(mContext.getContentResolver(),
                                Settings.System.SCREEN_BRIGHTNESS_MODE,
                                Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
                                UserHandle.USER_CURRENT_OR_SELF);
                    }
                    int screenDisplayId = displayId < 0 ? DEFAULT_DISPLAY : displayId;

                    float minLinearBrightness = mPowerManager.getBrightnessConstraint(
                            PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
                    float maxLinearBrightness = mPowerManager.getBrightnessConstraint(
                            PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
                    float linearBrightness = mDisplayManager.getBrightness(screenDisplayId);

                    float gammaBrightness = BrightnessUtils.convertLinearToGamma(linearBrightness);
                    float adjustedGammaBrightness =
                            gammaBrightness + 1f / BRIGHTNESS_STEPS * direction;
                    adjustedGammaBrightness = MathUtils.constrain(adjustedGammaBrightness, 0f,
                            1f);
                    float adjustedLinearBrightness = BrightnessUtils.convertGammaToLinear(
                            adjustedGammaBrightness);
                    adjustedLinearBrightness = MathUtils.constrain(adjustedLinearBrightness,
                            minLinearBrightness, maxLinearBrightness);
                    mDisplayManager.setBrightness(screenDisplayId, adjustedLinearBrightness);

                    Intent intent = new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION
                            | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
                    intent.putExtra(EXTRA_FROM_BRIGHTNESS_KEY, true);
                    startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.getBrightnessEvent(keyCode));
                }
                return true;
            case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN:
                if (down) {
                    mInputManagerInternal.decrementKeyboardBacklight(event.getDeviceId());
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.KEYBOARD_BACKLIGHT_DOWN);
                }
                return true;
            case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP:
                if (down) {
                    mInputManagerInternal.incrementKeyboardBacklight(event.getDeviceId());
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.KEYBOARD_BACKLIGHT_UP);
                }
                return true;
            case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE:
                // TODO: Add logic
                if (!down) {
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.KEYBOARD_BACKLIGHT_TOGGLE);
                }
                return true;
            case KeyEvent.KEYCODE_VOLUME_UP:
            case KeyEvent.KEYCODE_VOLUME_DOWN:
            case KeyEvent.KEYCODE_VOLUME_MUTE:
                if (mUseTvRouting || mHandleVolumeKeysInWM) {
                    // On TVs or when the configuration is enabled, volume keys never
                    // go to the foreground app.
                    dispatchDirectAudioEvent(event);
                    return true;
                }

                // If the device is in VR mode and keys are "internal" (e.g. on the side of the
                // device), then drop the volume keys and don't forward it to the
                // application/dispatch the audio event.
                if (mDefaultDisplayPolicy.isPersistentVrModeEnabled()) {
                    final InputDevice d = event.getDevice();
                    if (d != null && !d.isExternal()) {
                        return true;
                    }
                }
                break;
            case KeyEvent.KEYCODE_TAB:
                if (firstDown && !keyguardOn && isUserSetupComplete()) {
                    if (event.isMetaPressed()) {
                        showRecentApps(false);
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.RECENT_APPS);
                        return true;
                    } else if (mRecentAppsHeldModifiers == 0) {
                        final int shiftlessModifiers =
                                event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
                        if (KeyEvent.metaStateHasModifiers(
                                shiftlessModifiers, KeyEvent.META_ALT_ON)) {
                            mRecentAppsHeldModifiers = shiftlessModifiers;
                            showRecentApps(true);
                            logKeyboardSystemsEvent(event, KeyboardLogEvent.RECENT_APPS);
                            return true;
                        }
                    }
                }
                break;
            case KeyEvent.KEYCODE_ALL_APPS:
                if (!down) {
                    mHandler.removeMessages(MSG_HANDLE_ALL_APPS);
                    Message msg = mHandler.obtainMessage(MSG_HANDLE_ALL_APPS);
                    msg.setAsynchronous(true);
                    msg.sendToTarget();
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.ALL_APPS);
                }
                return true;
            case KeyEvent.KEYCODE_NOTIFICATION:
                if (!down) {
                    toggleNotificationPanel();
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL);
                }
                return true;
            case KeyEvent.KEYCODE_SEARCH:
                if (firstDown && !keyguardOn) {
                    switch (mSearchKeyBehavior) {
                        case SEARCH_BEHAVIOR_TARGET_ACTIVITY: {
                            launchTargetSearchActivity();
                            logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_SEARCH);
                            return true;
                        }
                        case SEARCH_BEHAVIOR_DEFAULT_SEARCH:
                        default:
                            break;
                    }
                }
                break;
            case KeyEvent.KEYCODE_LANGUAGE_SWITCH:
                if (firstDown) {
                    int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
                    sendSwitchKeyboardLayout(event, focusedToken, direction);
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.LANGUAGE_SWITCH);
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_META_LEFT:
            case KeyEvent.KEYCODE_META_RIGHT:
                if (down) {
                    if (event.isAltPressed()) {
                        mPendingCapsLockToggle = true;
                        mPendingMetaAction = false;
                    } else {
                        mPendingCapsLockToggle = false;
                        mPendingMetaAction = true;
                    }
                } else {
                    // Toggle Caps Lock on META-ALT.
                    if (mPendingCapsLockToggle) {
                        mInputManagerInternal.toggleCapsLock(event.getDeviceId());
                        mPendingCapsLockToggle = false;
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_CAPS_LOCK);
                    } else if (mPendingMetaAction) {
                        if (!canceled) {
                            launchAllAppsViaA11y();
                            logKeyboardSystemsEvent(event, KeyboardLogEvent.ACCESSIBILITY_ALL_APPS);
                        }
                        mPendingMetaAction = false;
                    }
                }
                return true;
            case KeyEvent.KEYCODE_ALT_LEFT:
            case KeyEvent.KEYCODE_ALT_RIGHT:
                if (down) {
                    if (event.isMetaPressed()) {
                        mPendingCapsLockToggle = true;
                        mPendingMetaAction = false;
                    } else {
                        mPendingCapsLockToggle = false;
                    }
                } else {
                    // hide recent if triggered by ALT-TAB.
                    if (mRecentAppsHeldModifiers != 0
                            && (metaState & mRecentAppsHeldModifiers) == 0) {
                        mRecentAppsHeldModifiers = 0;
                        hideRecentApps(true, false);
                        return true;
                    }

                    // Toggle Caps Lock on META-ALT.
                    if (mPendingCapsLockToggle) {
                        mInputManagerInternal.toggleCapsLock(event.getDeviceId());
                        mPendingCapsLockToggle = false;
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_CAPS_LOCK);
                        return true;
                    }
                }
                break;
            case KeyEvent.KEYCODE_CAPS_LOCK:
                if (!down) {
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_CAPS_LOCK);
                }
                break;
            case KeyEvent.KEYCODE_STYLUS_BUTTON_PRIMARY:
            case KeyEvent.KEYCODE_STYLUS_BUTTON_SECONDARY:
            case KeyEvent.KEYCODE_STYLUS_BUTTON_TERTIARY:
            case KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL:
                Slog.wtf(TAG, "KEYCODE_STYLUS_BUTTON_* should be handled in"
                        + " interceptKeyBeforeQueueing");
                return true;
            case KeyEvent.KEYCODE_SETTINGS:
                if (mShortPressOnSettingsBehavior == SHORT_PRESS_SETTINGS_NOTIFICATION_PANEL) {
                    if (!down) {
                        toggleNotificationPanel();
                        logKeyboardSystemsEvent(event, KeyboardLogEvent.TOGGLE_NOTIFICATION_PANEL);
                    }
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_STEM_PRIMARY:
                if (prepareToSendSystemKeyToApplication(focusedToken, event)) {
                    // Send to app.
                    return false;
                } else {
                    // Intercepted.
                    sendSystemKeyToStatusBarAsync(event);
                    return true;
                }
        }
        if (isValidGlobalKey(keyCode)
                && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
            return true;
        }

        // Reserve all the META modifier combos for system behavior
        return (metaState & KeyEvent.META_META_ON) != 0;
    }

    /**
     * In this function, we check whether a system key should be sent to the application. We also
     * detect the key gesture on this key, even if the key will be sent to the app. The gesture
     * action, if any, will not be executed immediately. It will be queued and execute only after
     * the application tells us that it didn't handle this key.
     *
     * @return true if this key should be sent to the application. This also means that the target
     *     application has the necessary permissions to receive this key. Return false otherwise.
     */
    private boolean prepareToSendSystemKeyToApplication(IBinder focusedToken, KeyEvent event) {
        final int keyCode = event.getKeyCode();
        if (!event.isSystem()) {
            Log.wtf(
                    TAG,
                    "Illegal keycode provided to prepareToSendSystemKeyToApplication: "
                            + KeyEvent.keyCodeToString(keyCode));
            return false;
        }
        final boolean isDown = event.getAction() == KeyEvent.ACTION_DOWN;
        if (isDown && event.getRepeatCount() == 0) {
            // This happens at the initial DOWN event. Check focused window permission now.
            final KeyInterceptionInfo info =
                    mWindowManagerInternal.getKeyInterceptionInfoFromToken(focusedToken);
            if (info != null
                    && mButtonOverridePermissionChecker.canAppOverrideSystemKey(
                            mContext, info.windowOwnerUid)) {
                // Focused window has the permission. Pass the event to it.
                return true;
            } else {
                // Focused window doesn't have the permission. Intercept the event.
                // If the initial DOWN event is intercepted, follow-up events will be intercepted
                // too. So we know the gesture won't be handled by app, and can handle the gesture
                // in system.
                setDeferredKeyActionsExecutableAsync(keyCode, event.getDownTime());
                return false;
            }
        } else {
            // This happens after the initial DOWN event. We will just reuse the initial decision.
            // I.e., if the initial DOWN event was dispatched, follow-up events should be
            // dispatched. Otherwise, follow-up events should be consumed.
            final Set<Integer> consumedKeys = mConsumedKeysForDevice.get(event.getDeviceId());
            final boolean wasConsumed = consumedKeys != null && consumedKeys.contains(keyCode);
            return !wasConsumed;
        }
    }

    private void setDeferredKeyActionsExecutableAsync(int keyCode, long downTime) {
        Message msg = Message.obtain(mHandler, MSG_SET_DEFERRED_KEY_ACTIONS_EXECUTABLE);
        msg.arg1 = keyCode;
        msg.obj = downTime;
        msg.setAsynchronous(true);
        msg.sendToTarget();
    }

    @SuppressLint("MissingPermission")
    private void injectBackGesture(long downtime) {
        // Create and inject down event
        KeyEvent downEvent = new KeyEvent(downtime, downtime, KeyEvent.ACTION_DOWN,
                KeyEvent.KEYCODE_BACK, 0 /* repeat */, 0 /* metaState */,
                KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
                KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
                InputDevice.SOURCE_KEYBOARD);
        mInputManager.injectInputEvent(downEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);


        // Create and inject up event
        KeyEvent upEvent = KeyEvent.changeAction(downEvent, KeyEvent.ACTION_UP);
        mInputManager.injectInputEvent(upEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);

        downEvent.recycle();
        upEvent.recycle();
    }

    private boolean handleHomeShortcuts(IBinder focusedToken, KeyEvent event) {
        // First we always handle the home key here, so applications
        // can never break it, although if keyguard is on, we do let
        // it handle it, because that gives us the correct 5 second
        // timeout.
        DisplayHomeButtonHandler handler = mDisplayHomeButtonHandlers.get(event.getDisplayId());
        if (handler == null) {
            handler = new DisplayHomeButtonHandler(event.getDisplayId());
            mDisplayHomeButtonHandlers.put(event.getDisplayId(), handler);
        }
        return handler.handleHomeButton(focusedToken, event);
    }

    private void toggleMicrophoneMuteFromKey() {
        if (mSensorPrivacyManager.supportsSensorToggle(
                SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE,
                SensorPrivacyManager.Sensors.MICROPHONE)) {
            boolean isEnabled = mSensorPrivacyManager.isSensorPrivacyEnabled(
                    SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE,
                    SensorPrivacyManager.Sensors.MICROPHONE);

            mSensorPrivacyManager.setSensorPrivacy(SensorPrivacyManager.Sensors.MICROPHONE,
                    !isEnabled);

            int toastTextResId;
            if (isEnabled) {
                toastTextResId = R.string.mic_access_on_toast;
            } else {
                toastTextResId = R.string.mic_access_off_toast;
            }

            Toast.makeText(
                mContext,
                UiThread.get().getLooper(),
                mContext.getString(toastTextResId),
                Toast.LENGTH_SHORT)
                .show();
        }
    }

    /**
     * TV only: recognizes a remote control gesture for capturing a bug report.
     */
    private void interceptBugreportGestureTv() {
        mHandler.removeMessages(MSG_BUGREPORT_TV);
        // The bugreport capture chord is a long press on DPAD CENTER and BACK simultaneously.
        Message msg = Message.obtain(mHandler, MSG_BUGREPORT_TV);
        msg.setAsynchronous(true);
        mHandler.sendMessageDelayed(msg, BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS);
    }

    private void cancelBugreportGestureTv() {
        mHandler.removeMessages(MSG_BUGREPORT_TV);
    }

    /**
     * TV only: recognizes a remote control gesture as Accessibility shortcut.
     * Shortcut: Long press (BACK + DPAD_DOWN)
     */
    private void interceptAccessibilityGestureTv() {
        mHandler.removeMessages(MSG_ACCESSIBILITY_TV);
        Message msg = Message.obtain(mHandler, MSG_ACCESSIBILITY_TV);
        msg.setAsynchronous(true);
        mHandler.sendMessageDelayed(msg, getAccessibilityShortcutTimeout());
    }
    private void cancelAccessibilityGestureTv() {
        mHandler.removeMessages(MSG_ACCESSIBILITY_TV);
    }

    private void requestBugreportForTv() {
        try {
            if (!ActivityManager.getService().launchBugReportHandlerApp()) {
                ActivityManager.getService().requestInteractiveBugReport();
            }
        } catch (RemoteException e) {
            Slog.e(TAG, "Error taking bugreport", e);
        }
    }

    // TODO(b/117479243): handle it in InputPolicy
    /** {@inheritDoc} */
    @Override
    public KeyEvent dispatchUnhandledKey(IBinder focusedToken, KeyEvent event, int policyFlags) {
        // Note: This method is only called if the initial down was unhandled.
        if (DEBUG_INPUT) {
            final KeyInterceptionInfo info =
                    mWindowManagerInternal.getKeyInterceptionInfoFromToken(focusedToken);
            final String title = info == null ? "<unknown>" : info.windowTitle;
            Slog.d(TAG, "Unhandled key: inputToken=" + focusedToken
                    + ", title=" + title
                    + ", action=" + event.getAction()
                    + ", flags=" + event.getFlags()
                    + ", keyCode=" + event.getKeyCode()
                    + ", scanCode=" + event.getScanCode()
                    + ", metaState=" + event.getMetaState()
                    + ", repeatCount=" + event.getRepeatCount()
                    + ", policyFlags=" + policyFlags);
        }

        if (interceptUnhandledKey(event, focusedToken)) {
            return null;
        }

        KeyEvent fallbackEvent = null;
        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
            final KeyCharacterMap kcm = event.getKeyCharacterMap();
            final int keyCode = event.getKeyCode();
            final int metaState = event.getMetaState();
            final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
                    && event.getRepeatCount() == 0;

            // Check for fallback actions specified by the key character map.
            final FallbackAction fallbackAction;
            if (initialDown) {
                fallbackAction = kcm.getFallbackAction(keyCode, metaState);
            } else {
                fallbackAction = mFallbackActions.get(keyCode);
            }

            if (fallbackAction != null) {
                if (DEBUG_INPUT) {
                    Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode
                            + " metaState=" + Integer.toHexString(fallbackAction.metaState));
                }

                final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
                fallbackEvent = KeyEvent.obtain(
                        event.getDownTime(), event.getEventTime(),
                        event.getAction(), fallbackAction.keyCode,
                        event.getRepeatCount(), fallbackAction.metaState,
                        event.getDeviceId(), event.getScanCode(),
                        flags, event.getSource(), event.getDisplayId(), null);

                if (!interceptFallback(focusedToken, fallbackEvent, policyFlags)) {
                    fallbackEvent.recycle();
                    fallbackEvent = null;
                }

                if (initialDown) {
                    mFallbackActions.put(keyCode, fallbackAction);
                } else if (event.getAction() == KeyEvent.ACTION_UP) {
                    mFallbackActions.remove(keyCode);
                    fallbackAction.recycle();
                }
            }
        }

        if (DEBUG_INPUT) {
            if (fallbackEvent == null) {
                Slog.d(TAG, "No fallback.");
            } else {
                Slog.d(TAG, "Performing fallback: " + fallbackEvent);
            }
        }
        return fallbackEvent;
    }

    private boolean interceptUnhandledKey(KeyEvent event, IBinder focusedToken) {
        final int keyCode = event.getKeyCode();
        final int repeatCount = event.getRepeatCount();
        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
        final int metaState = event.getModifiers();

        switch(keyCode) {
            case KeyEvent.KEYCODE_SPACE:
                if (down && repeatCount == 0) {
                    // Handle keyboard layout switching. (CTRL + SPACE)
                    if (KeyEvent.metaStateHasModifiers(metaState & ~KeyEvent.META_SHIFT_MASK,
                            KeyEvent.META_CTRL_ON)) {
                        int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
                        sendSwitchKeyboardLayout(event, focusedToken, direction);
                        return true;
                    }
                }
                break;
            case KeyEvent.KEYCODE_Z:
                if (down && KeyEvent.metaStateHasModifiers(metaState,
                        KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON)) {
                    // Intercept the Accessibility keychord (CTRL + ALT + Z) for keyboard users.
                    if (mAccessibilityShortcutController
                            .isAccessibilityShortcutAvailable(isKeyguardLocked())) {
                        mHandler.sendMessage(mHandler.obtainMessage(MSG_ACCESSIBILITY_SHORTCUT));
                        return true;
                    }
                }
                break;
            case KeyEvent.KEYCODE_SYSRQ:
                if (down && repeatCount == 0) {
                    interceptScreenshotChord(SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/);
                }
                return true;
            case KeyEvent.KEYCODE_ESCAPE:
                if (down
                        && KeyEvent.metaStateHasNoModifiers(metaState)
                        && repeatCount == 0) {
                    mContext.closeSystemDialogs();
                }
                return true;
            case KeyEvent.KEYCODE_STEM_PRIMARY:
                handleUnhandledSystemKey(event);
                sendSystemKeyToStatusBarAsync(event);
                return true;
        }

        return false;
    }

    /**
     * Called when a system key was sent to application and was unhandled. We will execute any
     * queued actions associated with this key code at this point.
     */
    private void handleUnhandledSystemKey(KeyEvent event) {
        if (!event.isSystem()) {
            Log.wtf(
                    TAG,
                    "Illegal keycode provided to handleUnhandledSystemKey: "
                            + KeyEvent.keyCodeToString(event.getKeyCode()));
            return;
        }
        if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
            // If the initial DOWN event is unhandled by app, follow-up events will also be
            // unhandled by app. So we can handle the key event in system.
            setDeferredKeyActionsExecutableAsync(event.getKeyCode(), event.getDownTime());
        }
    }

    private void sendSwitchKeyboardLayout(@NonNull KeyEvent event,
            @Nullable IBinder focusedToken, int direction) {
        SwitchKeyboardLayoutMessageObject object =
                new SwitchKeyboardLayoutMessageObject(event, focusedToken, direction);
        mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, object).sendToTarget();
    }

    private void handleSwitchKeyboardLayout(@NonNull KeyEvent event, int direction,
            IBinder focusedToken) {
        if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI)) {
            IBinder targetWindowToken =
                    mWindowManagerInternal.getTargetWindowTokenFromInputToken(focusedToken);
            InputMethodManagerInternal.get().onSwitchKeyboardLayoutShortcut(direction,
                    event.getDisplayId(), targetWindowToken);
        } else {
            mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
        }
    }

    private boolean interceptFallback(IBinder focusedToken, KeyEvent fallbackEvent,
            int policyFlags) {
        int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
        if ((actions & ACTION_PASS_TO_USER) != 0) {
            long delayMillis = interceptKeyBeforeDispatching(
                    focusedToken, fallbackEvent, policyFlags);
            if (delayMillis == 0 && !interceptUnhandledKey(fallbackEvent, focusedToken)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void setTopFocusedDisplay(int displayId) {
        mTopFocusedDisplayId = displayId;
    }

    @Override
    public void registerDisplayFoldListener(IDisplayFoldListener listener) {
        if (mDisplayFoldController != null) {
            mDisplayFoldController.registerDisplayFoldListener(listener);
        }
    }

    @Override
    public void unregisterDisplayFoldListener(IDisplayFoldListener listener) {
        if (mDisplayFoldController != null) {
            mDisplayFoldController.unregisterDisplayFoldListener(listener);
        }
    }

    @Override
    public void setOverrideFoldedArea(Rect area) {
        if (mDisplayFoldController != null) {
            mDisplayFoldController.setOverrideFoldedArea(area);
        }
    }

    @Override
    public Rect getFoldedArea() {
        if (mDisplayFoldController != null) {
            return mDisplayFoldController.getFoldedArea();
        }
        return new Rect();
    }

    @Override
    public void onDefaultDisplayFocusChangedLw(WindowState newFocus) {
        if (mDisplayFoldController != null) {
            mDisplayFoldController.onDefaultDisplayFocusChanged(
                    newFocus != null ? newFocus.getOwningPackage() : null);
        }
    }

    @Override
    public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
            throws RemoteException {
        synchronized (mLock) {
            mModifierShortcutManager.registerShortcutKey(shortcutCode, shortcutService);
        }
    }

    @Override
    public void onKeyguardOccludedChangedLw(boolean occluded) {
        if (mKeyguardDelegate != null) {
            mPendingKeyguardOccluded = occluded;
            mKeyguardOccludedChanged = true;
        }
    }

    @Override
    public int applyKeyguardOcclusionChange() {
        if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded commit occluded="
                + mPendingKeyguardOccluded + " changed=" + mKeyguardOccludedChanged);

        // TODO(b/276433230): Explicitly save before/after for occlude state in each
        // Transition so we don't need to update SysUI every time.
        if (setKeyguardOccludedLw(mPendingKeyguardOccluded)) {
            return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER;
        } else {
            return 0;
        }
    }

    /**
     * Called when keyguard related app transition starts, or cancelled.
     *
     * @param startKeyguardExitAnimation Trigger IKeyguardService#startKeyguardExitAnimation to
     *                                  start keyguard exit animation.
     * @param notifyOccluded Trigger IKeyguardService#setOccluded binder call to notify whether
     *                      the top activity can occlude the keyguard or not.
     *
     * @return Whether the flags have changed and we have to redo the layout.
     */
    private int handleTransitionForKeyguardLw(boolean startKeyguardExitAnimation,
            boolean notifyOccluded) {
        int redoLayout = 0;
        if (notifyOccluded) {
            redoLayout = applyKeyguardOcclusionChange();
        }
        if (startKeyguardExitAnimation) {
            if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation");
            startKeyguardExitAnimation(SystemClock.uptimeMillis());
        }
        return redoLayout;
    }

    // There are several different flavors of "assistant" that can be launched from
    // various parts of the UI.

    /** Asks the status bar to startAssist(), usually a full "assistant" interface */
    private void launchAssistAction(String hint, int deviceId, long eventTime,
            int invocationType) {
        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
        if (!isUserSetupComplete()) {
            // Disable opening assist window during setup
            return;
        }

        // Add Intent Extra data.
        Bundle args = null;
        args = new Bundle();
        if (deviceId != INVALID_INPUT_DEVICE_ID) {
            args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
        }
        if (hint != null) {
            args.putBoolean(hint, true);
        }
        args.putLong(Intent.EXTRA_TIME, eventTime);
        args.putInt(AssistUtils.INVOCATION_TYPE_KEY, invocationType);

        SearchManager searchManager = mContext.getSystemService(SearchManager.class);
        if (searchManager != null) {
            searchManager.launchAssist(args);
        } else {
            // Fallback to status bar if search manager doesn't exist (e.g. on wear).
            StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
            if (statusBar != null) {
                statusBar.startAssist(args);
            }
        }
    }

    /**
     * Launches ACTION_VOICE_ASSIST_RETAIL if in retail mode, or ACTION_VOICE_ASSIST otherwise
     * Does nothing on keyguard except for watches. Delegates it to keyguard if present on watch.
     */
    private void launchVoiceAssist(boolean allowDuringSetup) {
        final boolean keyguardActive =
                mKeyguardDelegate != null && mKeyguardDelegate.isShowing();
        if (!keyguardActive) {
            startActivityAsUser(
                    new Intent(Intent.ACTION_VOICE_ASSIST),
                    /* bundle= */ null,
                    UserHandle.CURRENT_OR_SELF,
                    allowDuringSetup);
        } else {
            mKeyguardDelegate.dismissKeyguardToLaunch(new Intent(Intent.ACTION_VOICE_ASSIST));
        }
    }

    private boolean isInRetailMode() {
        return Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.DEVICE_DEMO_MODE, 0) == 1;
    }

    private void startActivityAsUser(Intent intent, UserHandle handle) {
        startActivityAsUser(intent, null, handle);
    }

    private void startActivityAsUser(Intent intent, Bundle bundle, UserHandle handle) {
        startActivityAsUser(intent, bundle, handle, false /* allowDuringSetup */);
    }

    private void startActivityAsUser(Intent intent, Bundle bundle, UserHandle handle,
            boolean allowDuringSetup) {
        if (allowDuringSetup || isUserSetupComplete()) {
            mContext.startActivityAsUser(intent, bundle, handle);
        } else {
            Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent);
        }
    }

    private void preloadRecentApps() {
        mPreloadedRecentApps = true;
        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
        if (statusbar != null) {
            statusbar.preloadRecentApps();
        }
    }

    private void cancelPreloadRecentApps() {
        if (mPreloadedRecentApps) {
            mPreloadedRecentApps = false;
            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
            if (statusbar != null) {
                statusbar.cancelPreloadRecentApps();
            }
        }
    }

    private void toggleTaskbar() {
        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
        if (statusbar != null) {
            statusbar.toggleTaskbar();
        }
    }

    private void toggleRecentApps() {
        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
        if (statusbar != null) {
            statusbar.toggleRecentApps();
        }
    }

    @Override
    public void showRecentApps() {
        mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
        mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS).sendToTarget();
    }

    private void showRecentApps(boolean triggeredFromAltTab) {
        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
        if (statusbar != null) {
            statusbar.showRecentApps(triggeredFromAltTab);
        }
    }

    private void toggleKeyboardShortcutsMenu(int deviceId) {
        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
        if (statusbar != null) {
            statusbar.toggleKeyboardShortcutsMenu(deviceId);
        }
    }

    private void dismissKeyboardShortcutsMenu() {
        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
        if (statusbar != null) {
            statusbar.dismissKeyboardShortcutsMenu();
        }
    }

    private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
        if (statusbar != null) {
            statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
        }
    }

    private void enterStageSplitFromRunningApp(boolean leftOrTop) {
        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
        if (statusbar != null) {
            statusbar.enterStageSplitFromRunningApp(leftOrTop);
        }
    }

    void launchHomeFromHotKey(int displayId) {
        launchHomeFromHotKey(displayId, true /* awakenFromDreams */, true /*respectKeyguard*/);
    }

    /**
     * A home key -> launch home action was detected.  Take the appropriate action
     * given the situation with the keyguard.
     */
    void launchHomeFromHotKey(int displayId, final boolean awakenFromDreams,
            final boolean respectKeyguard) {
        if (respectKeyguard) {
            if (isKeyguardShowingAndNotOccluded()) {
                // don't launch home if keyguard showing
                return;
            }

            if (!isKeyguardOccluded() && mKeyguardDelegate.isInputRestricted()) {
                // when in keyguard restricted mode, must first verify unlock
                // before launching home
                mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
                    @Override
                    public void onKeyguardExitResult(boolean success) {
                        if (success) {
                            final long origId = Binder.clearCallingIdentity();
                            try {
                                startDockOrHome(displayId, true /*fromHomeKey*/, awakenFromDreams);
                            } finally {
                                Binder.restoreCallingIdentity(origId);
                            }
                        }
                    }
                });
                return;
            }
        }

        // no keyguard stuff to worry about, just launch home!
        if (mRecentsVisible) {
            try {
                ActivityManager.getService().stopAppSwitches();
            } catch (RemoteException e) {}

            // Hide Recents and notify it to launch Home
            if (awakenFromDreams) {
                awakenDreams();
            }
            hideRecentApps(false, true);
        } else {
            // Otherwise, just launch Home
            startDockOrHome(displayId, true /*fromHomeKey*/, awakenFromDreams);
        }
    }

    @Override
    public void setRecentsVisibilityLw(boolean visible) {
        mRecentsVisible = visible;
    }

    @Override
    public void setPipVisibilityLw(boolean visible) {
        mPictureInPictureVisible = visible;
    }

    @Override
    public void setNavBarVirtualKeyHapticFeedbackEnabledLw(boolean enabled) {
        mNavBarVirtualKeyHapticFeedbackEnabled = enabled;
    }

    /**
     * Updates the occluded state of the Keyguard immediately via
     * {@link com.android.internal.policy.IKeyguardService}.
     *
     * @param isOccluded Whether the Keyguard is occluded by another window.
     * @return Whether the flags have changed and we have to redo the layout.
     */
    private boolean setKeyguardOccludedLw(boolean isOccluded) {
        if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded);
        mKeyguardOccludedChanged = false;
        mPendingKeyguardOccluded = isOccluded;
        mKeyguardDelegate.setOccluded(isOccluded, true /* notify */);
        return mKeyguardDelegate.isShowing();
    }

    /** {@inheritDoc} */
    @Override
    public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
        // lid changed state
        final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
        if (newLidState == mDefaultDisplayPolicy.getLidState()) {
            return;
        }

        mDefaultDisplayPolicy.setLidState(newLidState);
        applyLidSwitchState();
        updateRotation(true);

        if (lidOpen) {
            wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
                    PowerManager.WAKE_REASON_LID, "android.policy:LID");
        } else if (getLidBehavior() != LID_BEHAVIOR_SLEEP) {
            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
        }
    }

    @Override
    public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
        int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
        if (mCameraLensCoverState == lensCoverState) {
            return;
        }
        if (!mContext.getResources().getBoolean(
                R.bool.config_launchCameraOnCameraLensCoverToggle)) {
            return;
        }
        if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
                lensCoverState == CAMERA_LENS_UNCOVERED) {
            Intent intent;
            final boolean keyguardActive = mKeyguardDelegate == null ? false :
                    mKeyguardDelegate.isShowing();
            if (keyguardActive) {
                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
            } else {
                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
            }
            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
                    PowerManager.WAKE_REASON_CAMERA_LAUNCH, "android.policy:CAMERA_COVER");
            startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
        }
        mCameraLensCoverState = lensCoverState;
    }

    void initializeHdmiState() {
        final int oldMask = StrictMode.allowThreadDiskReadsMask();
        try {
            initializeHdmiStateInternal();
        } finally {
            StrictMode.setThreadPolicyMask(oldMask);
        }
    }

    void initializeHdmiStateInternal() {
        boolean plugged = false;
        // watch for HDMI plug messages if the hdmi switch exists
        if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
            mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");

            final String filename = "/sys/class/switch/hdmi/state";
            FileReader reader = null;
            try {
                reader = new FileReader(filename);
                char[] buf = new char[15];
                int n = reader.read(buf);
                if (n > 1) {
                    plugged = 0 != Integer.parseInt(new String(buf, 0, n - 1));
                }
            } catch (IOException ex) {
                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
            } catch (NumberFormatException ex) {
                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
            } finally {
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException ex) {
                    }
                }
            }
        } else {
            final List<ExtconUEventObserver.ExtconInfo> extcons =
                    ExtconUEventObserver.ExtconInfo.getExtconInfoForTypes(
                            new String[] {ExtconUEventObserver.ExtconInfo.EXTCON_HDMI});
            if (!extcons.isEmpty()) {
                // TODO: handle more than one HDMI
                HdmiVideoExtconUEventObserver observer = new HdmiVideoExtconUEventObserver();
                plugged = observer.init(extcons.get(0));
                mHDMIObserver = observer;
            } else if (localLOGV) {
                Slog.v(TAG, "Not observing HDMI plug state because HDMI was not found.");
            }
        }

        // This dance forces the code in setHdmiPlugged to run.
        // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
        mDefaultDisplayPolicy.setHdmiPlugged(plugged, true /* force */);
    }

    // TODO(b/117479243): handle it in InputPolicy
    /** {@inheritDoc} */
    @Override
    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
        final int keyCode = event.getKeyCode();
        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
        boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
                || event.isWakeKey();

        if (!mSystemBooted) {
            // If we have not yet booted, don't let key events do anything.
            // Exception: Wake and power key events are forwarded to PowerManager to allow it to
            // wake from quiescent mode during boot. On these key events we also explicitly turn on
            // the connected TV and switch HDMI input if we're a HDMI playback device.
            boolean shouldTurnOnTv = false;
            if (down && (keyCode == KeyEvent.KEYCODE_POWER
                    || keyCode == KeyEvent.KEYCODE_TV_POWER)) {
                wakeUpFromPowerKey(event.getDownTime());
                shouldTurnOnTv = true;
            } else if (down && (isWakeKey || keyCode == KeyEvent.KEYCODE_WAKEUP)
                    && isWakeKeyWhenScreenOff(keyCode)) {
                wakeUpFromWakeKey(event);
                shouldTurnOnTv = true;
            }
            if (shouldTurnOnTv) {
                final HdmiControl hdmiControl = getHdmiControl();
                if (hdmiControl != null) {
                    hdmiControl.turnOnTv();
                }
            }
            return 0;
        }

        final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
        final boolean canceled = event.isCanceled();
        final int displayId = event.getDisplayId();
        final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;

        if (DEBUG_INPUT) {
            // If screen is off then we treat the case where the keyguard is open but hidden
            // the same as if it were open and in front.
            // This will prevent any keys other than the power button from waking the screen
            // when the keyguard is hidden by another activity.
            final boolean keyguardActive = (mKeyguardDelegate != null
                    && (interactive ? isKeyguardShowingAndNotOccluded() :
                    mKeyguardDelegate.isShowing()));
            Log.d(TAG, "interceptKeyTq keycode=" + keyCode
                    + " interactive=" + interactive + " keyguardActive=" + keyguardActive
                    + " policyFlags=" + Integer.toHexString(policyFlags));
        }

        // Basic policy based on interactive state.
        int result;
        if (interactive || (isInjected && !isWakeKey)) {
            // When the device is interactive or the key is injected pass the
            // key to the application.
            result = ACTION_PASS_TO_USER;
            isWakeKey = false;

            if (interactive) {
                // If the screen is awake, but the button pressed was the one that woke the device
                // then don't pass it to the application
                if (keyCode == mPendingWakeKey && !down) {
                    result = 0;
                }
                // Reset the pending key
                mPendingWakeKey = PENDING_KEY_NULL;
            }
        } else if (shouldDispatchInputWhenNonInteractive(displayId, keyCode)) {
            // If we're currently dozing with the screen on and the keyguard showing, pass the key
            // to the application but preserve its wake key status to make sure we still move
            // from dozing to fully interactive if we would normally go from off to fully
            // interactive.
            result = ACTION_PASS_TO_USER;
            // Since we're dispatching the input, reset the pending key
            mPendingWakeKey = PENDING_KEY_NULL;
        } else {
            // When the screen is off and the key is not injected, determine whether
            // to wake the device but don't pass the key to the application.
            result = 0;
            if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
                isWakeKey = false;
            }
            // Cache the wake key on down event so we can also avoid sending the up event to the app
            if (isWakeKey && down) {
                mPendingWakeKey = keyCode;
            }
        }

        // If the key would be handled globally, just return the result, don't worry about special
        // key processing.
        if (isValidGlobalKey(keyCode)
                && mGlobalKeyManager.shouldHandleGlobalKey(keyCode)) {
            // Dispatch if global key defined dispatchWhenNonInteractive.
            if (!interactive && isWakeKey && down
                    && mGlobalKeyManager.shouldDispatchFromNonInteractive(keyCode)) {
                mGlobalKeyManager.setBeganFromNonInteractive();
                result = ACTION_PASS_TO_USER;
                // Since we're dispatching the input, reset the pending key
                mPendingWakeKey = PENDING_KEY_NULL;
            }

            if (isWakeKey) {
                wakeUpFromWakeKey(event);
            }
            return result;
        }

        // Alternate TV power to power key for Android TV device.
        final HdmiControlManager hdmiControlManager = getHdmiControlManager();
        if (keyCode == KeyEvent.KEYCODE_TV_POWER && mHasFeatureLeanback
                && (hdmiControlManager == null || !hdmiControlManager.shouldHandleTvPowerKey())) {
            event = KeyEvent.obtain(
                    event.getDownTime(), event.getEventTime(),
                    event.getAction(), KeyEvent.KEYCODE_POWER,
                    event.getRepeatCount(), event.getMetaState(),
                    event.getDeviceId(), event.getScanCode(),
                    event.getFlags(), event.getSource(), event.getDisplayId(), null);
            return interceptKeyBeforeQueueing(event, policyFlags);
        }

        // This could prevent some wrong state in multi-displays environment,
        // the default display may turned off but interactive is true.
        final boolean isDefaultDisplayOn = Display.isOnState(mDefaultDisplay.getState());
        final boolean isDefaultDisplayAwake = mDefaultDisplayPolicy.isAwake();
        final boolean interactiveAndAwake = interactive && isDefaultDisplayAwake;
        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
            handleKeyGesture(event, interactiveAndAwake, isDefaultDisplayOn);
        }

        // Enable haptics if down and virtual key without multiple repetitions. If this is a hard
        // virtual key such as a navigation bar button, only vibrate if flag is enabled.
        final boolean isNavBarVirtKey = ((event.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) != 0);
        boolean useHapticFeedback = down
                && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
                && (!isNavBarVirtKey || mNavBarVirtualKeyHapticFeedbackEnabled)
                && event.getRepeatCount() == 0;

        // Handle special keys.
        switch (keyCode) {
            case KeyEvent.KEYCODE_BACK: {
                logKeyboardSystemsEventOnActionUp(event, KeyboardLogEvent.BACK);
                if (down) {
                    mBackKeyHandled = false;
                } else {
                    if (!hasLongPressOnBackBehavior()) {
                        mBackKeyHandled |= backKeyPress();
                    }
                    // Don't pass back press to app if we've already handled it via long press
                    if (mBackKeyHandled) {
                        result &= ~ACTION_PASS_TO_USER;
                    }
                }
                break;
            }

            case KeyEvent.KEYCODE_VOLUME_DOWN:
            case KeyEvent.KEYCODE_VOLUME_UP:
            case KeyEvent.KEYCODE_VOLUME_MUTE: {
                logKeyboardSystemsEventOnActionDown(event,
                        KeyboardLogEvent.getVolumeEvent(keyCode));
                if (down) {
                    sendSystemKeyToStatusBarAsync(event);

                    NotificationManager nm = getNotificationService();
                    if (nm != null && !mHandleVolumeKeysInWM) {
                        nm.silenceNotificationSound();
                    }

                    TelecomManager telecomManager = getTelecommService();
                    if (telecomManager != null && !mHandleVolumeKeysInWM) {
                        // When {@link #mHandleVolumeKeysInWM} is set, volume key events
                        // should be dispatched to WM.
                        if (telecomManager.isRinging()) {
                            // If an incoming call is ringing, either VOLUME key means
                            // "silence ringer".  We handle these keys here, rather than
                            // in the InCallScreen, to make sure we'll respond to them
                            // even if the InCallScreen hasn't come to the foreground yet.
                            // Look for the DOWN event here, to agree with the "fallback"
                            // behavior in the InCallScreen.
                            Log.i(TAG, "interceptKeyBeforeQueueing:"
                                  + " VOLUME key-down while ringing: Silence ringer!");

                            // Silence the ringer.  (It's safe to call this
                            // even if the ringer has already been silenced.)
                            telecomManager.silenceRinger();

                            // And *don't* pass this key thru to the current activity
                            // (which is probably the InCallScreen.)
                            result &= ~ACTION_PASS_TO_USER;
                            break;
                        }
                    }
                    int audioMode = AudioManager.MODE_NORMAL;
                    try {
                        audioMode = getAudioService().getMode();
                    } catch (Exception e) {
                        Log.e(TAG, "Error getting AudioService in interceptKeyBeforeQueueing.", e);
                    }
                    boolean isInCall = (telecomManager != null && telecomManager.isInCall()) ||
                            audioMode == AudioManager.MODE_IN_COMMUNICATION;
                    if (isInCall && (result & ACTION_PASS_TO_USER) == 0) {
                        // If we are in call but we decided not to pass the key to
                        // the application, just pass it to the session service.
                        MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
                                event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
                        break;
                    }
                }
                if (mUseTvRouting || mHandleVolumeKeysInWM) {
                    // Defer special key handlings to
                    // {@link interceptKeyBeforeDispatching()}.
                    result |= ACTION_PASS_TO_USER;
                } else if ((result & ACTION_PASS_TO_USER) == 0) {
                    // If we aren't passing to the user and no one else
                    // handled it send it to the session manager to
                    // figure out.
                    MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
                            event, AudioManager.USE_DEFAULT_STREAM_TYPE, true);
                }
                break;
            }

            case KeyEvent.KEYCODE_ENDCALL: {
                result &= ~ACTION_PASS_TO_USER;
                if (down) {
                    TelecomManager telecomManager = getTelecommService();
                    boolean hungUp = false;
                    if (telecomManager != null) {
                        hungUp = telecomManager.endCall();
                    }
                    if (interactive && !hungUp) {
                        mEndCallKeyHandled = false;
                        mHandler.postDelayed(mEndCallLongPress,
                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
                    } else {
                        mEndCallKeyHandled = true;
                    }
                } else {
                    if (!mEndCallKeyHandled) {
                        mHandler.removeCallbacks(mEndCallLongPress);
                        if (!canceled) {
                            if ((mEndcallBehavior
                                    & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
                                if (goHome()) {
                                    break;
                                }
                            }
                            if ((mEndcallBehavior
                                    & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
                                sleepDefaultDisplay(event.getEventTime(),
                                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
                                isWakeKey = false;
                            }
                        }
                    }
                }
                break;
            }

            case KeyEvent.KEYCODE_TV_POWER: {
                logKeyboardSystemsEventOnActionUp(event, KeyboardLogEvent.TOGGLE_POWER);
                result &= ~ACTION_PASS_TO_USER;
                isWakeKey = false; // wake-up will be handled separately
                if (down && hdmiControlManager != null) {
                    hdmiControlManager.toggleAndFollowTvPower();
                }
                break;
            }

            case KeyEvent.KEYCODE_POWER: {
                logKeyboardSystemsEventOnActionUp(event, KeyboardLogEvent.TOGGLE_POWER);
                EventLogTags.writeInterceptPower(
                        KeyEvent.actionToString(event.getAction()),
                        mPowerKeyHandled ? 1 : 0,
                        mSingleKeyGestureDetector.getKeyPressCounter(KeyEvent.KEYCODE_POWER));
                // Any activity on the power button stops the accessibility shortcut
                result &= ~ACTION_PASS_TO_USER;
                isWakeKey = false; // wake-up will be handled separately
                if (down) {
                    interceptPowerKeyDown(event, interactiveAndAwake);
                } else {
                    interceptPowerKeyUp(event, canceled);
                }
                break;
            }

            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
                // fall through
            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
                // fall through
            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
                // fall through
            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
                logKeyboardSystemsEventOnActionUp(event, KeyboardLogEvent.SYSTEM_NAVIGATION);
                result &= ~ACTION_PASS_TO_USER;
                interceptSystemNavigationKey(event);
                break;
            }

            case KeyEvent.KEYCODE_SLEEP: {
                logKeyboardSystemsEventOnActionUp(event, KeyboardLogEvent.SLEEP);
                result &= ~ACTION_PASS_TO_USER;
                isWakeKey = false;
                if (!mPowerManager.isInteractive()) {
                    useHapticFeedback = false; // suppress feedback if already non-interactive
                }
                if (down) {
                    sleepPress();
                } else {
                    sleepRelease(event.getEventTime());
                }
                sendSystemKeyToStatusBarAsync(event);
                break;
            }

            case KeyEvent.KEYCODE_SOFT_SLEEP: {
                logKeyboardSystemsEventOnActionUp(event, KeyboardLogEvent.SLEEP);
                result &= ~ACTION_PASS_TO_USER;
                isWakeKey = false;
                if (!down) {
                    mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
                }
                sendSystemKeyToStatusBarAsync(event);
                break;
            }

            case KeyEvent.KEYCODE_WAKEUP: {
                logKeyboardSystemsEventOnActionUp(event, KeyboardLogEvent.WAKEUP);
                result &= ~ACTION_PASS_TO_USER;
                isWakeKey = true;
                break;
            }

            case KeyEvent.KEYCODE_MUTE:
                result &= ~ACTION_PASS_TO_USER;
                if (down && event.getRepeatCount() == 0) {
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.SYSTEM_MUTE);
                    toggleMicrophoneMuteFromKey();
                }
                break;
            case KeyEvent.KEYCODE_MEDIA_PLAY:
            case KeyEvent.KEYCODE_MEDIA_PAUSE:
            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
            case KeyEvent.KEYCODE_HEADSETHOOK:
            case KeyEvent.KEYCODE_MEDIA_STOP:
            case KeyEvent.KEYCODE_MEDIA_NEXT:
            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
            case KeyEvent.KEYCODE_MEDIA_REWIND:
            case KeyEvent.KEYCODE_MEDIA_RECORD:
            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
                logKeyboardSystemsEventOnActionUp(event, KeyboardLogEvent.MEDIA_KEY);
                if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
                    // If the global session is active pass all media keys to it
                    // instead of the active window.
                    result &= ~ACTION_PASS_TO_USER;
                }
                if ((result & ACTION_PASS_TO_USER) == 0) {
                    // Only do this if we would otherwise not pass it to the user. In that
                    // case, the PhoneWindow class will do the same thing, except it will
                    // only do it if the showing app doesn't process the key on its own.
                    // Note that we need to make a copy of the key event here because the
                    // original key event will be recycled when we return.
                    mBroadcastWakeLock.acquire();
                    Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
                            new KeyEvent(event));
                    msg.setAsynchronous(true);
                    msg.sendToTarget();
                }
                break;
            }

            case KeyEvent.KEYCODE_CALL: {
                if (down) {
                    TelecomManager telecomManager = getTelecommService();
                    if (telecomManager != null) {
                        if (telecomManager.isRinging()) {
                            Log.i(TAG, "interceptKeyBeforeQueueing:"
                                  + " CALL key-down while ringing: Answer the call!");
                            telecomManager.acceptRingingCall();

                            // And *don't* pass this key thru to the current activity
                            // (which is presumably the InCallScreen.)
                            result &= ~ACTION_PASS_TO_USER;
                        }
                    }
                }
                break;
            }
            case KeyEvent.KEYCODE_ASSIST: {
                final boolean longPressed = event.getRepeatCount() > 0;
                if (down && !longPressed) {
                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_ASSIST, event.getDeviceId(),
                            0 /* unused */, event.getEventTime() /* eventTime */);
                    msg.setAsynchronous(true);
                    msg.sendToTarget();
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_ASSISTANT);
                }
                result &= ~ACTION_PASS_TO_USER;
                break;
            }
            case KeyEvent.KEYCODE_VOICE_ASSIST: {
                if (!down) {
                    mBroadcastWakeLock.acquire();
                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK);
                    msg.setAsynchronous(true);
                    msg.sendToTarget();
                    logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_VOICE_ASSISTANT);
                }
                result &= ~ACTION_PASS_TO_USER;
                break;
            }
            case KeyEvent.KEYCODE_WINDOW: {
                if (mShortPressOnWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
                    if (mPictureInPictureVisible) {
                        // Consumes the key only if picture-in-picture is visible to show
                        // picture-in-picture control menu. This gives a chance to the foreground
                        // activity to customize PIP key behavior.
                        if (!down) {
                            showPictureInPictureMenu(event);
                        }
                        result &= ~ACTION_PASS_TO_USER;
                    }
                }
                break;
            }
            case KeyEvent.KEYCODE_VIDEO_APP_1:
            case KeyEvent.KEYCODE_VIDEO_APP_2:
            case KeyEvent.KEYCODE_VIDEO_APP_3:
            case KeyEvent.KEYCODE_VIDEO_APP_4:
            case KeyEvent.KEYCODE_VIDEO_APP_5:
            case KeyEvent.KEYCODE_VIDEO_APP_6:
            case KeyEvent.KEYCODE_VIDEO_APP_7:
            case KeyEvent.KEYCODE_VIDEO_APP_8:
            case KeyEvent.KEYCODE_FEATURED_APP_1:
            case KeyEvent.KEYCODE_FEATURED_APP_2:
            case KeyEvent.KEYCODE_FEATURED_APP_3:
            case KeyEvent.KEYCODE_FEATURED_APP_4:
            case KeyEvent.KEYCODE_DEMO_APP_1:
            case KeyEvent.KEYCODE_DEMO_APP_2:
            case KeyEvent.KEYCODE_DEMO_APP_3:
            case KeyEvent.KEYCODE_DEMO_APP_4: {
                // Just drop if keys are not intercepted for direct key.
                result &= ~ACTION_PASS_TO_USER;
                break;
            }
            case KeyEvent.KEYCODE_STYLUS_BUTTON_PRIMARY:
            case KeyEvent.KEYCODE_STYLUS_BUTTON_SECONDARY:
            case KeyEvent.KEYCODE_STYLUS_BUTTON_TERTIARY:
            case KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL: {
                if (mStylusButtonsEnabled) {
                    sendSystemKeyToStatusBarAsync(event);
                }
                result &= ~ACTION_PASS_TO_USER;
                break;
            }
            case KeyEvent.KEYCODE_MACRO_1:
            case KeyEvent.KEYCODE_MACRO_2:
            case KeyEvent.KEYCODE_MACRO_3:
            case KeyEvent.KEYCODE_MACRO_4:
                result &= ~ACTION_PASS_TO_USER;
                break;
        }

        if (useHapticFeedback) {
            performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, false,
                    "Virtual Key - Press");
        }

        if (isWakeKey) {
            wakeUpFromWakeKey(event);
        }

        // If the key event is targeted to a specific display, then the user is interacting with
        // that display. Therefore, try to give focus to the display that the user is interacting
        // with.
        if ((result & ACTION_PASS_TO_USER) != 0 && displayId != INVALID_DISPLAY
                && displayId != mTopFocusedDisplayId) {
            // An event is targeting a non-focused display. Move the display to top so that
            // it can become the focused display to interact with the user.
            // This should be done asynchronously, once the focus logic is fully moved to input
            // from windowmanager. Currently, we need to ensure the setInputWindows completes,
            // which would force the focus event to be queued before the current key event.
            // TODO(b/70668286): post call to 'moveDisplayToTop' to mHandler instead
            Log.i(TAG, "Attempting to move non-focused display " + displayId + " to top "
                    + "because a key is targeting it");
            mWindowManagerFuncs.moveDisplayToTopIfAllowed(displayId);
        }

        return result;
    }

    private void handleKeyGesture(KeyEvent event, boolean interactive, boolean defaultDisplayOn) {
        if (mKeyCombinationManager.interceptKey(event, interactive)) {
            // handled by combo keys manager.
            mSingleKeyGestureDetector.reset();
            return;
        }

        if (event.getKeyCode() == KEYCODE_POWER && event.getAction() == KeyEvent.ACTION_DOWN) {
            mPowerKeyHandled = handleCameraGesture(event, interactive);
            if (mPowerKeyHandled) {
                // handled by camera gesture.
                mSingleKeyGestureDetector.reset();
                return;
            }
        }

        mSingleKeyGestureDetector.interceptKey(event, interactive, defaultDisplayOn);
    }

    // The camera gesture will be detected by GestureLauncherService.
    private boolean handleCameraGesture(KeyEvent event, boolean interactive) {
        // camera gesture.
        if (mGestureLauncherService == null) {
            return false;
        }
        mCameraGestureTriggered = false;
        final MutableBoolean outLaunched = new MutableBoolean(false);
        final boolean intercept =
                mGestureLauncherService.interceptPowerKeyDown(event, interactive, outLaunched);
        if (!outLaunched.value) {
            // If GestureLauncherService intercepted the power key, but didn't launch camera app,
            // we should still return the intercept result. This prevents the single key gesture
            // detector from processing the power key later on.
            return intercept;
        }
        mCameraGestureTriggered = true;
        if (mRequestedOrSleepingDefaultDisplay) {
            mCameraGestureTriggeredDuringGoingToSleep = true;
            // Wake device up early to prevent display doing redundant turning off/on stuff.
            wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromPowerKey,
                    PowerManager.WAKE_REASON_CAMERA_LAUNCH,
                    "android.policy:CAMERA_GESTURE_PREVENT_LOCK");
        }
        return true;
    }

    /**
     * Handle statusbar expansion events.
     * @param event
     */
    private void interceptSystemNavigationKey(KeyEvent event) {
        if (event.getAction() == KeyEvent.ACTION_UP) {
            if (!mAccessibilityManager.isEnabled()
                    || !mAccessibilityManager.sendFingerprintGesture(event.getKeyCode())) {
                if (mSystemNavigationKeysEnabled) {
                    sendSystemKeyToStatusBarAsync(event);
                }
            }
        }
    }

    /**
     * Notify the StatusBar that a system key was pressed.
     */
    private void sendSystemKeyToStatusBar(KeyEvent key) {
        IStatusBarService statusBar = getStatusBarService();
        if (statusBar != null) {
            try {
                statusBar.handleSystemKey(key);
            } catch (RemoteException e) {
                // Oh well.
            }
        }
    }

    /**
     * Notify the StatusBar that a system key was pressed without blocking the current thread.
     */
    private void sendSystemKeyToStatusBarAsync(KeyEvent keyEvent) {
        // Make a copy because the event may be recycled.
        Message message = mHandler.obtainMessage(MSG_SYSTEM_KEY_PRESS, KeyEvent.obtain(keyEvent));
        message.setAsynchronous(true);
        mHandler.sendMessage(message);
    }

    /**
     * Returns true if the key can have global actions attached to it.
     * We reserve all power management keys for the system since they require
     * very careful handling.
     */
    private static boolean isValidGlobalKey(int keyCode) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_POWER:
            case KeyEvent.KEYCODE_WAKEUP:
            case KeyEvent.KEYCODE_SLEEP:
                return false;
            default:
                return true;
        }
    }

    /**
     * When the screen is off we ignore some keys that might otherwise typically
     * be considered wake keys.  We filter them out here.
     *
     * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
     * is always considered a wake key.
     */
    private boolean isWakeKeyWhenScreenOff(int keyCode) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_UP:
            case KeyEvent.KEYCODE_DPAD_DOWN:
            case KeyEvent.KEYCODE_DPAD_LEFT:
            case KeyEvent.KEYCODE_DPAD_RIGHT:
            case KeyEvent.KEYCODE_DPAD_CENTER:
                return mWakeOnDpadKeyPress;

            case KeyEvent.KEYCODE_ASSIST:
                return mWakeOnAssistKeyPress;

            case KeyEvent.KEYCODE_BACK:
                return mWakeOnBackKeyPress;

            case KeyEvent.KEYCODE_STYLUS_BUTTON_PRIMARY:
            case KeyEvent.KEYCODE_STYLUS_BUTTON_SECONDARY:
            case KeyEvent.KEYCODE_STYLUS_BUTTON_TERTIARY:
            case KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL:
                return mStylusButtonsEnabled;
        }

        return true;
    }

    // TODO(b/117479243): handle it in InputPolicy
    /** {@inheritDoc} */
    @Override
    public int interceptMotionBeforeQueueingNonInteractive(int displayId, long whenNanos,
            int policyFlags) {
        if ((policyFlags & FLAG_WAKE) != 0) {
            if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
                    PowerManager.WAKE_REASON_WAKE_MOTION, "android.policy:MOTION")) {
                // Woke up. Pass motion events to user.
                return ACTION_PASS_TO_USER;
            }
        }

        if (shouldDispatchInputWhenNonInteractive(displayId, KEYCODE_UNKNOWN)) {
            return ACTION_PASS_TO_USER;
        }

        // If we have not passed the action up and we are in theater mode without dreaming,
        // there will be no dream to intercept the touch and wake into ambient.  The device should
        // wake up in this case.
        if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
            if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
                    PowerManager.WAKE_REASON_WAKE_MOTION, "android.policy:MOTION")) {
                // Woke up. Pass motion events to user.
                return ACTION_PASS_TO_USER;
            }
        }

        return 0;
    }

    private boolean shouldDispatchInputWhenNonInteractive(int displayId, int keyCode) {
        // Apply the default display policy to unknown displays as well.
        final boolean isDefaultDisplay = displayId == DEFAULT_DISPLAY
                || displayId == INVALID_DISPLAY;
        final Display display = isDefaultDisplay
                ? mDefaultDisplay
                : mDisplayManager.getDisplay(displayId);
        final boolean displayOff = (display == null
                || display.getState() == STATE_OFF);

        if (displayOff) {
            return false;
        }

        // Send events to keyguard while the screen is on and it's showing.
        if (isKeyguardShowingAndNotOccluded()) {
            return true;
        }

        // TODO(b/123372519): Refine when dream can support multi display.
        if (isDefaultDisplay) {
            // Send events to a dozing dream since the dream is in control of the state of the
            // screen.
            IDreamManager dreamManager = getDreamManager();

            try {
                if (dreamManager != null && dreamManager.isDreaming()) {
                    return true;
                }
            } catch (RemoteException e) {
                Slog.e(TAG, "RemoteException when checking if dreaming", e);
            }
        }

        // Otherwise, consume events since the user can't see what is being
        // interacted with.
        return false;
    }

    // pre-condition: event.getKeyCode() is one of KeyEvent.KEYCODE_VOLUME_UP,
    //                                   KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_VOLUME_MUTE
    private void dispatchDirectAudioEvent(KeyEvent event) {
        // When System Audio Mode is off, volume keys received by AVR can be either consumed by AVR
        // or forwarded to the TV. It's up to Amplifier manufacturer’s implementation.
        HdmiControlManager hdmiControlManager = getHdmiControlManager();
        if (null != hdmiControlManager
                && !hdmiControlManager.getSystemAudioMode()
                && shouldCecAudioDeviceForwardVolumeKeysSystemAudioModeOff()) {
            HdmiAudioSystemClient audioSystemClient = hdmiControlManager.getAudioSystemClient();
            if (audioSystemClient != null) {
                audioSystemClient.sendKeyEvent(
                        event.getKeyCode(), event.getAction() == KeyEvent.ACTION_DOWN);
                return;
            }
        }
        try {
            getAudioService().handleVolumeKey(event, mUseTvRouting,
                    mContext.getOpPackageName(), TAG);
        } catch (Exception e) {
            Log.e(TAG, "Error dispatching volume key in handleVolumeKey for event:"
                    + event, e);
        }
    }

    @Nullable
    private HdmiControlManager getHdmiControlManager() {
        if (!mHasFeatureHdmiCec) {
            return null;
        }
        return (HdmiControlManager) mContext.getSystemService(HdmiControlManager.class);
    }

    private boolean shouldCecAudioDeviceForwardVolumeKeysSystemAudioModeOff() {
        return RoSystemProperties.CEC_AUDIO_DEVICE_FORWARD_VOLUME_KEYS_SYSTEM_AUDIO_MODE_OFF;
    }

    void dispatchMediaKeyWithWakeLock(KeyEvent event) {
        if (DEBUG_INPUT) {
            Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
        }

        if (mHavePendingMediaKeyRepeatWithWakeLock) {
            if (DEBUG_INPUT) {
                Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
            }

            mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
            mHavePendingMediaKeyRepeatWithWakeLock = false;
            mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
        }

        dispatchMediaKeyWithWakeLockToAudioService(event);

        if (event.getAction() == KeyEvent.ACTION_DOWN
                && event.getRepeatCount() == 0) {
            mHavePendingMediaKeyRepeatWithWakeLock = true;

            Message msg = mHandler.obtainMessage(
                    MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
            msg.setAsynchronous(true);
            mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
        } else {
            mBroadcastWakeLock.release();
        }
    }

    void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
        mHavePendingMediaKeyRepeatWithWakeLock = false;

        KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
                SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
        if (DEBUG_INPUT) {
            Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
        }

        dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
        mBroadcastWakeLock.release();
    }

    void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
        if (mActivityManagerInternal.isSystemReady()) {
            MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
        }
    }

    void launchVoiceAssistWithWakeLock() {
        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);

        final Intent voiceIntent;
        if (!keyguardOn()) {
            voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
        } else {
            DeviceIdleManager dim = mContext.getSystemService(DeviceIdleManager.class);
            if (dim != null) {
                dim.endIdle("voice-search");
            }
            voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
            voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
        }
        startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
        mBroadcastWakeLock.release();
    }

    BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
                mDefaultDisplayPolicy.setDockMode(intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
                        Intent.EXTRA_DOCK_STATE_UNDOCKED));
            } else {
                try {
                    IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
                            ServiceManager.getService(Context.UI_MODE_SERVICE));
                    mUiMode = uiModeService.getCurrentModeType();
                } catch (RemoteException e) {
                }
            }
            updateRotation(true);
            mDefaultDisplayRotation.updateOrientationListener();
        }
    };

    BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
                // tickle the settings observer: this first ensures that we're
                // observing the relevant settings for the newly-active user,
                // and then updates our own bookkeeping based on the now-
                // current user.
                mSettingsObserver.onChange(false);
                mDefaultDisplayRotation.onUserSwitch();
                mWindowManagerFuncs.onUserSwitched();
            }
        }
    };

    @Override
    public void startedWakingUpGlobal(@WakeReason int reason) {

    }

    @Override
    public void finishedWakingUpGlobal(@WakeReason int reason) {

    }

    @Override
    public void startedGoingToSleepGlobal(@PowerManager.GoToSleepReason int reason) {
        mDeviceGoingToSleep = true;
    }

    @Override
    public void finishedGoingToSleepGlobal(@PowerManager.GoToSleepReason int reason) {
        mDeviceGoingToSleep = false;
    }

    // Called on the PowerManager's Notifier thread.
    @Override
    public void startedGoingToSleep(int displayGroupId,
            @PowerManager.GoToSleepReason int pmSleepReason) {
        if (DEBUG_WAKEUP) {
            Slog.i(TAG, "Started going to sleep... (groupId=" + displayGroupId + " why="
                    + WindowManagerPolicyConstants.offReasonToString(
                            WindowManagerPolicyConstants.translateSleepReasonToOffReason(
                                    pmSleepReason)) + ")");
        }
        if (displayGroupId != Display.DEFAULT_DISPLAY_GROUP) {
            return;
        }

        mRequestedOrSleepingDefaultDisplay = true;

        if (mKeyguardDelegate != null) {
            mKeyguardDelegate.onStartedGoingToSleep(pmSleepReason);
        }
    }

    // Called on the PowerManager's Notifier thread.
    @Override
    public void finishedGoingToSleep(int displayGroupId,
            @PowerManager.GoToSleepReason int pmSleepReason) {
        if (displayGroupId != Display.DEFAULT_DISPLAY_GROUP) {
            return;
        }
        EventLogTags.writeScreenToggled(0);
        if (DEBUG_WAKEUP) {
            Slog.i(TAG, "Finished going to sleep... (groupId=" + displayGroupId + " why="
                    + WindowManagerPolicyConstants.offReasonToString(
                            WindowManagerPolicyConstants.translateSleepReasonToOffReason(
                                    pmSleepReason)) + ")");
        }
        MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);

        mRequestedOrSleepingDefaultDisplay = false;
        mDefaultDisplayPolicy.setAwake(false);

        // We must get this work done here because the power manager will drop
        // the wake lock and let the system suspend once this function returns.
        synchronized (mLock) {
            updateWakeGestureListenerLp();
            updateLockScreenTimeout();
        }
        mDefaultDisplayRotation.updateOrientationListener();

        if (mKeyguardDelegate != null) {
            mKeyguardDelegate.onFinishedGoingToSleep(pmSleepReason,
                    mCameraGestureTriggeredDuringGoingToSleep);
        }
        if (mDisplayFoldController != null) {
            mDisplayFoldController.finishedGoingToSleep();
        }
        mCameraGestureTriggeredDuringGoingToSleep = false;
        mCameraGestureTriggered = false;
    }

    // Called on the PowerManager's Notifier thread.
    @Override
    public void startedWakingUp(int displayGroupId, @WakeReason int pmWakeReason) {
        if (DEBUG_WAKEUP) {
            Slog.i(TAG, "Started waking up... (groupId=" + displayGroupId + " why="
                    + WindowManagerPolicyConstants.onReasonToString(
                    WindowManagerPolicyConstants.translateWakeReasonToOnReason(
                            pmWakeReason)) + ")");
        }
        if (displayGroupId != Display.DEFAULT_DISPLAY_GROUP) {
            return;
        }
        EventLogTags.writeScreenToggled(1);


        mDefaultDisplayPolicy.setAwake(true);

        // Since goToSleep performs these functions synchronously, we must
        // do the same here.  We cannot post this work to a handler because
        // that might cause it to become reordered with respect to what
        // may happen in a future call to goToSleep.
        synchronized (mLock) {
            updateWakeGestureListenerLp();
            updateLockScreenTimeout();
        }
        mDefaultDisplayRotation.updateOrientationListener();

        if (mKeyguardDelegate != null) {
            mKeyguardDelegate.onStartedWakingUp(pmWakeReason, mCameraGestureTriggered);
        }

        mCameraGestureTriggered = false;
    }

    // Called on the PowerManager's Notifier thread.
    @Override
    public void finishedWakingUp(int displayGroupId, @WakeReason int pmWakeReason) {
        if (DEBUG_WAKEUP) {
            Slog.i(TAG, "Finished waking up... (groupId=" + displayGroupId + " why="
                    + WindowManagerPolicyConstants.onReasonToString(
                            WindowManagerPolicyConstants.translateWakeReasonToOnReason(
                                    pmWakeReason)) + ")");
        }
        if (displayGroupId != Display.DEFAULT_DISPLAY_GROUP) {
            return;
        }

        if (mKeyguardDelegate != null) {
            mKeyguardDelegate.onFinishedWakingUp();
        }
        if (mDisplayFoldController != null) {
            mDisplayFoldController.finishedWakingUp();
        }
    }

    private boolean shouldWakeUpWithHomeIntent() {
        if (mWakeUpToLastStateTimeout <= 0) {
            return false;
        }

        final long sleepDurationRealtime =
                mPowerManagerInternal.getLastWakeup().sleepDurationRealtime;
        if (DEBUG_WAKEUP) {
            Log.i(TAG, "shouldWakeUpWithHomeIntent: sleepDurationRealtime= " + sleepDurationRealtime
                    + " mWakeUpToLastStateTimeout= " + mWakeUpToLastStateTimeout);
        }
        return sleepDurationRealtime > mWakeUpToLastStateTimeout;
    }

    private void wakeUpFromPowerKey(long eventTime) {
        if (wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey,
                PowerManager.WAKE_REASON_POWER_BUTTON, "android.policy:POWER")) {
            // Start HOME with "reason" extra if sleeping for more than mWakeUpToLastStateTimeout
            if (shouldWakeUpWithHomeIntent()) {
                startDockOrHome(DEFAULT_DISPLAY, /*fromHomeKey*/ false, /*wakenFromDreams*/ true,
                        PowerManager.wakeReasonToString(PowerManager.WAKE_REASON_POWER_BUTTON));
            }
        }
    }

    private void wakeUpFromWakeKey(KeyEvent event) {
        if (wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey,
                PowerManager.WAKE_REASON_WAKE_KEY, "android.policy:KEY")) {
            // Start HOME with "reason" extra if sleeping for more than mWakeUpToLastStateTimeout
            if (shouldWakeUpWithHomeIntent() && event.getKeyCode() == KEYCODE_HOME) {
                startDockOrHome(DEFAULT_DISPLAY, /*fromHomeKey*/ true, /*wakenFromDreams*/ true,
                        PowerManager.wakeReasonToString(PowerManager.WAKE_REASON_WAKE_KEY));
            }
        }
    }

    private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, @WakeReason int reason,
            String details) {
        final boolean theaterModeEnabled = isTheaterModeEnabled();
        if (!wakeInTheaterMode && theaterModeEnabled) {
            return false;
        }

        mPowerManager.wakeUp(wakeTime, reason, details);
        return true;
    }

    private void finishKeyguardDrawn() {
        if (!mDefaultDisplayPolicy.finishKeyguardDrawn()) {
            return;
        }

        synchronized (mLock) {
            if (mKeyguardDelegate != null) {
                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
            }
        }

        // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
        // as well as enabling the orientation change logic/sensor.
        Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER,
                TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD, INVALID_DISPLAY /* cookie */);
        mWindowManagerInternal.waitForAllWindowsDrawn(mHandler.obtainMessage(
                MSG_WINDOW_MANAGER_DRAWN_COMPLETE, INVALID_DISPLAY, 0),
                WAITING_FOR_DRAWN_TIMEOUT, INVALID_DISPLAY);
    }

    // Called on the DisplayManager's DisplayPowerController thread.
    @Override
    public void screenTurnedOff(int displayId, boolean isSwappingDisplay) {
        if (DEBUG_WAKEUP) Slog.i(TAG, "Display" + displayId + " turned off...");

        if (displayId == DEFAULT_DISPLAY) {
            updateScreenOffSleepToken(true, isSwappingDisplay);
            mRequestedOrSleepingDefaultDisplay = false;
            mDefaultDisplayPolicy.screenTurnedOff();
            synchronized (mLock) {
                if (mKeyguardDelegate != null) {
                    mKeyguardDelegate.onScreenTurnedOff();
                }
            }
            mDefaultDisplayRotation.updateOrientationListener();
            reportScreenStateToVrManager(false);
        }
    }

    private long getKeyguardDrawnTimeout() {
        final boolean bootCompleted =
                LocalServices.getService(SystemServiceManager.class).isBootCompleted();
        // Set longer timeout if it has not booted yet to prevent showing empty window.
        return bootCompleted ? mKeyguardDrawnTimeout : 5000;
    }

    @Nullable
    private WallpaperManagerInternal getWallpaperManagerInternal() {
        if (mWallpaperManagerInternal == null) {
            mWallpaperManagerInternal = LocalServices.getService(WallpaperManagerInternal.class);
        }
        return mWallpaperManagerInternal;
    }

    private void reportScreenTurningOnToWallpaper(int displayId) {
        WallpaperManagerInternal wallpaperManagerInternal = getWallpaperManagerInternal();
        if (wallpaperManagerInternal != null) {
            wallpaperManagerInternal.onScreenTurningOn(displayId);
        }
    }

    private void reportScreenTurnedOnToWallpaper(int displayId) {
        WallpaperManagerInternal wallpaperManagerInternal = getWallpaperManagerInternal();
        if (wallpaperManagerInternal != null) {
            wallpaperManagerInternal.onScreenTurnedOn(displayId);
        }
    }

    // Called on the DisplayManager's DisplayPowerController thread.
    @Override
    public void screenTurningOn(int displayId, final ScreenOnListener screenOnListener) {
        if (DEBUG_WAKEUP) Slog.i(TAG, "Display " + displayId + " turning on...");

        reportScreenTurningOnToWallpaper(displayId);
        if (displayId == DEFAULT_DISPLAY) {
            Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenTurningOn",
                    0 /* cookie */);
            updateScreenOffSleepToken(false /* acquire */, false /* isSwappingDisplay */);
            mDefaultDisplayPolicy.screenTurnedOn(screenOnListener);
            mBootAnimationDismissable = false;

            synchronized (mLock) {
                if (mKeyguardDelegate != null && mKeyguardDelegate.hasKeyguard()) {
                    mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
                    mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT,
                            getKeyguardDrawnTimeout());
                    mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
                } else {
                    if (DEBUG_WAKEUP) Slog.d(TAG,
                            "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
                    mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
                }
            }
        } else {
            mScreenOnListeners.put(displayId, screenOnListener);

            Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER,
                    TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD, displayId /* cookie */);
            mWindowManagerInternal.waitForAllWindowsDrawn(mHandler.obtainMessage(
                    MSG_WINDOW_MANAGER_DRAWN_COMPLETE, displayId, 0),
                    WAITING_FOR_DRAWN_TIMEOUT, displayId);
        }
    }

    // Called on the DisplayManager's DisplayPowerController thread.
    @Override
    public void screenTurnedOn(int displayId) {
        if (DEBUG_WAKEUP) Slog.i(TAG, "Display " + displayId + " turned on...");

        reportScreenTurnedOnToWallpaper(displayId);

        if (displayId != DEFAULT_DISPLAY) {
            return;
        }

        synchronized (mLock) {
            if (mKeyguardDelegate != null) {
                mKeyguardDelegate.onScreenTurnedOn();
            }
        }
        reportScreenStateToVrManager(true);
    }

    @Override
    public void screenTurningOff(int displayId, ScreenOffListener screenOffListener) {
        mWindowManagerFuncs.screenTurningOff(displayId, screenOffListener);
        if (displayId != DEFAULT_DISPLAY) {
            return;
        }

        mRequestedOrSleepingDefaultDisplay = true;
        synchronized (mLock) {
            if (mKeyguardDelegate != null) {
                mKeyguardDelegate.onScreenTurningOff();
            }
        }
    }

    private void reportScreenStateToVrManager(boolean isScreenOn) {
        if (mVrManagerInternal == null) {
            return;
        }
        mVrManagerInternal.onScreenStateChanged(isScreenOn);
    }

    private void finishWindowsDrawn(int displayId) {
        if (displayId != DEFAULT_DISPLAY && displayId != INVALID_DISPLAY) {
            final ScreenOnListener screenOnListener = mScreenOnListeners.removeReturnOld(displayId);
            if (screenOnListener != null) {
                screenOnListener.onScreenOn();
            }
            return;
        }

        if (!mDefaultDisplayPolicy.finishWindowsDrawn()) {
            return;
        }

        finishScreenTurningOn();
    }

    private void finishScreenTurningOn() {
        // We have just finished drawing screen content. Since the orientation listener
        // gets only installed when all windows are drawn, we try to install it again.
        mDefaultDisplayRotation.updateOrientationListener();

        final ScreenOnListener listener = mDefaultDisplayPolicy.getScreenOnListener();
        if (!mDefaultDisplayPolicy.finishScreenTurningOn()) {
            return; // Spurious or not ready yet.
        }
        Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "screenTurningOn", 0 /* cookie */);

        enableScreen(listener, true /* report */);
    }

    private void enableScreen(ScreenOnListener listener, boolean report) {
        final boolean enableScreen;
        final boolean awake = mDefaultDisplayPolicy.isAwake();
        synchronized (mLock) {
            // Remember the first time we draw the keyguard so we know when we're done with
            // the main part of booting and can enable the screen and hide boot messages.
            if (!mKeyguardDrawnOnce && awake) {
                mKeyguardDrawnOnce = true;
                enableScreen = true;
                if (mBootMessageNeedsHiding) {
                    mBootMessageNeedsHiding = false;
                    hideBootMessages();
                }
            } else {
                enableScreen = false;
            }
        }

        if (report) {
            if (listener != null) {
                listener.onScreenOn();
            }
        }

        if (enableScreen) {
            mWindowManagerFuncs.enableScreenIfNeeded();
        }
    }

    private void handleHideBootMessage() {
        synchronized (mLock) {
            if (!mKeyguardDrawnOnce) {
                mBootMessageNeedsHiding = true;
                return; // keyguard hasn't drawn the first time yet, not done booting
            }
        }

        if (mBootMsgDialog != null) {
            if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
            mBootMsgDialog.dismiss();
            mBootMsgDialog = null;
        }
    }

    @Override
    public boolean isScreenOn() {
        return mDefaultDisplayPolicy.isScreenOnEarly();
    }

    @Override
    public boolean okToAnimate(boolean ignoreScreenOn) {
        return (ignoreScreenOn || isScreenOn()) && !mDeviceGoingToSleep;
    }

    /** {@inheritDoc} */
    @Override
    public void enableKeyguard(boolean enabled) {
        if (mKeyguardDelegate != null) {
            mKeyguardDelegate.setKeyguardEnabled(enabled);
        }
    }

    /** {@inheritDoc} */
    @Override
    public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
        if (mKeyguardDelegate != null) {
            mKeyguardDelegate.verifyUnlock(callback);
        }
    }

    @Override
    public boolean isKeyguardShowing() {
        if (mKeyguardDelegate == null) return false;
        return mKeyguardDelegate.isShowing();
    }

    @Override
    public boolean isKeyguardShowingAndNotOccluded() {
        if (mKeyguardDelegate == null) return false;
        return mKeyguardDelegate.isShowing() && !isKeyguardOccluded();
    }

    @Override
    public boolean isKeyguardTrustedLw() {
        if (mKeyguardDelegate == null) return false;
        return mKeyguardDelegate.isTrusted();
    }

    /** {@inheritDoc} */
    @Override
    public boolean isKeyguardLocked() {
        return keyguardOn();
    }

    /** {@inheritDoc} */
    @Override
    public boolean isKeyguardSecure(int userId) {
        if (mKeyguardDelegate == null) return false;
        return mKeyguardDelegate.isSecure(userId);
    }

    /** {@inheritDoc} */
    @Override
    public boolean isKeyguardOccluded() {
        if (mKeyguardDelegate == null) return false;
        return mKeyguardDelegate.isOccluded();
    }

    /** {@inheritDoc} */
    @Override
    public boolean inKeyguardRestrictedKeyInputMode() {
        if (mKeyguardDelegate == null) return false;
        return mKeyguardDelegate.isInputRestricted();
    }

    /** {@inheritDoc} */
    @Override
    public boolean isKeyguardUnoccluding() {
        return keyguardOn() && !mWindowManagerFuncs.isAppTransitionStateIdle();
    }

    @Override
    public void dismissKeyguardLw(IKeyguardDismissCallback callback, CharSequence message) {
        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");

            // ask the keyguard to prompt the user to authenticate if necessary
            mKeyguardDelegate.dismiss(callback, message);
        } else if (callback != null) {
            try {
                callback.onDismissError();
            } catch (RemoteException e) {
                Slog.w(TAG, "Failed to call callback", e);
            }
        }
    }

    @Override
    public boolean isKeyguardDrawnLw() {
        synchronized (mLock) {
            return mKeyguardDrawnOnce;
        }
    }

    @Override
    public void startKeyguardExitAnimation(long startTime) {
        if (mKeyguardDelegate != null) {
            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
            mKeyguardDelegate.startKeyguardExitAnimation(startTime);
        }
    }

    void sendCloseSystemWindows() {
        PhoneWindow.sendCloseSystemWindows(mContext, null);
    }

    void sendCloseSystemWindows(String reason) {
        PhoneWindow.sendCloseSystemWindows(mContext, reason);
    }

    @Override
    public void setSafeMode(boolean safeMode) {
        mSafeMode = safeMode;
        if (safeMode) {
            performHapticFeedback(HapticFeedbackConstants.SAFE_MODE_ENABLED, true,
                    "Safe Mode Enabled");
        }
    }

    private void bindKeyguard() {
        synchronized (mLock) {
            if (mKeyguardBound) {
                return;
            }
            mKeyguardBound = true;
        }
        mKeyguardDelegate.bindService(mContext);
    }

    @Override
    public void onSystemUiStarted() {
        bindKeyguard();
    }

    /** {@inheritDoc} */
    @Override
    public void systemReady() {
        // In normal flow, systemReady is called before other system services are ready.
        // So it is better not to bind keyguard here.
        mKeyguardDelegate.onSystemReady();

        mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
        if (mVrManagerInternal != null) {
            mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
        }

        readCameraLensCoverState();
        updateUiMode();
        mDefaultDisplayRotation.updateOrientationListener();
        synchronized (mLock) {
            mSystemReady = true;
            updateSettings(mHandler);
            // If this happens, for whatever reason, systemReady came later than systemBooted.
            // And keyguard should be already bound from systemBooted
            if (mSystemBooted) {
                mKeyguardDelegate.onBootCompleted();
            }
        }

        mAutofillManagerInternal = LocalServices.getService(AutofillManagerInternal.class);
        mGestureLauncherService = LocalServices.getService(GestureLauncherService.class);
    }

    /** {@inheritDoc} */
    @Override
    public void systemBooted() {
        bindKeyguard();
        synchronized (mLock) {
            mSystemBooted = true;
            if (mSystemReady) {
                mKeyguardDelegate.onBootCompleted();
            }
        }
        mSideFpsEventHandler.onFingerprintSensorReady();
        startedWakingUp(Display.DEFAULT_DISPLAY_GROUP, PowerManager.WAKE_REASON_UNKNOWN);
        finishedWakingUp(Display.DEFAULT_DISPLAY_GROUP, PowerManager.WAKE_REASON_UNKNOWN);

        int defaultDisplayState = mDisplayManager.getDisplay(DEFAULT_DISPLAY).getState();
        boolean defaultDisplayOn = defaultDisplayState == Display.STATE_ON;
        boolean defaultScreenTurningOn = mDefaultDisplayPolicy.getScreenOnListener() != null;
        if (defaultDisplayOn || defaultScreenTurningOn) {
            // Now that system is booted, wait for keyguard and windows to be drawn before
            // updating the orientation listener, stopping the boot animation and enabling screen.
            screenTurningOn(DEFAULT_DISPLAY, mDefaultDisplayPolicy.getScreenOnListener());
            screenTurnedOn(DEFAULT_DISPLAY);
        } else {
            // We're not turning the screen on, so don't wait for keyguard to be drawn
            // to dismiss the boot animation and finish booting
            mBootAnimationDismissable = true;
            enableScreen(null, false /* report */);
        }
    }

    @Override
    public boolean canDismissBootAnimation() {
        // Allow to dismiss the boot animation if the keyguard has finished drawing,
        // or mBootAnimationDismissable has been set
        return mDefaultDisplayPolicy.isKeyguardDrawComplete() || mBootAnimationDismissable;
    }

    ProgressDialog mBootMsgDialog = null;

    /** {@inheritDoc} */
    @Override
    public void showBootMessage(final CharSequence msg, final boolean always) {
        mHandler.post(new Runnable() {
            @Override public void run() {
                if (mBootMsgDialog == null) {
                    int theme;
                    if (mPackageManager.hasSystemFeature(FEATURE_LEANBACK)) {
                        theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
                    } else {
                        theme = 0;
                    }

                    mBootMsgDialog = new ProgressDialog(mContext, theme) {
                        // This dialog will consume all events coming in to
                        // it, to avoid it trying to do things too early in boot.
                        @Override public boolean dispatchKeyEvent(KeyEvent event) {
                            return true;
                        }
                        @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
                            return true;
                        }
                        @Override public boolean dispatchTouchEvent(MotionEvent ev) {
                            return true;
                        }
                        @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
                            return true;
                        }
                        @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
                            return true;
                        }
                        @Override public boolean dispatchPopulateAccessibilityEvent(
                                AccessibilityEvent event) {
                            return true;
                        }
                    };
                    if (mPackageManager.isDeviceUpgrading()) {
                        mBootMsgDialog.setTitle(R.string.android_upgrading_title);
                    } else {
                        mBootMsgDialog.setTitle(R.string.android_start_title);
                    }
                    mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
                    mBootMsgDialog.setIndeterminate(true);
                    mBootMsgDialog.getWindow().setType(
                            WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
                    mBootMsgDialog.getWindow().addFlags(
                            WindowManager.LayoutParams.FLAG_DIM_BEHIND
                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
                    mBootMsgDialog.getWindow().setDimAmount(1);
                    WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
                    lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
                    lp.setFitInsetsTypes(0 /* types */);
                    mBootMsgDialog.getWindow().setAttributes(lp);
                    mBootMsgDialog.setCancelable(false);
                    mBootMsgDialog.show();
                }
                mBootMsgDialog.setMessage(msg);
            }
        });
    }

    /** {@inheritDoc} */
    @Override
    public void hideBootMessages() {
        mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
    }

    /** {@inheritDoc} */
    @Override
    public void userActivity(int displayGroupId, int event) {
        if (displayGroupId == DEFAULT_DISPLAY && event == PowerManager.USER_ACTIVITY_EVENT_TOUCH) {
            mDefaultDisplayPolicy.onUserActivityEventTouch();
        }
        synchronized (mScreenLockTimeout) {
            if (mLockScreenTimerActive) {
                // reset the timer
                mHandler.removeCallbacks(mScreenLockTimeout);
                mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
            }
        }
    }

    class ScreenLockTimeout implements Runnable {
        Bundle options;

        @Override
        public void run() {
            synchronized (this) {
                if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
                if (mKeyguardDelegate != null) {
                    mKeyguardDelegate.doKeyguardTimeout(options);
                }
                mLockScreenTimerActive = false;
                mLockNowPending = false;
                options = null;
            }
        }

        public void setLockOptions(Bundle options) {
            this.options = options;
        }
    }

    final ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();

    @Override
    public void lockNow(Bundle options) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
        mHandler.removeCallbacks(mScreenLockTimeout);
        if (options != null) {
            // In case multiple calls are made to lockNow, we don't wipe out the options
            // until the runnable actually executes.
            mScreenLockTimeout.setLockOptions(options);
        }
        mHandler.post(mScreenLockTimeout);
        synchronized (mScreenLockTimeout) {
            mLockNowPending = true;
        }
    }

    // TODO (b/113840485): Move this logic to DisplayPolicy when lockscreen supports multi-display.
    @Override
    public void setAllowLockscreenWhenOn(int displayId, boolean allow) {
        if (allow) {
            mAllowLockscreenWhenOnDisplays.add(displayId);
        } else {
            mAllowLockscreenWhenOnDisplays.remove(displayId);
        }
        updateLockScreenTimeout();
    }

    private void updateLockScreenTimeout() {
        synchronized (mScreenLockTimeout) {
            if (mLockNowPending) {
                Log.w(TAG, "lockNow pending, ignore updating lockscreen timeout");
                return;
            }
            final boolean enable = !mAllowLockscreenWhenOnDisplays.isEmpty()
                    && mDefaultDisplayPolicy.isAwake()
                    && mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId);
            if (mLockScreenTimerActive != enable) {
                if (enable) {
                    if (localLOGV) Log.v(TAG, "setting lockscreen timer");
                    mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
                    mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
                } else {
                    if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
                    mHandler.removeCallbacks(mScreenLockTimeout);
                }
                mLockScreenTimerActive = enable;
            }
        }
    }

    // TODO (multidisplay): Support multiple displays in WindowManagerPolicy.
    private void updateScreenOffSleepToken(boolean acquire, boolean isSwappingDisplay) {
        if (acquire) {
            mScreenOffSleepTokenAcquirer.acquire(DEFAULT_DISPLAY, isSwappingDisplay);
        } else {
            mScreenOffSleepTokenAcquirer.release(DEFAULT_DISPLAY);
        }
    }

    /** {@inheritDoc} */
    @Override
    public void enableScreenAfterBoot() {
        readLidState();
        applyLidSwitchState();
        updateRotation(true);
    }

    private void applyLidSwitchState() {
        final int lidState = mDefaultDisplayPolicy.getLidState();
        if (lidState == LID_CLOSED) {
            int lidBehavior = getLidBehavior();
            switch (lidBehavior) {
                case LID_BEHAVIOR_LOCK:
                    mWindowManagerFuncs.lockDeviceNow();
                    break;
                case LID_BEHAVIOR_SLEEP:
                    sleepDefaultDisplay(SystemClock.uptimeMillis(),
                            PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
                            PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
                    break;
                case LID_BEHAVIOR_NONE:
                    // fall through
                default:
                    break;
            }
        }

        synchronized (mLock) {
            updateWakeGestureListenerLp();
        }
    }

    void updateUiMode() {
        if (mUiModeManager == null) {
            mUiModeManager = IUiModeManager.Stub.asInterface(
                    ServiceManager.getService(Context.UI_MODE_SERVICE));
        }
        try {
            mUiMode = mUiModeManager.getCurrentModeType();
        } catch (RemoteException e) {
        }
    }

    @Override
    public int getUiMode() {
        return mUiMode;
    }

    void updateRotation(boolean alwaysSendConfiguration) {
        mWindowManagerFuncs.updateRotation(alwaysSendConfiguration, false /* forceRelayout */);
    }

    /**
     * Return an Intent to launch the currently active dock app as home.  Returns
     * null if the standard home should be launched, which is the case if any of the following is
     * true:
     * <ul>
     *  <li>The device is not in either car mode or desk mode
     *  <li>The device is in car mode but mEnableCarDockHomeCapture is false
     *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
     *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
     *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
     * </ul>
     * @return A dock intent.
     */
    Intent createHomeDockIntent() {
        Intent intent = null;

        // What home does is based on the mode, not the dock state.  That
        // is, when in car mode you should be taken to car home regardless
        // of whether we are actually in a car dock.
        if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
            if (mEnableCarDockHomeCapture) {
                intent = mCarDockIntent;
            }
        } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
            if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
                intent = mDeskDockIntent;
            }
        } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH) {
            final int dockMode = mDefaultDisplayPolicy.getDockMode();
            if (dockMode == Intent.EXTRA_DOCK_STATE_DESK
                    || dockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
                    || dockMode == Intent.EXTRA_DOCK_STATE_LE_DESK) {
                // Always launch dock home from home when watch is docked, if it exists.
                intent = mDeskDockIntent;
            }
        } else if (mUiMode == Configuration.UI_MODE_TYPE_VR_HEADSET) {
            if (ENABLE_VR_HEADSET_HOME_CAPTURE) {
                intent = mVrHeadsetHomeIntent;
            }
        }

        if (intent == null) {
            return null;
        }

        ActivityInfo ai = null;
        ResolveInfo info = mPackageManager.resolveActivityAsUser(
                intent,
                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
                mCurrentUserId);
        if (info != null) {
            ai = info.activityInfo;
        }
        if (ai != null
                && ai.metaData != null
                && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
            intent = new Intent(intent);
            intent.setClassName(ai.packageName, ai.name);
            return intent;
        }

        return null;
    }

    void startDockOrHome(int displayId, boolean fromHomeKey, boolean awakenFromDreams,
            String startReason) {
        try {
            ActivityManager.getService().stopAppSwitches();
        } catch (RemoteException e) {}
        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);

        if (awakenFromDreams) {
            awakenDreams();
        }

        if (!mHasFeatureAuto && !isUserSetupComplete()) {
            Slog.i(TAG, "Not going home because user setup is in progress.");
            return;
        }

        // Start dock.
        Intent dock = createHomeDockIntent();
        if (dock != null) {
            try {
                if (fromHomeKey) {
                    dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
                }
                startActivityAsUser(dock, UserHandle.CURRENT);
                return;
            } catch (ActivityNotFoundException e) {
            }
        }

        if (DEBUG_WAKEUP) {
            Log.d(TAG, "startDockOrHome: startReason= " + startReason);
        }

        int userId = mUserManagerInternal.getUserAssignedToDisplay(displayId);
        // Start home.
        mActivityTaskManagerInternal.startHomeOnDisplay(userId, startReason,
                displayId, true /* allowInstrumenting */, fromHomeKey);
    }

    void startDockOrHome(int displayId, boolean fromHomeKey, boolean awakenFromDreams) {
        startDockOrHome(displayId, fromHomeKey, awakenFromDreams, /*startReason*/
                "startDockOrHome");
    }

    /**
     * goes to the home screen
     * @return whether it did anything
     */
    boolean goHome() {
        if (!isUserSetupComplete()) {
            Slog.i(TAG, "Not going home because user setup is in progress.");
            return false;
        }
        if (false) {
            // This code always brings home to the front.
            startDockOrHome(DEFAULT_DISPLAY, false /*fromHomeKey*/, true /* awakenFromDreams */);
        } else {
            // This code brings home to the front or, if it is already
            // at the front, puts the device to sleep.
            try {
                if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
                    /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
                    Log.d(TAG, "UTS-TEST-MODE");
                } else {
                    ActivityManager.getService().stopAppSwitches();
                    sendCloseSystemWindows();
                    final Intent dock = createHomeDockIntent();
                    if (dock != null) {
                        int result = ActivityTaskManager.getService()
                                .startActivityAsUser(null, mContext.getOpPackageName(),
                                        mContext.getAttributionTag(), dock,
                                        dock.resolveTypeIfNeeded(mContext.getContentResolver()),
                                        null, null, 0,
                                        ActivityManager.START_FLAG_ONLY_IF_NEEDED,
                                        null, null, UserHandle.USER_CURRENT);
                        if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
                            return false;
                        }
                    }
                }
                int result = ActivityTaskManager.getService()
                        .startActivityAsUser(null, mContext.getOpPackageName(),
                                mContext.getAttributionTag(), mHomeIntent,
                                mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
                                null, null, 0,
                                ActivityManager.START_FLAG_ONLY_IF_NEEDED,
                                null, null, UserHandle.USER_CURRENT);
                if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
                    return false;
                }
            } catch (RemoteException ex) {
                // bummer, the activity manager, which is in this process, is dead
            }
        }
        return true;
    }

    private boolean isTheaterModeEnabled() {
        return Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.THEATER_MODE_ON, 0) == 1;
    }

    private boolean performHapticFeedback(int effectId, boolean always, String reason) {
        return performHapticFeedback(Process.myUid(), mContext.getOpPackageName(),
            effectId, always, reason);
    }

    @Override
    public boolean isGlobalKey(int keyCode) {
        return mGlobalKeyManager.shouldHandleGlobalKey(keyCode);
    }

    @Override
    public boolean performHapticFeedback(int uid, String packageName, int effectId,
            boolean always, String reason) {
        if (!mVibrator.hasVibrator()) {
            return false;
        }
        VibrationEffect effect =
                mHapticFeedbackVibrationProvider.getVibrationForHapticFeedback(effectId);
        if (effect == null) {
            return false;
        }
        VibrationAttributes attrs =
                mHapticFeedbackVibrationProvider.getVibrationAttributesForHapticFeedback(
                        effectId, /* bypassVibrationIntensitySetting= */ always);
        mVibrator.vibrate(uid, packageName, effect, reason, attrs);
        return true;
    }


    @Override
    public void keepScreenOnStartedLw() {
    }

    @Override
    public void keepScreenOnStoppedLw() {
        if (isKeyguardShowingAndNotOccluded()) {
            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
        }
    }

    // Use this instead of checking config_showNavigationBar so that it can be consistently
    // overridden by qemu.hw.mainkeys in the emulator.
    @Override
    public boolean hasNavigationBar() {
        return mDefaultDisplayPolicy.hasNavigationBar();
    }

    @Override
    public void setDismissImeOnBackKeyPressed(boolean newValue) {
        mDismissImeOnBackKeyPressed = newValue;
    }

    @Override
    public void setCurrentUserLw(int newUserId) {
        mCurrentUserId = newUserId;
        if (mKeyguardDelegate != null) {
            mKeyguardDelegate.setCurrentUser(newUserId);
        }
        if (mAccessibilityShortcutController != null) {
            mAccessibilityShortcutController.setCurrentUser(newUserId);
        }
        StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
        if (statusBar != null) {
            statusBar.setCurrentUser(newUserId);
        }
    }

    @Override
    public void setSwitchingUser(boolean switching) {
        mKeyguardDelegate.setSwitchingUser(switching);
    }

    @Override
    public void dumpDebug(ProtoOutputStream proto, long fieldId) {
        final long token = proto.start(fieldId);
        proto.write(ROTATION_MODE, mDefaultDisplayRotation.getUserRotationMode());
        proto.write(ROTATION, mDefaultDisplayRotation.getUserRotation());
        proto.write(ORIENTATION, mDefaultDisplayRotation.getCurrentAppOrientation());
        proto.write(SCREEN_ON_FULLY, mDefaultDisplayPolicy.isScreenOnFully());
        proto.write(KEYGUARD_DRAW_COMPLETE, mDefaultDisplayPolicy.isKeyguardDrawComplete());
        proto.write(WINDOW_MANAGER_DRAW_COMPLETE,
                mDefaultDisplayPolicy.isWindowManagerDrawComplete());
        proto.write(KEYGUARD_OCCLUDED, isKeyguardOccluded());
        proto.write(KEYGUARD_OCCLUDED_CHANGED, mKeyguardOccludedChanged);
        proto.write(KEYGUARD_OCCLUDED_PENDING, mPendingKeyguardOccluded);
        if (mKeyguardDelegate != null) {
            mKeyguardDelegate.dumpDebug(proto, KEYGUARD_DELEGATE);
        }
        proto.end(token);
    }

    @Override
    public void dump(String prefix, PrintWriter pw, String[] args) {
        pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
                pw.print(" mSystemReady="); pw.print(mSystemReady);
                pw.print(" mSystemBooted="); pw.println(mSystemBooted);
        pw.print(prefix); pw.print("mCameraLensCoverState=");
                pw.println(WindowManagerFuncs.cameraLensStateToString(mCameraLensCoverState));
        pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
                pw.println(mWakeGestureEnabledSetting);

        pw.print(prefix);
                pw.print("mUiMode=");
                pw.print(Configuration.uiModeToString(mUiMode));
                pw.print("mEnableCarDockHomeCapture="); pw.println(mEnableCarDockHomeCapture);
        pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
                pw.print(mLidKeyboardAccessibility);
                pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
                pw.print(" getLidBehavior="); pw.println(lidBehaviorToString(getLidBehavior()));
        pw.print(prefix);
                pw.print("mLongPressOnBackBehavior=");
                pw.println(longPressOnBackBehaviorToString(mLongPressOnBackBehavior));
        pw.print(prefix);
                pw.print("mLongPressOnHomeBehavior=");
                pw.println(longPressOnHomeBehaviorToString(mLongPressOnHomeBehavior));
        pw.print(prefix);
                pw.print("mDoubleTapOnHomeBehavior=");
                pw.println(doubleTapOnHomeBehaviorToString(mDoubleTapOnHomeBehavior));
        pw.print(prefix);
                pw.print("mShortPressOnPowerBehavior=");
                pw.println(shortPressOnPowerBehaviorToString(mShortPressOnPowerBehavior));
        pw.print(prefix);
                pw.print("mLongPressOnPowerBehavior=");
                pw.println(longPressOnPowerBehaviorToString(mLongPressOnPowerBehavior));
        pw.print(prefix);
        pw.print("mShortPressOnSettingsBehavior=");
        pw.println(shortPressOnSettingsBehaviorToString(mShortPressOnSettingsBehavior));
        pw.print(prefix);
        pw.print("mLongPressOnPowerAssistantTimeoutMs=");
        pw.println(mLongPressOnPowerAssistantTimeoutMs);
        pw.print(prefix);
                pw.print("mVeryLongPressOnPowerBehavior=");
                pw.println(veryLongPressOnPowerBehaviorToString(mVeryLongPressOnPowerBehavior));
        pw.print(prefix);
                pw.print("mDoublePressOnPowerBehavior=");
                pw.println(multiPressOnPowerBehaviorToString(mDoublePressOnPowerBehavior));
        pw.print(prefix);
                pw.print("mTriplePressOnPowerBehavior=");
                pw.println(multiPressOnPowerBehaviorToString(mTriplePressOnPowerBehavior));
        pw.print(prefix);
                pw.print("mSupportShortPressPowerWhenDefaultDisplayOn=");
                pw.println(mSupportShortPressPowerWhenDefaultDisplayOn);
        pw.print(prefix);
        pw.print("mPowerVolUpBehavior=");
        pw.println(powerVolumeUpBehaviorToString(mPowerVolUpBehavior));
        pw.print(prefix);
                pw.print("mShortPressOnSleepBehavior=");
                pw.println(shortPressOnSleepBehaviorToString(mShortPressOnSleepBehavior));
        pw.print(prefix);
                pw.print("mShortPressOnWindowBehavior=");
                pw.println(shortPressOnWindowBehaviorToString(mShortPressOnWindowBehavior));
        pw.print(prefix);
                pw.print("mShortPressOnStemPrimaryBehavior=");
                pw.println(shortPressOnStemPrimaryBehaviorToString(
                    mShortPressOnStemPrimaryBehavior));
        pw.print(prefix);
                pw.print("mDoublePressOnStemPrimaryBehavior=");
                pw.println(doublePressOnStemPrimaryBehaviorToString(
                    mDoublePressOnStemPrimaryBehavior));
        pw.print(prefix);
                pw.print("mTriplePressOnStemPrimaryBehavior=");
                pw.println(triplePressOnStemPrimaryBehaviorToString(
                    mTriplePressOnStemPrimaryBehavior));
        pw.print(prefix);
                pw.print("mLongPressOnStemPrimaryBehavior=");
                pw.println(longPressOnStemPrimaryBehaviorToString(
                    mLongPressOnStemPrimaryBehavior));
        pw.print(prefix);
                pw.print("mAllowStartActivityForLongPressOnPowerDuringSetup=");
                pw.println(mAllowStartActivityForLongPressOnPowerDuringSetup);
        pw.print(prefix);
                pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
        pw.print(prefix);
                pw.print("mDismissImeOnBackKeyPressed="); pw.print(mDismissImeOnBackKeyPressed);
                pw.print(" mIncallPowerBehavior=");
                pw.println(incallPowerBehaviorToString(mIncallPowerBehavior));
        pw.print(prefix);
                pw.print("mIncallBackBehavior=");
                pw.print(incallBackBehaviorToString(mIncallBackBehavior));
                pw.print(" mEndcallBehavior=");
                pw.println(endcallBehaviorToString(mEndcallBehavior));
        pw.print(prefix);
        // TODO(b/117479243): handle it in InputPolicy
        pw.println("mDisplayHomeButtonHandlers=");
        for (int i = 0; i < mDisplayHomeButtonHandlers.size(); i++) {
            final int key = mDisplayHomeButtonHandlers.keyAt(i);
            pw.print(prefix); pw.print("  "); pw.println(mDisplayHomeButtonHandlers.get(key));
        }
        pw.print(prefix); pw.print("mKeyguardOccluded="); pw.print(isKeyguardOccluded());
                pw.print(" mKeyguardOccludedChanged="); pw.print(mKeyguardOccludedChanged);
                pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded);
        pw.print(prefix); pw.print("mAllowLockscreenWhenOnDisplays=");
                pw.print(!mAllowLockscreenWhenOnDisplays.isEmpty());
                pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
                pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
        pw.print(prefix); pw.print("mKidsModeEnabled="); pw.println(mKidsModeEnabled);

        mHapticFeedbackVibrationProvider.dump(prefix, pw);
        mGlobalKeyManager.dump(prefix, pw);
        mKeyCombinationManager.dump(prefix, pw);
        mSingleKeyGestureDetector.dump(prefix, pw);
        mDeferredKeyActionExecutor.dump(prefix, pw);

        if (mWakeGestureListener != null) {
            mWakeGestureListener.dump(pw, prefix);
        }
        if (mBurnInProtectionHelper != null) {
            mBurnInProtectionHelper.dump(prefix, pw);
        }
        if (mKeyguardDelegate != null) {
            mKeyguardDelegate.dump(prefix, pw);
        }

        pw.print(prefix); pw.println("Looper state:");
        mHandler.getLooper().dump(new PrintWriterPrinter(pw), prefix + "  ");
    }

    private static String endcallBehaviorToString(int behavior) {
        StringBuilder sb = new StringBuilder();
        if ((behavior & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0 ) {
            sb.append("home|");
        }
        if ((behavior & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
            sb.append("sleep|");
        }

        final int N = sb.length();
        if (N == 0) {
            return "<nothing>";
        } else {
            // Chop off the trailing '|'
            return sb.substring(0, N - 1);
        }
    }

    private static String incallPowerBehaviorToString(int behavior) {
        if ((behavior & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0) {
            return "hangup";
        } else {
            return "sleep";
        }
    }

    private static String incallBackBehaviorToString(int behavior) {
        if ((behavior & Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_HANGUP) != 0) {
            return "hangup";
        } else {
            return "<nothing>";
        }
    }

    private static String longPressOnBackBehaviorToString(int behavior) {
        switch (behavior) {
            case LONG_PRESS_BACK_NOTHING:
                return "LONG_PRESS_BACK_NOTHING";
            case LONG_PRESS_BACK_GO_TO_VOICE_ASSIST:
                return "LONG_PRESS_BACK_GO_TO_VOICE_ASSIST";
            default:
                return Integer.toString(behavior);
        }
    }

    private static String longPressOnHomeBehaviorToString(int behavior) {
        switch (behavior) {
            case LONG_PRESS_HOME_NOTHING:
                return "LONG_PRESS_HOME_NOTHING";
            case LONG_PRESS_HOME_ALL_APPS:
                return "LONG_PRESS_HOME_ALL_APPS";
            case LONG_PRESS_HOME_ASSIST:
                return "LONG_PRESS_HOME_ASSIST";
            case LONG_PRESS_HOME_NOTIFICATION_PANEL:
                return "LONG_PRESS_HOME_NOTIFICATION_PANEL";
            default:
                return Integer.toString(behavior);
        }
    }

    private static String doubleTapOnHomeBehaviorToString(int behavior) {
        switch (behavior) {
            case DOUBLE_TAP_HOME_NOTHING:
                return "DOUBLE_TAP_HOME_NOTHING";
            case DOUBLE_TAP_HOME_RECENT_SYSTEM_UI:
                return "DOUBLE_TAP_HOME_RECENT_SYSTEM_UI";
            case DOUBLE_TAP_HOME_PIP_MENU:
                return "DOUBLE_TAP_HOME_PIP_MENU";
            default:
                return Integer.toString(behavior);
        }
    }

    private static String shortPressOnPowerBehaviorToString(int behavior) {
        switch (behavior) {
            case SHORT_PRESS_POWER_NOTHING:
                return "SHORT_PRESS_POWER_NOTHING";
            case SHORT_PRESS_POWER_GO_TO_SLEEP:
                return "SHORT_PRESS_POWER_GO_TO_SLEEP";
            case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
                return "SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP";
            case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
                return "SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME";
            case SHORT_PRESS_POWER_GO_HOME:
                return "SHORT_PRESS_POWER_GO_HOME";
            case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME:
                return "SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME";
            default:
                return Integer.toString(behavior);
        }
    }

    private static String longPressOnPowerBehaviorToString(int behavior) {
        switch (behavior) {
            case LONG_PRESS_POWER_NOTHING:
                return "LONG_PRESS_POWER_NOTHING";
            case LONG_PRESS_POWER_GLOBAL_ACTIONS:
                return "LONG_PRESS_POWER_GLOBAL_ACTIONS";
            case LONG_PRESS_POWER_SHUT_OFF:
                return "LONG_PRESS_POWER_SHUT_OFF";
            case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
                return "LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM";
            case LONG_PRESS_POWER_GO_TO_VOICE_ASSIST:
                return "LONG_PRESS_POWER_GO_TO_VOICE_ASSIST";
            case LONG_PRESS_POWER_ASSISTANT:
                return "LONG_PRESS_POWER_ASSISTANT";
            default:
                return Integer.toString(behavior);
        }
    }

    private static String shortPressOnSettingsBehaviorToString(int behavior) {
        switch (behavior) {
            case SHORT_PRESS_SETTINGS_NOTHING:
                return "SHORT_PRESS_SETTINGS_NOTHING";
            case SHORT_PRESS_SETTINGS_NOTIFICATION_PANEL:
                return "SHORT_PRESS_SETTINGS_NOTIFICATION_PANEL";
            default:
                return Integer.toString(behavior);
        }
    }

    private static String veryLongPressOnPowerBehaviorToString(int behavior) {
        switch (behavior) {
            case VERY_LONG_PRESS_POWER_NOTHING:
                return "VERY_LONG_PRESS_POWER_NOTHING";
            case VERY_LONG_PRESS_POWER_GLOBAL_ACTIONS:
                return "VERY_LONG_PRESS_POWER_GLOBAL_ACTIONS";
            default:
                return Integer.toString(behavior);
        }
    }

    private static String powerVolumeUpBehaviorToString(int behavior) {
        switch (behavior) {
            case POWER_VOLUME_UP_BEHAVIOR_NOTHING:
                return "POWER_VOLUME_UP_BEHAVIOR_NOTHING";
            case POWER_VOLUME_UP_BEHAVIOR_MUTE:
                return "POWER_VOLUME_UP_BEHAVIOR_MUTE";
            case POWER_VOLUME_UP_BEHAVIOR_GLOBAL_ACTIONS:
                return "POWER_VOLUME_UP_BEHAVIOR_GLOBAL_ACTIONS";
            default:
                return Integer.toString(behavior);
        }
    }

    private static String multiPressOnPowerBehaviorToString(int behavior) {
        switch (behavior) {
            case MULTI_PRESS_POWER_NOTHING:
                return "MULTI_PRESS_POWER_NOTHING";
            case MULTI_PRESS_POWER_THEATER_MODE:
                return "MULTI_PRESS_POWER_THEATER_MODE";
            case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
                return "MULTI_PRESS_POWER_BRIGHTNESS_BOOST";
            case MULTI_PRESS_POWER_LAUNCH_TARGET_ACTIVITY:
                return "MULTI_PRESS_POWER_LAUNCH_TARGET_ACTIVITY";
            default:
                return Integer.toString(behavior);
        }
    }

    private static String shortPressOnSleepBehaviorToString(int behavior) {
        switch (behavior) {
            case SHORT_PRESS_SLEEP_GO_TO_SLEEP:
                return "SHORT_PRESS_SLEEP_GO_TO_SLEEP";
            case SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME:
                return "SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME";
            default:
                return Integer.toString(behavior);
        }
    }

    private static String shortPressOnWindowBehaviorToString(int behavior) {
        switch (behavior) {
            case SHORT_PRESS_WINDOW_NOTHING:
                return "SHORT_PRESS_WINDOW_NOTHING";
            case SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE:
                return "SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE";
            default:
                return Integer.toString(behavior);
        }
    }

    private static String shortPressOnStemPrimaryBehaviorToString(int behavior) {
        switch (behavior) {
            case SHORT_PRESS_PRIMARY_NOTHING:
                return "SHORT_PRESS_PRIMARY_NOTHING";
            case SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS:
                return "SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS";
            case SHORT_PRESS_PRIMARY_LAUNCH_TARGET_ACTIVITY:
                return "SHORT_PRESS_PRIMARY_LAUNCH_TARGET_ACTIVITY";
            default:
                return Integer.toString(behavior);
        }
    }

    private static String doublePressOnStemPrimaryBehaviorToString(int behavior) {
        switch (behavior) {
            case DOUBLE_PRESS_PRIMARY_NOTHING:
                return "DOUBLE_PRESS_PRIMARY_NOTHING";
            case DOUBLE_PRESS_PRIMARY_SWITCH_RECENT_APP:
                return "DOUBLE_PRESS_PRIMARY_SWITCH_RECENT_APP";
            default:
                return Integer.toString(behavior);
        }
    }

    private static String triplePressOnStemPrimaryBehaviorToString(int behavior) {
        switch (behavior) {
            case TRIPLE_PRESS_PRIMARY_NOTHING:
                return "TRIPLE_PRESS_PRIMARY_NOTHING";
            case TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY:
                return "TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY";
            default:
                return Integer.toString(behavior);
        }
    }

    private static String longPressOnStemPrimaryBehaviorToString(int behavior) {
        switch (behavior) {
            case LONG_PRESS_PRIMARY_NOTHING:
                return "LONG_PRESS_PRIMARY_NOTHING";
            case LONG_PRESS_PRIMARY_LAUNCH_VOICE_ASSISTANT:
                return "LONG_PRESS_PRIMARY_LAUNCH_VOICE_ASSISTANT";
            default:
                return Integer.toString(behavior);
        }
    }

    private static String lidBehaviorToString(int behavior) {
        switch (behavior) {
            case LID_BEHAVIOR_LOCK:
                return "LID_BEHAVIOR_LOCK";
            case LID_BEHAVIOR_SLEEP:
                return "LID_BEHAVIOR_SLEEP";
            case LID_BEHAVIOR_NONE:
                return "LID_BEHAVIOR_NONE";
            default:
                return Integer.toString(behavior);
        }
    }

    public static boolean isLongPressToAssistantEnabled(Context context) {
        ContentResolver resolver = context.getContentResolver();
        int longPressToAssistant = Settings.System.getIntForUser(resolver,
                Settings.Global.Wearable.CLOCKWORK_LONG_PRESS_TO_ASSISTANT_ENABLED,
                /* def= */ 1,
                UserHandle.USER_CURRENT);
        if(Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "longPressToAssistant = " + longPressToAssistant);
        }
        return (longPressToAssistant == 1);
    }

    private class HdmiVideoExtconUEventObserver extends ExtconStateObserver<Boolean> {
        private static final String HDMI_EXIST = "HDMI=1";
        private static final String DP_EXIST = "DP=1";
        private static final String NAME = "hdmi";

        private boolean init(ExtconInfo hdmi) {
            boolean plugged = false;
            try {
                plugged = parseStateFromFile(hdmi);
            } catch (FileNotFoundException e) {
                Slog.w(TAG,
                        hdmi.getStatePath()
                                + " not found while attempting to determine initial state",
                        e);
            } catch (IOException e) {
                Slog.e(TAG,
                        "Error reading " + hdmi.getStatePath()
                                + " while attempting to determine initial state",
                        e);
            }
            startObserving(hdmi);
            return plugged;
        }

        @Override
        public void updateState(ExtconInfo extconInfo, String eventName, Boolean state) {
            mDefaultDisplayPolicy.setHdmiPlugged(state);
        }

        @Override
        public Boolean parseState(ExtconInfo extconIfno, String state) {
            // extcon event state changes from kernel4.9
            // new state will be like STATE=HDMI=1
            // or like STATE=DP=1 for newer kernel
            return state.contains(HDMI_EXIST) || state.contains(DP_EXIST);
        }
    }

    private void launchTargetSearchActivity() {
        Intent intent;
        if (mSearchKeyTargetActivity != null) {
            intent = new Intent();
            intent.setComponent(mSearchKeyTargetActivity);
        } else {
            intent = new Intent(Intent.ACTION_WEB_SEARCH);
        }
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
        try {
            startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
        } catch (ActivityNotFoundException ignore) {
            Slog.e(TAG, "Could not resolve activity with : "
                    + intent.getComponent().flattenToString()
                    + " name.");
        }
    }

    /** A helper class to check button override permission. */
    static class ButtonOverridePermissionChecker {
        boolean canAppOverrideSystemKey(Context context, int uid) {
            return PermissionChecker.checkPermissionForDataDelivery(
                            context,
                            OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW,
                            PID_UNKNOWN,
                            uid,
                            null,
                            null,
                            null)
                    == PERMISSION_GRANTED;
        }
    }
}
