Home | History | Annotate | Download | only in policy
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.policy;
     18 
     19 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
     20 import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
     21 import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
     22 import static android.app.AppOpsManager.OP_TOAST_WINDOW;
     23 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
     24 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
     25 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
     26 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
     27 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
     28 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
     29 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
     30 import static android.content.Context.CONTEXT_RESTRICTED;
     31 import static android.content.Context.DISPLAY_SERVICE;
     32 import static android.content.Context.WINDOW_SERVICE;
     33 import static android.content.pm.PackageManager.FEATURE_LEANBACK;
     34 import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
     35 import static android.content.pm.PackageManager.FEATURE_WATCH;
     36 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
     37 import static android.content.res.Configuration.EMPTY;
     38 import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
     39 import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
     40 import static android.os.Build.VERSION_CODES.M;
     41 import static android.os.Build.VERSION_CODES.O;
     42 import static android.provider.Settings.Secure.VOLUME_HUSH_OFF;
     43 import static android.view.Display.DEFAULT_DISPLAY;
     44 import static android.view.Display.STATE_OFF;
     45 import static android.view.WindowManager.DOCKED_LEFT;
     46 import static android.view.WindowManager.DOCKED_RIGHT;
     47 import static android.view.WindowManager.DOCKED_TOP;
     48 import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
     49 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
     50 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
     51 import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
     52 import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
     53 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
     54 import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
     55 import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
     56 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR;
     57 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
     58 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN;
     59 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
     60 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
     61 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
     62 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
     63 import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
     64 import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
     65 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
     66 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
     67 import static android.view.WindowManager.LayoutParams.LAST_SYSTEM_WINDOW;
     68 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
     69 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
     70 import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
     71 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN;
     72 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
     73 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
     74 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR;
     75 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
     76 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
     77 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
     78 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
     79 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
     80 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
     81 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
     82 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
     83 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
     84 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
     85 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
     86 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
     87 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
     88 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
     89 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
     90 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
     91 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
     92 import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
     93 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
     94 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
     95 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
     96 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
     97 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
     98 import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
     99 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
    100 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
    101 import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
    102 import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
    103 import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
    104 import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
    105 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
    106 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
    107 import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
    108 import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR;
    109 import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
    110 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
    111 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
    112 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
    113 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
    114 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
    115 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
    116 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
    117 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
    118 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
    119 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING;
    120 import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
    121 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
    122 import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
    123 import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
    124 import static android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION;
    125 import static android.view.WindowManagerGlobal.ADD_OKAY;
    126 import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED;
    127 
    128 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
    129 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
    130 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
    131 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
    132 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
    133 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
    134 import static com.android.server.wm.WindowManagerPolicyProto.FOCUSED_APP_TOKEN;
    135 import static com.android.server.wm.WindowManagerPolicyProto.FOCUSED_WINDOW;
    136 import static com.android.server.wm.WindowManagerPolicyProto.FORCE_STATUS_BAR;
    137 import static com.android.server.wm.WindowManagerPolicyProto.FORCE_STATUS_BAR_FROM_KEYGUARD;
    138 import static com.android.server.wm.WindowManagerPolicyProto.KEYGUARD_DELEGATE;
    139 import static com.android.server.wm.WindowManagerPolicyProto.KEYGUARD_DRAW_COMPLETE;
    140 import static com.android.server.wm.WindowManagerPolicyProto.KEYGUARD_OCCLUDED;
    141 import static com.android.server.wm.WindowManagerPolicyProto.KEYGUARD_OCCLUDED_CHANGED;
    142 import static com.android.server.wm.WindowManagerPolicyProto.KEYGUARD_OCCLUDED_PENDING;
    143 import static com.android.server.wm.WindowManagerPolicyProto.LAST_SYSTEM_UI_FLAGS;
    144 import static com.android.server.wm.WindowManagerPolicyProto.NAVIGATION_BAR;
    145 import static com.android.server.wm.WindowManagerPolicyProto.ORIENTATION;
    146 import static com.android.server.wm.WindowManagerPolicyProto.ORIENTATION_LISTENER;
    147 import static com.android.server.wm.WindowManagerPolicyProto.ROTATION;
    148 import static com.android.server.wm.WindowManagerPolicyProto.ROTATION_MODE;
    149 import static com.android.server.wm.WindowManagerPolicyProto.SCREEN_ON_FULLY;
    150 import static com.android.server.wm.WindowManagerPolicyProto.STATUS_BAR;
    151 import static com.android.server.wm.WindowManagerPolicyProto.TOP_FULLSCREEN_OPAQUE_OR_DIMMING_WINDOW;
    152 import static com.android.server.wm.WindowManagerPolicyProto.TOP_FULLSCREEN_OPAQUE_WINDOW;
    153 import static com.android.server.wm.WindowManagerPolicyProto.WINDOW_MANAGER_DRAW_COMPLETE;
    154 
    155 import android.annotation.Nullable;
    156 import android.app.ActivityManager;
    157 import android.app.ActivityManagerInternal;
    158 import android.app.ActivityManagerInternal.SleepToken;
    159 import android.app.ActivityThread;
    160 import android.app.AppOpsManager;
    161 import android.app.IUiModeManager;
    162 import android.app.ProgressDialog;
    163 import android.app.SearchManager;
    164 import android.app.StatusBarManager;
    165 import android.app.UiModeManager;
    166 import android.content.ActivityNotFoundException;
    167 import android.content.BroadcastReceiver;
    168 import android.content.ContentResolver;
    169 import android.content.Context;
    170 import android.content.Intent;
    171 import android.content.IntentFilter;
    172 import android.content.pm.ActivityInfo;
    173 import android.content.pm.ApplicationInfo;
    174 import android.content.pm.PackageManager;
    175 import android.content.pm.ResolveInfo;
    176 import android.content.res.CompatibilityInfo;
    177 import android.content.res.Configuration;
    178 import android.content.res.Resources;
    179 import android.content.res.TypedArray;
    180 import android.database.ContentObserver;
    181 import android.graphics.PixelFormat;
    182 import android.graphics.Rect;
    183 import android.graphics.drawable.Drawable;
    184 import android.hardware.display.DisplayManager;
    185 import android.hardware.hdmi.HdmiControlManager;
    186 import android.hardware.hdmi.HdmiPlaybackClient;
    187 import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback;
    188 import android.hardware.input.InputManager;
    189 import android.hardware.input.InputManagerInternal;
    190 import android.hardware.power.V1_0.PowerHint;
    191 import android.media.AudioAttributes;
    192 import android.media.AudioManager;
    193 import android.media.AudioManagerInternal;
    194 import android.media.AudioSystem;
    195 import android.media.IAudioService;
    196 import android.media.session.MediaSessionLegacyHelper;
    197 import android.os.Binder;
    198 import android.os.Bundle;
    199 import android.os.FactoryTest;
    200 import android.os.Handler;
    201 import android.os.IBinder;
    202 import android.os.IDeviceIdleController;
    203 import android.os.Looper;
    204 import android.os.Message;
    205 import android.os.PowerManager;
    206 import android.os.PowerManagerInternal;
    207 import android.os.Process;
    208 import android.os.RemoteException;
    209 import android.os.ServiceManager;
    210 import android.os.StrictMode;
    211 import android.os.SystemClock;
    212 import android.os.SystemProperties;
    213 import android.os.UEventObserver;
    214 import android.os.UserHandle;
    215 import android.os.VibrationEffect;
    216 import android.os.Vibrator;
    217 import android.provider.MediaStore;
    218 import android.provider.Settings;
    219 import android.service.dreams.DreamManagerInternal;
    220 import android.service.dreams.DreamService;
    221 import android.service.dreams.IDreamManager;
    222 import android.service.vr.IPersistentVrStateCallbacks;
    223 import android.speech.RecognizerIntent;
    224 import android.telecom.TelecomManager;
    225 import android.util.ArraySet;
    226 import android.util.DisplayMetrics;
    227 import android.util.EventLog;
    228 import android.util.Log;
    229 import android.util.LongSparseArray;
    230 import android.util.MutableBoolean;
    231 import android.util.PrintWriterPrinter;
    232 import android.util.Slog;
    233 import android.util.SparseArray;
    234 import android.util.proto.ProtoOutputStream;
    235 import android.view.Display;
    236 import android.view.DisplayCutout;
    237 import android.view.Gravity;
    238 import android.view.HapticFeedbackConstants;
    239 import android.view.IApplicationToken;
    240 import android.view.IWindowManager;
    241 import android.view.InputChannel;
    242 import android.view.InputDevice;
    243 import android.view.InputEvent;
    244 import android.view.InputEventReceiver;
    245 import android.view.KeyCharacterMap;
    246 import android.view.KeyCharacterMap.FallbackAction;
    247 import android.view.KeyEvent;
    248 import android.view.MotionEvent;
    249 import android.view.PointerIcon;
    250 import android.view.Surface;
    251 import android.view.View;
    252 import android.view.ViewConfiguration;
    253 import android.view.WindowManager;
    254 import android.view.WindowManager.LayoutParams;
    255 import android.view.WindowManagerGlobal;
    256 import android.view.accessibility.AccessibilityEvent;
    257 import android.view.accessibility.AccessibilityManager;
    258 import android.view.animation.Animation;
    259 import android.view.animation.AnimationSet;
    260 import android.view.animation.AnimationUtils;
    261 import android.view.autofill.AutofillManagerInternal;
    262 import android.view.inputmethod.InputMethodManagerInternal;
    263 
    264 import com.android.internal.R;
    265 import com.android.internal.accessibility.AccessibilityShortcutController;
    266 import com.android.internal.annotations.GuardedBy;
    267 import com.android.internal.annotations.VisibleForTesting;
    268 import com.android.internal.logging.MetricsLogger;
    269 import com.android.internal.logging.nano.MetricsProto;
    270 import com.android.internal.policy.IKeyguardDismissCallback;
    271 import com.android.internal.policy.IShortcutService;
    272 import com.android.internal.policy.KeyguardDismissCallback;
    273 import com.android.internal.policy.PhoneWindow;
    274 import com.android.internal.statusbar.IStatusBarService;
    275 import com.android.internal.util.ArrayUtils;
    276 import com.android.internal.util.ScreenshotHelper;
    277 import com.android.internal.util.ScreenShapeHelper;
    278 import com.android.internal.widget.PointerLocationView;
    279 import com.android.server.GestureLauncherService;
    280 import com.android.server.LocalServices;
    281 import com.android.server.SystemServiceManager;
    282 import com.android.server.policy.keyguard.KeyguardServiceDelegate;
    283 import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener;
    284 import com.android.server.policy.keyguard.KeyguardStateMonitor.StateCallback;
    285 import com.android.server.statusbar.StatusBarManagerInternal;
    286 import com.android.server.vr.VrManagerInternal;
    287 import com.android.server.wm.AppTransition;
    288 import com.android.server.wm.DisplayFrames;
    289 import com.android.server.wm.WindowManagerInternal;
    290 import com.android.server.wm.WindowManagerInternal.AppTransitionListener;
    291 
    292 import java.io.File;
    293 import java.io.FileReader;
    294 import java.io.IOException;
    295 import java.io.PrintWriter;
    296 import java.util.List;
    297 
    298 /**
    299  * WindowManagerPolicy implementation for the Android phone UI.  This
    300  * introduces a new method suffix, Lp, for an internal lock of the
    301  * PhoneWindowManager.  This is used to protect some internal state, and
    302  * can be acquired with either the Lw and Li lock held, so has the restrictions
    303  * of both of those when held.
    304  */
    305 public class PhoneWindowManager implements WindowManagerPolicy {
    306     static final String TAG = "WindowManager";
    307     static final boolean DEBUG = false;
    308     static final boolean localLOGV = false;
    309     static final boolean DEBUG_INPUT = false;
    310     static final boolean DEBUG_KEYGUARD = false;
    311     static final boolean DEBUG_LAYOUT = false;
    312     static final boolean DEBUG_SPLASH_SCREEN = false;
    313     static final boolean DEBUG_WAKEUP = false;
    314     static final boolean SHOW_SPLASH_SCREENS = true;
    315 
    316     // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
    317     // No longer recommended for desk docks;
    318     static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
    319 
    320     // Whether to allow devices placed in vr headset viewers to have an alternative Home intent.
    321     static final boolean ENABLE_VR_HEADSET_HOME_CAPTURE = true;
    322 
    323     static final boolean ALTERNATE_CAR_MODE_NAV_SIZE = false;
    324 
    325     static final int SHORT_PRESS_POWER_NOTHING = 0;
    326     static final int SHORT_PRESS_POWER_GO_TO_SLEEP = 1;
    327     static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2;
    328     static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3;
    329     static final int SHORT_PRESS_POWER_GO_HOME = 4;
    330     static final int SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME = 5;
    331 
    332     static final int LONG_PRESS_POWER_NOTHING = 0;
    333     static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
    334     static final int LONG_PRESS_POWER_SHUT_OFF = 2;
    335     static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
    336     static final int LONG_PRESS_POWER_GO_TO_VOICE_ASSIST = 4;
    337 
    338     static final int VERY_LONG_PRESS_POWER_NOTHING = 0;
    339     static final int VERY_LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
    340 
    341     static final int MULTI_PRESS_POWER_NOTHING = 0;
    342     static final int MULTI_PRESS_POWER_THEATER_MODE = 1;
    343     static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2;
    344 
    345     static final int LONG_PRESS_BACK_NOTHING = 0;
    346     static final int LONG_PRESS_BACK_GO_TO_VOICE_ASSIST = 1;
    347 
    348     // These need to match the documentation/constant in
    349     // core/res/res/values/config.xml
    350     static final int LONG_PRESS_HOME_NOTHING = 0;
    351     static final int LONG_PRESS_HOME_ALL_APPS = 1;
    352     static final int LONG_PRESS_HOME_ASSIST = 2;
    353     static final int LAST_LONG_PRESS_HOME_BEHAVIOR = LONG_PRESS_HOME_ASSIST;
    354 
    355     static final int DOUBLE_TAP_HOME_NOTHING = 0;
    356     static final int DOUBLE_TAP_HOME_RECENT_SYSTEM_UI = 1;
    357 
    358     static final int SHORT_PRESS_WINDOW_NOTHING = 0;
    359     static final int SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE = 1;
    360 
    361     static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP = 0;
    362     static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME = 1;
    363 
    364     static final int PENDING_KEY_NULL = -1;
    365 
    366     // Controls navigation bar opacity depending on which workspace stacks are currently
    367     // visible.
    368     // Nav bar is always opaque when either the freeform stack or docked stack is visible.
    369     static final int NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED = 0;
    370     // Nav bar is always translucent when the freeform stack is visible, otherwise always opaque.
    371     static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1;
    372 
    373     static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
    374     static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
    375     static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
    376     static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
    377     static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";
    378     static public final String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot";
    379 
    380     /**
    381      * These are the system UI flags that, when changing, can cause the layout
    382      * of the screen to change.
    383      */
    384     static final int SYSTEM_UI_CHANGING_LAYOUT =
    385               View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
    386             | View.SYSTEM_UI_FLAG_FULLSCREEN
    387             | View.STATUS_BAR_TRANSLUCENT
    388             | View.NAVIGATION_BAR_TRANSLUCENT
    389             | View.STATUS_BAR_TRANSPARENT
    390             | View.NAVIGATION_BAR_TRANSPARENT;
    391 
    392     private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
    393             .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
    394             .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
    395             .build();
    396 
    397     // The panic gesture may become active only after the keyguard is dismissed and the immersive
    398     // app shows again. If that doesn't happen for 30s we drop the gesture.
    399     private static final long PANIC_GESTURE_EXPIRATION = 30000;
    400 
    401     private static final String SYSUI_PACKAGE = "com.android.systemui";
    402     private static final String SYSUI_SCREENSHOT_SERVICE =
    403             "com.android.systemui.screenshot.TakeScreenshotService";
    404     private static final String SYSUI_SCREENSHOT_ERROR_RECEIVER =
    405             "com.android.systemui.screenshot.ScreenshotServiceErrorReceiver";
    406 
    407     /**
    408      * Keyguard stuff
    409      */
    410     private boolean mKeyguardDrawnOnce;
    411 
    412     /* Table of Application Launch keys.  Maps from key codes to intent categories.
    413      *
    414      * These are special keys that are used to launch particular kinds of applications,
    415      * such as a web browser.  HID defines nearly a hundred of them in the Consumer (0x0C)
    416      * usage page.  We don't support quite that many yet...
    417      */
    418     static SparseArray<String> sApplicationLaunchKeyCategories;
    419     static {
    420         sApplicationLaunchKeyCategories = new SparseArray<String>();
    421         sApplicationLaunchKeyCategories.append(
    422                 KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER);
    423         sApplicationLaunchKeyCategories.append(
    424                 KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL);
    425         sApplicationLaunchKeyCategories.append(
    426                 KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS);
    427         sApplicationLaunchKeyCategories.append(
    428                 KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR);
    429         sApplicationLaunchKeyCategories.append(
    430                 KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC);
    431         sApplicationLaunchKeyCategories.append(
    432                 KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
    433     }
    434 
    435     private static final int USER_ACTIVITY_NOTIFICATION_DELAY = 200;
    436 
    437     /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
    438     static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;
    439 
    440     /** Amount of time (in milliseconds) a toast window can be shown. */
    441     public static final int TOAST_WINDOW_TIMEOUT = 3500; // 3.5 seconds
    442 
    443     /**
    444      * Lock protecting internal state.  Must not call out into window
    445      * manager with lock held.  (This lock will be acquired in places
    446      * where the window manager is calling in with its own lock held.)
    447      */
    448     private final Object mLock = new Object();
    449 
    450     Context mContext;
    451     IWindowManager mWindowManager;
    452     WindowManagerFuncs mWindowManagerFuncs;
    453     WindowManagerInternal mWindowManagerInternal;
    454     PowerManager mPowerManager;
    455     ActivityManagerInternal mActivityManagerInternal;
    456     AutofillManagerInternal mAutofillManagerInternal;
    457     InputManagerInternal mInputManagerInternal;
    458     InputMethodManagerInternal mInputMethodManagerInternal;
    459     DreamManagerInternal mDreamManagerInternal;
    460     PowerManagerInternal mPowerManagerInternal;
    461     IStatusBarService mStatusBarService;
    462     StatusBarManagerInternal mStatusBarManagerInternal;
    463     AudioManagerInternal mAudioManagerInternal;
    464     boolean mPreloadedRecentApps;
    465     final Object mServiceAquireLock = new Object();
    466     Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
    467     SearchManager mSearchManager;
    468     AccessibilityManager mAccessibilityManager;
    469     BurnInProtectionHelper mBurnInProtectionHelper;
    470     AppOpsManager mAppOpsManager;
    471     private ScreenshotHelper mScreenshotHelper;
    472     private boolean mHasFeatureWatch;
    473     private boolean mHasFeatureLeanback;
    474 
    475     // Assigned on main thread, accessed on UI thread
    476     volatile VrManagerInternal mVrManagerInternal;
    477 
    478     // Vibrator pattern for haptic feedback of a long press.
    479     long[] mLongPressVibePattern;
    480 
    481     // Vibrator pattern for a short vibration when tapping on a day/month/year date of a Calendar.
    482     long[] mCalendarDateVibePattern;
    483 
    484     // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
    485     long[] mSafeModeEnabledVibePattern;
    486 
    487     /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
    488     boolean mEnableShiftMenuBugReports = false;
    489 
    490     /** Controller that supports enabling an AccessibilityService by holding down the volume keys */
    491     private AccessibilityShortcutController mAccessibilityShortcutController;
    492 
    493     boolean mSafeMode;
    494     private final ArraySet<WindowState> mScreenDecorWindows = new ArraySet<>();
    495     WindowState mStatusBar = null;
    496     private final int[] mStatusBarHeightForRotation = new int[4];
    497     WindowState mNavigationBar = null;
    498     boolean mHasNavigationBar = false;
    499     boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?
    500     @NavigationBarPosition
    501     int mNavigationBarPosition = NAV_BAR_BOTTOM;
    502     int[] mNavigationBarHeightForRotationDefault = new int[4];
    503     int[] mNavigationBarWidthForRotationDefault = new int[4];
    504     int[] mNavigationBarHeightForRotationInCarMode = new int[4];
    505     int[] mNavigationBarWidthForRotationInCarMode = new int[4];
    506 
    507     private LongSparseArray<IShortcutService> mShortcutKeyServices = new LongSparseArray<>();
    508 
    509     // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
    510     // This is for car dock and this is updated from resource.
    511     private boolean mEnableCarDockHomeCapture = true;
    512 
    513     boolean mBootMessageNeedsHiding;
    514     KeyguardServiceDelegate mKeyguardDelegate;
    515     private boolean mKeyguardBound;
    516     final Runnable mWindowManagerDrawCallback = new Runnable() {
    517         @Override
    518         public void run() {
    519             if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!");
    520             mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);
    521         }
    522     };
    523     final DrawnListener mKeyguardDrawnCallback = new DrawnListener() {
    524         @Override
    525         public void onDrawn() {
    526             if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn.");
    527             mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
    528         }
    529     };
    530 
    531     GlobalActions mGlobalActions;
    532     Handler mHandler;
    533     WindowState mLastInputMethodWindow = null;
    534     WindowState mLastInputMethodTargetWindow = null;
    535 
    536     // FIXME This state is shared between the input reader and handler thread.
    537     // Technically it's broken and buggy but it has been like this for many years
    538     // and we have not yet seen any problems.  Someday we'll rewrite this logic
    539     // so that only one thread is involved in handling input policy.  Unfortunately
    540     // it's on a critical path for power management so we can't just post the work to the
    541     // handler thread.  We'll need to resolve this someday by teaching the input dispatcher
    542     // to hold wakelocks during dispatch and eliminating the critical path.
    543     volatile boolean mPowerKeyHandled;
    544     volatile boolean mBackKeyHandled;
    545     volatile boolean mBeganFromNonInteractive;
    546     volatile int mPowerKeyPressCounter;
    547     volatile boolean mEndCallKeyHandled;
    548     volatile boolean mCameraGestureTriggeredDuringGoingToSleep;
    549     volatile boolean mGoingToSleep;
    550     volatile boolean mRequestedOrGoingToSleep;
    551     volatile boolean mRecentsVisible;
    552     volatile boolean mNavBarVirtualKeyHapticFeedbackEnabled = true;
    553     volatile boolean mPictureInPictureVisible;
    554     // Written by vr manager thread, only read in this class.
    555     volatile private boolean mPersistentVrModeEnabled;
    556     volatile private boolean mDismissImeOnBackKeyPressed;
    557 
    558     // Used to hold the last user key used to wake the device.  This helps us prevent up events
    559     // from being passed to the foregrounded app without a corresponding down event
    560     volatile int mPendingWakeKey = PENDING_KEY_NULL;
    561 
    562     int mRecentAppsHeldModifiers;
    563     boolean mLanguageSwitchKeyPressed;
    564 
    565     int mLidState = LID_ABSENT;
    566     int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT;
    567     boolean mHaveBuiltInKeyboard;
    568 
    569     boolean mSystemReady;
    570     boolean mSystemBooted;
    571     boolean mHdmiPlugged;
    572     HdmiControl mHdmiControl;
    573     IUiModeManager mUiModeManager;
    574     int mUiMode;
    575     int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
    576     int mLidOpenRotation;
    577     int mCarDockRotation;
    578     int mDeskDockRotation;
    579     int mUndockedHdmiRotation;
    580     int mDemoHdmiRotation;
    581     boolean mDemoHdmiRotationLock;
    582     int mDemoRotation;
    583     boolean mDemoRotationLock;
    584 
    585     boolean mWakeGestureEnabledSetting;
    586     MyWakeGestureListener mWakeGestureListener;
    587 
    588     // Default display does not rotate, apps that require non-default orientation will have to
    589     // have the orientation emulated.
    590     private boolean mForceDefaultOrientation = false;
    591 
    592     int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
    593     int mUserRotation = Surface.ROTATION_0;
    594 
    595     boolean mSupportAutoRotation;
    596     int mAllowAllRotations = -1;
    597     boolean mCarDockEnablesAccelerometer;
    598     boolean mDeskDockEnablesAccelerometer;
    599     int mLidKeyboardAccessibility;
    600     int mLidNavigationAccessibility;
    601     boolean mLidControlsScreenLock;
    602     boolean mLidControlsSleep;
    603     int mShortPressOnPowerBehavior;
    604     int mLongPressOnPowerBehavior;
    605     int mVeryLongPressOnPowerBehavior;
    606     int mDoublePressOnPowerBehavior;
    607     int mTriplePressOnPowerBehavior;
    608     int mLongPressOnBackBehavior;
    609     int mShortPressOnSleepBehavior;
    610     int mShortPressOnWindowBehavior;
    611     volatile boolean mAwake;
    612     boolean mScreenOnEarly;
    613     boolean mScreenOnFully;
    614     ScreenOnListener mScreenOnListener;
    615     boolean mKeyguardDrawComplete;
    616     boolean mWindowManagerDrawComplete;
    617     boolean mOrientationSensorEnabled = false;
    618     int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
    619     boolean mHasSoftInput = false;
    620     boolean mTranslucentDecorEnabled = true;
    621     boolean mUseTvRouting;
    622     int mVeryLongPressTimeout;
    623     boolean mAllowStartActivityForLongPressOnPowerDuringSetup;
    624     MetricsLogger mLogger;
    625 
    626     private boolean mHandleVolumeKeysInWM;
    627 
    628     int mPointerLocationMode = 0; // guarded by mLock
    629 
    630     // The last window we were told about in focusChanged.
    631     WindowState mFocusedWindow;
    632     IApplicationToken mFocusedApp;
    633 
    634     PointerLocationView mPointerLocationView;
    635 
    636     // During layout, the layer at which the doc window is placed.
    637     int mDockLayer;
    638     // During layout, this is the layer of the status bar.
    639     int mStatusBarLayer;
    640     int mLastSystemUiFlags;
    641     // Bits that we are in the process of clearing, so we want to prevent
    642     // them from being set by applications until everything has been updated
    643     // to have them clear.
    644     int mResettingSystemUiFlags = 0;
    645     // Bits that we are currently always keeping cleared.
    646     int mForceClearedSystemUiFlags = 0;
    647     int mLastFullscreenStackSysUiFlags;
    648     int mLastDockedStackSysUiFlags;
    649     final Rect mNonDockedStackBounds = new Rect();
    650     final Rect mDockedStackBounds = new Rect();
    651     final Rect mLastNonDockedStackBounds = new Rect();
    652     final Rect mLastDockedStackBounds = new Rect();
    653 
    654     // What we last reported to system UI about whether the compatibility
    655     // menu needs to be displayed.
    656     boolean mLastFocusNeedsMenu = false;
    657     // If nonzero, a panic gesture was performed at that time in uptime millis and is still pending.
    658     private long mPendingPanicGestureUptime;
    659 
    660     InputConsumer mInputConsumer = null;
    661 
    662     static final Rect mTmpParentFrame = new Rect();
    663     static final Rect mTmpDisplayFrame = new Rect();
    664     static final Rect mTmpOverscanFrame = new Rect();
    665     static final Rect mTmpContentFrame = new Rect();
    666     static final Rect mTmpVisibleFrame = new Rect();
    667     static final Rect mTmpDecorFrame = new Rect();
    668     static final Rect mTmpStableFrame = new Rect();
    669     static final Rect mTmpNavigationFrame = new Rect();
    670     static final Rect mTmpOutsetFrame = new Rect();
    671     private static final Rect mTmpDisplayCutoutSafeExceptMaybeBarsRect = new Rect();
    672     private static final Rect mTmpRect = new Rect();
    673 
    674     WindowState mTopFullscreenOpaqueWindowState;
    675     WindowState mTopFullscreenOpaqueOrDimmingWindowState;
    676     WindowState mTopDockedOpaqueWindowState;
    677     WindowState mTopDockedOpaqueOrDimmingWindowState;
    678     boolean mTopIsFullscreen;
    679     boolean mForceStatusBar;
    680     boolean mForceStatusBarFromKeyguard;
    681     private boolean mForceStatusBarTransparent;
    682     int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
    683     boolean mForcingShowNavBar;
    684     int mForcingShowNavBarLayer;
    685 
    686     private boolean mPendingKeyguardOccluded;
    687     private boolean mKeyguardOccludedChanged;
    688     private boolean mNotifyUserActivity;
    689 
    690     boolean mShowingDream;
    691     private boolean mLastShowingDream;
    692     boolean mDreamingLockscreen;
    693     boolean mDreamingSleepTokenNeeded;
    694     private boolean mWindowSleepTokenNeeded;
    695     private boolean mLastWindowSleepTokenNeeded;
    696 
    697     @GuardedBy("mHandler")
    698     private SleepToken mWindowSleepToken;
    699 
    700     SleepToken mDreamingSleepToken;
    701     SleepToken mScreenOffSleepToken;
    702     volatile boolean mKeyguardOccluded;
    703     boolean mHomePressed;
    704     boolean mHomeConsumed;
    705     boolean mHomeDoubleTapPending;
    706     Intent mHomeIntent;
    707     Intent mCarDockIntent;
    708     Intent mDeskDockIntent;
    709     Intent mVrHeadsetHomeIntent;
    710     boolean mSearchKeyShortcutPending;
    711     boolean mConsumeSearchKeyUp;
    712     boolean mPendingMetaAction;
    713     boolean mPendingCapsLockToggle;
    714     int mMetaState;
    715     int mInitialMetaState;
    716     boolean mForceShowSystemBars;
    717 
    718     // support for activating the lock screen while the screen is on
    719     boolean mAllowLockscreenWhenOn;
    720     int mLockScreenTimeout;
    721     boolean mLockScreenTimerActive;
    722 
    723     // Behavior of ENDCALL Button.  (See Settings.System.END_BUTTON_BEHAVIOR.)
    724     int mEndcallBehavior;
    725 
    726     // Behavior of POWER button while in-call and screen on.
    727     // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
    728     int mIncallPowerBehavior;
    729 
    730     // Behavior of Back button while in-call and screen on
    731     int mIncallBackBehavior;
    732 
    733     // Behavior of rotation suggestions. (See Settings.Secure.SHOW_ROTATION_SUGGESTION)
    734     int mShowRotationSuggestions;
    735 
    736     // Whether system navigation keys are enabled
    737     boolean mSystemNavigationKeysEnabled;
    738 
    739     Display mDisplay;
    740 
    741     int mLandscapeRotation = 0;  // default landscape rotation
    742     int mSeascapeRotation = 0;   // "other" landscape rotation, 180 degrees from mLandscapeRotation
    743     int mPortraitRotation = 0;   // default portrait rotation
    744     int mUpsideDownRotation = 0; // "other" portrait rotation
    745 
    746     // What we do when the user long presses on home
    747     private int mLongPressOnHomeBehavior;
    748 
    749     // What we do when the user double-taps on home
    750     private int mDoubleTapOnHomeBehavior;
    751 
    752     // Allowed theater mode wake actions
    753     private boolean mAllowTheaterModeWakeFromKey;
    754     private boolean mAllowTheaterModeWakeFromPowerKey;
    755     private boolean mAllowTheaterModeWakeFromMotion;
    756     private boolean mAllowTheaterModeWakeFromMotionWhenNotDreaming;
    757     private boolean mAllowTheaterModeWakeFromCameraLens;
    758     private boolean mAllowTheaterModeWakeFromLidSwitch;
    759     private boolean mAllowTheaterModeWakeFromWakeGesture;
    760 
    761     // Whether to support long press from power button in non-interactive mode
    762     private boolean mSupportLongPressPowerWhenNonInteractive;
    763 
    764     // Whether to go to sleep entering theater mode from power button
    765     private boolean mGoToSleepOnButtonPressTheaterMode;
    766 
    767     // Screenshot trigger states
    768     // Time to volume and power must be pressed within this interval of each other.
    769     private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
    770     // Increase the chord delay when taking a screenshot from the keyguard
    771     private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f;
    772     private boolean mScreenshotChordEnabled;
    773     private boolean mScreenshotChordVolumeDownKeyTriggered;
    774     private long mScreenshotChordVolumeDownKeyTime;
    775     private boolean mScreenshotChordVolumeDownKeyConsumed;
    776     private boolean mA11yShortcutChordVolumeUpKeyTriggered;
    777     private long mA11yShortcutChordVolumeUpKeyTime;
    778     private boolean mA11yShortcutChordVolumeUpKeyConsumed;
    779 
    780     private boolean mScreenshotChordPowerKeyTriggered;
    781     private long mScreenshotChordPowerKeyTime;
    782 
    783     // Ringer toggle should reuse timing and triggering from screenshot power and a11y vol up
    784     private int mRingerToggleChord = VOLUME_HUSH_OFF;
    785 
    786     private static final long BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS = 1000;
    787 
    788     private boolean mBugreportTvKey1Pressed;
    789     private boolean mBugreportTvKey2Pressed;
    790     private boolean mBugreportTvScheduled;
    791 
    792     private boolean mAccessibilityTvKey1Pressed;
    793     private boolean mAccessibilityTvKey2Pressed;
    794     private boolean mAccessibilityTvScheduled;
    795 
    796     /* The number of steps between min and max brightness */
    797     private static final int BRIGHTNESS_STEPS = 10;
    798 
    799     SettingsObserver mSettingsObserver;
    800     ShortcutManager mShortcutManager;
    801     PowerManager.WakeLock mBroadcastWakeLock;
    802     PowerManager.WakeLock mPowerKeyWakeLock;
    803     boolean mHavePendingMediaKeyRepeatWithWakeLock;
    804 
    805     private int mCurrentUserId;
    806 
    807     // Maps global key codes to the components that will handle them.
    808     private GlobalKeyManager mGlobalKeyManager;
    809 
    810     // Fallback actions by key code.
    811     private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions =
    812             new SparseArray<KeyCharacterMap.FallbackAction>();
    813 
    814     private final LogDecelerateInterpolator mLogDecelerateInterpolator
    815             = new LogDecelerateInterpolator(100, 0);
    816 
    817     private final MutableBoolean mTmpBoolean = new MutableBoolean(false);
    818 
    819     private boolean mAodShowing;
    820 
    821     private static final int MSG_ENABLE_POINTER_LOCATION = 1;
    822     private static final int MSG_DISABLE_POINTER_LOCATION = 2;
    823     private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
    824     private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
    825     private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
    826     private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6;
    827     private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7;
    828     private static final int MSG_DISPATCH_SHOW_RECENTS = 9;
    829     private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10;
    830     private static final int MSG_HIDE_BOOT_MESSAGE = 11;
    831     private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12;
    832     private static final int MSG_POWER_DELAYED_PRESS = 13;
    833     private static final int MSG_POWER_LONG_PRESS = 14;
    834     private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 15;
    835     private static final int MSG_REQUEST_TRANSIENT_BARS = 16;
    836     private static final int MSG_SHOW_PICTURE_IN_PICTURE_MENU = 17;
    837     private static final int MSG_BACK_LONG_PRESS = 18;
    838     private static final int MSG_DISPOSE_INPUT_CONSUMER = 19;
    839     private static final int MSG_ACCESSIBILITY_SHORTCUT = 20;
    840     private static final int MSG_BUGREPORT_TV = 21;
    841     private static final int MSG_ACCESSIBILITY_TV = 22;
    842     private static final int MSG_DISPATCH_BACK_KEY_TO_AUTOFILL = 23;
    843     private static final int MSG_SYSTEM_KEY_PRESS = 24;
    844     private static final int MSG_HANDLE_ALL_APPS = 25;
    845     private static final int MSG_LAUNCH_ASSIST = 26;
    846     private static final int MSG_LAUNCH_ASSIST_LONG_PRESS = 27;
    847     private static final int MSG_POWER_VERY_LONG_PRESS = 28;
    848     private static final int MSG_NOTIFY_USER_ACTIVITY = 29;
    849     private static final int MSG_RINGER_TOGGLE_CHORD = 30;
    850 
    851     private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
    852     private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
    853 
    854     private class PolicyHandler extends Handler {
    855         @Override
    856         public void handleMessage(Message msg) {
    857             switch (msg.what) {
    858                 case MSG_ENABLE_POINTER_LOCATION:
    859                     enablePointerLocation();
    860                     break;
    861                 case MSG_DISABLE_POINTER_LOCATION:
    862                     disablePointerLocation();
    863                     break;
    864                 case MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK:
    865                     dispatchMediaKeyWithWakeLock((KeyEvent)msg.obj);
    866                     break;
    867                 case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK:
    868                     dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj);
    869                     break;
    870                 case MSG_DISPATCH_SHOW_RECENTS:
    871                     showRecentApps(false);
    872                     break;
    873                 case MSG_DISPATCH_SHOW_GLOBAL_ACTIONS:
    874                     showGlobalActionsInternal();
    875                     break;
    876                 case MSG_KEYGUARD_DRAWN_COMPLETE:
    877                     if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete");
    878                     finishKeyguardDrawn();
    879                     break;
    880                 case MSG_KEYGUARD_DRAWN_TIMEOUT:
    881                     Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete");
    882                     finishKeyguardDrawn();
    883                     break;
    884                 case MSG_WINDOW_MANAGER_DRAWN_COMPLETE:
    885                     if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete");
    886                     finishWindowsDrawn();
    887                     break;
    888                 case MSG_HIDE_BOOT_MESSAGE:
    889                     handleHideBootMessage();
    890                     break;
    891                 case MSG_LAUNCH_ASSIST:
    892                     final int deviceId = msg.arg1;
    893                     final String hint = (String) msg.obj;
    894                     launchAssistAction(hint, deviceId);
    895                     break;
    896                 case MSG_LAUNCH_ASSIST_LONG_PRESS:
    897                     launchAssistLongPressAction();
    898                     break;
    899                 case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK:
    900                     launchVoiceAssistWithWakeLock();
    901                     break;
    902                 case MSG_POWER_DELAYED_PRESS:
    903                     powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2);
    904                     finishPowerKeyPress();
    905                     break;
    906                 case MSG_POWER_LONG_PRESS:
    907                     powerLongPress();
    908                     break;
    909                 case MSG_POWER_VERY_LONG_PRESS:
    910                     powerVeryLongPress();
    911                     break;
    912                 case MSG_UPDATE_DREAMING_SLEEP_TOKEN:
    913                     updateDreamingSleepToken(msg.arg1 != 0);
    914                     break;
    915                 case MSG_REQUEST_TRANSIENT_BARS:
    916                     WindowState targetBar = (msg.arg1 == MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS) ?
    917                             mStatusBar : mNavigationBar;
    918                     if (targetBar != null) {
    919                         requestTransientBars(targetBar);
    920                     }
    921                     break;
    922                 case MSG_SHOW_PICTURE_IN_PICTURE_MENU:
    923                     showPictureInPictureMenuInternal();
    924                     break;
    925                 case MSG_BACK_LONG_PRESS:
    926                     backLongPress();
    927                     break;
    928                 case MSG_DISPOSE_INPUT_CONSUMER:
    929                     disposeInputConsumer((InputConsumer) msg.obj);
    930                     break;
    931                 case MSG_ACCESSIBILITY_SHORTCUT:
    932                     accessibilityShortcutActivated();
    933                     break;
    934                 case MSG_BUGREPORT_TV:
    935                     requestFullBugreport();
    936                     break;
    937                 case MSG_ACCESSIBILITY_TV:
    938                     if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(false)) {
    939                         accessibilityShortcutActivated();
    940                     }
    941                     break;
    942                 case MSG_DISPATCH_BACK_KEY_TO_AUTOFILL:
    943                     mAutofillManagerInternal.onBackKeyPressed();
    944                     break;
    945                 case MSG_SYSTEM_KEY_PRESS:
    946                     sendSystemKeyToStatusBar(msg.arg1);
    947                     break;
    948                 case MSG_HANDLE_ALL_APPS:
    949                     launchAllAppsAction();
    950                     break;
    951                 case MSG_NOTIFY_USER_ACTIVITY:
    952                     removeMessages(MSG_NOTIFY_USER_ACTIVITY);
    953                     Intent intent = new Intent(ACTION_USER_ACTIVITY_NOTIFICATION);
    954                     intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
    955                     mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
    956                             android.Manifest.permission.USER_ACTIVITY);
    957                 case MSG_RINGER_TOGGLE_CHORD:
    958                     handleRingerChordGesture();
    959                     break;
    960             }
    961         }
    962     }
    963 
    964     private UEventObserver mHDMIObserver = new UEventObserver() {
    965         @Override
    966         public void onUEvent(UEventObserver.UEvent event) {
    967             setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
    968         }
    969     };
    970 
    971     class SettingsObserver extends ContentObserver {
    972         SettingsObserver(Handler handler) {
    973             super(handler);
    974         }
    975 
    976         void observe() {
    977             // Observe all users' changes
    978             ContentResolver resolver = mContext.getContentResolver();
    979             resolver.registerContentObserver(Settings.System.getUriFor(
    980                     Settings.System.END_BUTTON_BEHAVIOR), false, this,
    981                     UserHandle.USER_ALL);
    982             resolver.registerContentObserver(Settings.Secure.getUriFor(
    983                     Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this,
    984                     UserHandle.USER_ALL);
    985             resolver.registerContentObserver(Settings.Secure.getUriFor(
    986                     Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR), false, this,
    987                     UserHandle.USER_ALL);
    988             resolver.registerContentObserver(Settings.Secure.getUriFor(
    989                     Settings.Secure.WAKE_GESTURE_ENABLED), false, this,
    990                     UserHandle.USER_ALL);
    991             resolver.registerContentObserver(Settings.System.getUriFor(
    992                     Settings.System.ACCELEROMETER_ROTATION), false, this,
    993                     UserHandle.USER_ALL);
    994             resolver.registerContentObserver(Settings.System.getUriFor(
    995                     Settings.System.USER_ROTATION), false, this,
    996                     UserHandle.USER_ALL);
    997             resolver.registerContentObserver(Settings.System.getUriFor(
    998                     Settings.System.SCREEN_OFF_TIMEOUT), false, this,
    999                     UserHandle.USER_ALL);
   1000             resolver.registerContentObserver(Settings.System.getUriFor(
   1001                     Settings.System.POINTER_LOCATION), false, this,
   1002                     UserHandle.USER_ALL);
   1003             resolver.registerContentObserver(Settings.Secure.getUriFor(
   1004                     Settings.Secure.DEFAULT_INPUT_METHOD), false, this,
   1005                     UserHandle.USER_ALL);
   1006             resolver.registerContentObserver(Settings.Secure.getUriFor(
   1007                     Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this,
   1008                     UserHandle.USER_ALL);
   1009             resolver.registerContentObserver(Settings.Secure.getUriFor(
   1010                     Settings.Secure.SHOW_ROTATION_SUGGESTIONS), false, this,
   1011                     UserHandle.USER_ALL);
   1012             resolver.registerContentObserver(Settings.Secure.getUriFor(
   1013                     Settings.Secure.VOLUME_HUSH_GESTURE), false, this,
   1014                     UserHandle.USER_ALL);
   1015             resolver.registerContentObserver(Settings.Global.getUriFor(
   1016                     Settings.Global.POLICY_CONTROL), false, this,
   1017                     UserHandle.USER_ALL);
   1018             resolver.registerContentObserver(Settings.Secure.getUriFor(
   1019                     Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED), false, this,
   1020                     UserHandle.USER_ALL);
   1021             updateSettings();
   1022         }
   1023 
   1024         @Override public void onChange(boolean selfChange) {
   1025             updateSettings();
   1026             updateRotation(false);
   1027         }
   1028     }
   1029 
   1030     class MyWakeGestureListener extends WakeGestureListener {
   1031         MyWakeGestureListener(Context context, Handler handler) {
   1032             super(context, handler);
   1033         }
   1034 
   1035         @Override
   1036         public void onWakeUp() {
   1037             synchronized (mLock) {
   1038                 if (shouldEnableWakeGestureLp()) {
   1039                     performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
   1040                     wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture,
   1041                             "android.policy:GESTURE");
   1042                 }
   1043             }
   1044         }
   1045     }
   1046 
   1047     class MyOrientationListener extends WindowOrientationListener {
   1048 
   1049         private SparseArray<Runnable> mRunnableCache;
   1050 
   1051         MyOrientationListener(Context context, Handler handler) {
   1052             super(context, handler);
   1053             mRunnableCache = new SparseArray<>(5);
   1054         }
   1055 
   1056         private class UpdateRunnable implements Runnable {
   1057             private final int mRotation;
   1058             UpdateRunnable(int rotation) {
   1059                 mRotation = rotation;
   1060             }
   1061 
   1062             @Override
   1063             public void run() {
   1064                 // send interaction hint to improve redraw performance
   1065                 mPowerManagerInternal.powerHint(PowerHint.INTERACTION, 0);
   1066                 if (isRotationChoicePossible(mCurrentAppOrientation)) {
   1067                     final boolean isValid = isValidRotationChoice(mCurrentAppOrientation,
   1068                             mRotation);
   1069                     sendProposedRotationChangeToStatusBarInternal(mRotation, isValid);
   1070                 } else {
   1071                     updateRotation(false);
   1072                 }
   1073             }
   1074         }
   1075 
   1076         @Override
   1077         public void onProposedRotationChanged(int rotation) {
   1078             if (localLOGV) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
   1079             Runnable r = mRunnableCache.get(rotation, null);
   1080             if (r == null){
   1081                 r = new UpdateRunnable(rotation);
   1082                 mRunnableCache.put(rotation, r);
   1083             }
   1084             mHandler.post(r);
   1085         }
   1086     }
   1087     MyOrientationListener mOrientationListener;
   1088 
   1089     final IPersistentVrStateCallbacks mPersistentVrModeListener =
   1090             new IPersistentVrStateCallbacks.Stub() {
   1091         @Override
   1092         public void onPersistentVrStateChanged(boolean enabled) {
   1093             mPersistentVrModeEnabled = enabled;
   1094         }
   1095     };
   1096 
   1097     private final StatusBarController mStatusBarController = new StatusBarController();
   1098 
   1099     private final BarController mNavigationBarController = new BarController("NavigationBar",
   1100             View.NAVIGATION_BAR_TRANSIENT,
   1101             View.NAVIGATION_BAR_UNHIDE,
   1102             View.NAVIGATION_BAR_TRANSLUCENT,
   1103             StatusBarManager.WINDOW_NAVIGATION_BAR,
   1104             FLAG_TRANSLUCENT_NAVIGATION,
   1105             View.NAVIGATION_BAR_TRANSPARENT);
   1106 
   1107     private final BarController.OnBarVisibilityChangedListener mNavBarVisibilityListener =
   1108             new BarController.OnBarVisibilityChangedListener() {
   1109         @Override
   1110         public void onBarVisibilityChanged(boolean visible) {
   1111             mAccessibilityManager.notifyAccessibilityButtonVisibilityChanged(visible);
   1112         }
   1113     };
   1114 
   1115     private final Runnable mAcquireSleepTokenRunnable = () -> {
   1116         if (mWindowSleepToken != null) {
   1117             return;
   1118         }
   1119         mWindowSleepToken = mActivityManagerInternal.acquireSleepToken("WindowSleepToken",
   1120                 DEFAULT_DISPLAY);
   1121     };
   1122 
   1123     private final Runnable mReleaseSleepTokenRunnable = () -> {
   1124         if (mWindowSleepToken == null) {
   1125             return;
   1126         }
   1127         mWindowSleepToken.release();
   1128         mWindowSleepToken = null;
   1129     };
   1130 
   1131     private ImmersiveModeConfirmation mImmersiveModeConfirmation;
   1132 
   1133     @VisibleForTesting
   1134     SystemGesturesPointerEventListener mSystemGestures;
   1135 
   1136     private void handleRingerChordGesture() {
   1137         if (mRingerToggleChord == VOLUME_HUSH_OFF) {
   1138             return;
   1139         }
   1140         getAudioManagerInternal();
   1141         mAudioManagerInternal.silenceRingerModeInternal("volume_hush");
   1142         Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.HUSH_GESTURE_USED, 1);
   1143         mLogger.action(MetricsProto.MetricsEvent.ACTION_HUSH_GESTURE, mRingerToggleChord);
   1144     }
   1145 
   1146     IStatusBarService getStatusBarService() {
   1147         synchronized (mServiceAquireLock) {
   1148             if (mStatusBarService == null) {
   1149                 mStatusBarService = IStatusBarService.Stub.asInterface(
   1150                         ServiceManager.getService("statusbar"));
   1151             }
   1152             return mStatusBarService;
   1153         }
   1154     }
   1155 
   1156     StatusBarManagerInternal getStatusBarManagerInternal() {
   1157         synchronized (mServiceAquireLock) {
   1158             if (mStatusBarManagerInternal == null) {
   1159                 mStatusBarManagerInternal =
   1160                         LocalServices.getService(StatusBarManagerInternal.class);
   1161             }
   1162             return mStatusBarManagerInternal;
   1163         }
   1164     }
   1165 
   1166     AudioManagerInternal getAudioManagerInternal() {
   1167         synchronized (mServiceAquireLock) {
   1168             if (mAudioManagerInternal == null) {
   1169                 mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
   1170             }
   1171             return mAudioManagerInternal;
   1172         }
   1173     }
   1174 
   1175     /*
   1176      * We always let the sensor be switched on by default except when
   1177      * the user has explicitly disabled sensor based rotation or when the
   1178      * screen is switched off.
   1179      */
   1180     boolean needSensorRunningLp() {
   1181         if (mSupportAutoRotation) {
   1182             if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
   1183                     || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
   1184                     || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
   1185                     || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
   1186                 // If the application has explicitly requested to follow the
   1187                 // orientation, then we need to turn the sensor on.
   1188                 return true;
   1189             }
   1190         }
   1191         if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
   1192                 (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
   1193                         || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
   1194                         || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
   1195             // enable accelerometer if we are docked in a dock that enables accelerometer
   1196             // orientation management,
   1197             return true;
   1198         }
   1199         if (mUserRotationMode == USER_ROTATION_LOCKED) {
   1200             // If the setting for using the sensor by default is enabled, then
   1201             // we will always leave it on.  Note that the user could go to
   1202             // a window that forces an orientation that does not use the
   1203             // sensor and in theory we could turn it off... however, when next
   1204             // turning it on we won't have a good value for the current
   1205             // orientation for a little bit, which can cause orientation
   1206             // changes to lag, so we'd like to keep it always on.  (It will
   1207             // still be turned off when the screen is off.)
   1208 
   1209             // When locked we can provide rotation suggestions users can approve to change the
   1210             // current screen rotation. To do this the sensor needs to be running.
   1211             return mSupportAutoRotation &&
   1212                     mShowRotationSuggestions == Settings.Secure.SHOW_ROTATION_SUGGESTIONS_ENABLED;
   1213         }
   1214         return mSupportAutoRotation;
   1215     }
   1216 
   1217     /*
   1218      * Various use cases for invoking this function
   1219      * screen turning off, should always disable listeners if already enabled
   1220      * screen turned on and current app has sensor based orientation, enable listeners
   1221      * if not already enabled
   1222      * screen turned on and current app does not have sensor orientation, disable listeners if
   1223      * already enabled
   1224      * screen turning on and current app has sensor based orientation, enable listeners if needed
   1225      * screen turning on and current app has nosensor based orientation, do nothing
   1226      */
   1227     void updateOrientationListenerLp() {
   1228         if (!mOrientationListener.canDetectOrientation()) {
   1229             // If sensor is turned off or nonexistent for some reason
   1230             return;
   1231         }
   1232         // Could have been invoked due to screen turning on or off or
   1233         // change of the currently visible window's orientation.
   1234         if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly
   1235                 + ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation
   1236                 + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled
   1237                 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
   1238                 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
   1239 
   1240         boolean disable = true;
   1241         // Note: We postpone the rotating of the screen until the keyguard as well as the
   1242         // window manager have reported a draw complete or the keyguard is going away in dismiss
   1243         // mode.
   1244         if (mScreenOnEarly && mAwake && ((mKeyguardDrawComplete && mWindowManagerDrawComplete))) {
   1245             if (needSensorRunningLp()) {
   1246                 disable = false;
   1247                 //enable listener if not already enabled
   1248                 if (!mOrientationSensorEnabled) {
   1249                     // Don't clear the current sensor orientation if the keyguard is going away in
   1250                     // dismiss mode. This allows window manager to use the last sensor reading to
   1251                     // determine the orientation vs. falling back to the last known orientation if
   1252                     // the sensor reading was cleared which can cause it to relaunch the app that
   1253                     // will show in the wrong orientation first before correcting leading to app
   1254                     // launch delays.
   1255                     mOrientationListener.enable(true /* clearCurrentRotation */);
   1256                     if(localLOGV) Slog.v(TAG, "Enabling listeners");
   1257                     mOrientationSensorEnabled = true;
   1258                 }
   1259             }
   1260         }
   1261         //check if sensors need to be disabled
   1262         if (disable && mOrientationSensorEnabled) {
   1263             mOrientationListener.disable();
   1264             if(localLOGV) Slog.v(TAG, "Disabling listeners");
   1265             mOrientationSensorEnabled = false;
   1266         }
   1267     }
   1268 
   1269     private void interceptBackKeyDown() {
   1270         MetricsLogger.count(mContext, "key_back_down", 1);
   1271         // Reset back key state for long press
   1272         mBackKeyHandled = false;
   1273 
   1274         if (hasLongPressOnBackBehavior()) {
   1275             Message msg = mHandler.obtainMessage(MSG_BACK_LONG_PRESS);
   1276             msg.setAsynchronous(true);
   1277             mHandler.sendMessageDelayed(msg,
   1278                     ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
   1279         }
   1280     }
   1281 
   1282     // returns true if the key was handled and should not be passed to the user
   1283     private boolean interceptBackKeyUp(KeyEvent event) {
   1284         // Cache handled state
   1285         boolean handled = mBackKeyHandled;
   1286 
   1287         // Reset back long press state
   1288         cancelPendingBackKeyAction();
   1289 
   1290         if (mHasFeatureWatch) {
   1291             TelecomManager telecomManager = getTelecommService();
   1292 
   1293             if (telecomManager != null) {
   1294                 if (telecomManager.isRinging()) {
   1295                     // Pressing back while there's a ringing incoming
   1296                     // call should silence the ringer.
   1297                     telecomManager.silenceRinger();
   1298 
   1299                     // It should not prevent navigating away
   1300                     return false;
   1301                 } else if (
   1302                     (mIncallBackBehavior & Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_HANGUP) != 0
   1303                         && telecomManager.isInCall()) {
   1304                     // Otherwise, if "Back button ends call" is enabled,
   1305                     // the Back button will hang up any current active call.
   1306                     return telecomManager.endCall();
   1307                 }
   1308             }
   1309         }
   1310 
   1311         if (mAutofillManagerInternal != null && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
   1312             mHandler.sendMessage(mHandler.obtainMessage(MSG_DISPATCH_BACK_KEY_TO_AUTOFILL));
   1313         }
   1314 
   1315         return handled;
   1316     }
   1317 
   1318     private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
   1319         // Hold a wake lock until the power key is released.
   1320         if (!mPowerKeyWakeLock.isHeld()) {
   1321             mPowerKeyWakeLock.acquire();
   1322         }
   1323 
   1324         // Cancel multi-press detection timeout.
   1325         if (mPowerKeyPressCounter != 0) {
   1326             mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);
   1327         }
   1328 
   1329         // Detect user pressing the power button in panic when an application has
   1330         // taken over the whole screen.
   1331         boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
   1332                 SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags),
   1333                 isNavBarEmpty(mLastSystemUiFlags));
   1334         if (panic) {
   1335             mHandler.post(mHiddenNavPanic);
   1336         }
   1337 
   1338         // Abort possibly stuck animations.
   1339         mHandler.post(mWindowManagerFuncs::triggerAnimationFailsafe);
   1340 
   1341         // Latch power key state to detect screenshot chord.
   1342         if (interactive && !mScreenshotChordPowerKeyTriggered
   1343                 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
   1344             mScreenshotChordPowerKeyTriggered = true;
   1345             mScreenshotChordPowerKeyTime = event.getDownTime();
   1346             interceptScreenshotChord();
   1347             interceptRingerToggleChord();
   1348         }
   1349 
   1350         // Stop ringing or end call if configured to do so when power is pressed.
   1351         TelecomManager telecomManager = getTelecommService();
   1352         boolean hungUp = false;
   1353         if (telecomManager != null) {
   1354             if (telecomManager.isRinging()) {
   1355                 // Pressing Power while there's a ringing incoming
   1356                 // call should silence the ringer.
   1357                 telecomManager.silenceRinger();
   1358             } else if ((mIncallPowerBehavior
   1359                     & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
   1360                     && telecomManager.isInCall() && interactive) {
   1361                 // Otherwise, if "Power button ends call" is enabled,
   1362                 // the Power button will hang up any current active call.
   1363                 hungUp = telecomManager.endCall();
   1364             }
   1365         }
   1366 
   1367         GestureLauncherService gestureService = LocalServices.getService(
   1368                 GestureLauncherService.class);
   1369         boolean gesturedServiceIntercepted = false;
   1370         if (gestureService != null) {
   1371             gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive,
   1372                     mTmpBoolean);
   1373             if (mTmpBoolean.value && mRequestedOrGoingToSleep) {
   1374                 mCameraGestureTriggeredDuringGoingToSleep = true;
   1375             }
   1376         }
   1377 
   1378         // Inform the StatusBar; but do not allow it to consume the event.
   1379         sendSystemKeyToStatusBarAsync(event.getKeyCode());
   1380 
   1381         // If the power key has still not yet been handled, then detect short
   1382         // press, long press, or multi press and decide what to do.
   1383         mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
   1384                 || mA11yShortcutChordVolumeUpKeyTriggered || gesturedServiceIntercepted;
   1385         if (!mPowerKeyHandled) {
   1386             if (interactive) {
   1387                 // When interactive, we're already awake.
   1388                 // Wait for a long press or for the button to be released to decide what to do.
   1389                 if (hasLongPressOnPowerBehavior()) {
   1390                     if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
   1391                         powerLongPress();
   1392                     } else {
   1393                         Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
   1394                         msg.setAsynchronous(true);
   1395                         mHandler.sendMessageDelayed(msg,
   1396                                 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
   1397 
   1398                         if (hasVeryLongPressOnPowerBehavior()) {
   1399                             Message longMsg = mHandler.obtainMessage(MSG_POWER_VERY_LONG_PRESS);
   1400                             longMsg.setAsynchronous(true);
   1401                             mHandler.sendMessageDelayed(longMsg, mVeryLongPressTimeout);
   1402                         }
   1403                     }
   1404                 }
   1405             } else {
   1406                 wakeUpFromPowerKey(event.getDownTime());
   1407 
   1408                 if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
   1409                     if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
   1410                         powerLongPress();
   1411                     } else {
   1412                         Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
   1413                         msg.setAsynchronous(true);
   1414                         mHandler.sendMessageDelayed(msg,
   1415                                 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
   1416 
   1417                         if (hasVeryLongPressOnPowerBehavior()) {
   1418                             Message longMsg = mHandler.obtainMessage(MSG_POWER_VERY_LONG_PRESS);
   1419                             longMsg.setAsynchronous(true);
   1420                             mHandler.sendMessageDelayed(longMsg, mVeryLongPressTimeout);
   1421                         }
   1422                     }
   1423 
   1424                     mBeganFromNonInteractive = true;
   1425                 } else {
   1426                     final int maxCount = getMaxMultiPressPowerCount();
   1427 
   1428                     if (maxCount <= 1) {
   1429                         mPowerKeyHandled = true;
   1430                     } else {
   1431                         mBeganFromNonInteractive = true;
   1432                     }
   1433                 }
   1434             }
   1435         }
   1436     }
   1437 
   1438     private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
   1439         final boolean handled = canceled || mPowerKeyHandled;
   1440         mScreenshotChordPowerKeyTriggered = false;
   1441         cancelPendingScreenshotChordAction();
   1442         cancelPendingPowerKeyAction();
   1443 
   1444         if (!handled) {
   1445             // Figure out how to handle the key now that it has been released.
   1446             mPowerKeyPressCounter += 1;
   1447 
   1448             final int maxCount = getMaxMultiPressPowerCount();
   1449             final long eventTime = event.getDownTime();
   1450             if (mPowerKeyPressCounter < maxCount) {
   1451                 // This could be a multi-press.  Wait a little bit longer to confirm.
   1452                 // Continue holding the wake lock.
   1453                 Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
   1454                         interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
   1455                 msg.setAsynchronous(true);
   1456                 mHandler.sendMessageDelayed(msg, ViewConfiguration.getMultiPressTimeout());
   1457                 return;
   1458             }
   1459 
   1460             // No other actions.  Handle it immediately.
   1461             powerPress(eventTime, interactive, mPowerKeyPressCounter);
   1462         }
   1463 
   1464         // Done.  Reset our state.
   1465         finishPowerKeyPress();
   1466     }
   1467 
   1468     private void finishPowerKeyPress() {
   1469         mBeganFromNonInteractive = false;
   1470         mPowerKeyPressCounter = 0;
   1471         if (mPowerKeyWakeLock.isHeld()) {
   1472             mPowerKeyWakeLock.release();
   1473         }
   1474     }
   1475 
   1476     private void cancelPendingPowerKeyAction() {
   1477         if (!mPowerKeyHandled) {
   1478             mPowerKeyHandled = true;
   1479             mHandler.removeMessages(MSG_POWER_LONG_PRESS);
   1480         }
   1481         if (hasVeryLongPressOnPowerBehavior()) {
   1482             mHandler.removeMessages(MSG_POWER_VERY_LONG_PRESS);
   1483         }
   1484     }
   1485 
   1486     private void cancelPendingBackKeyAction() {
   1487         if (!mBackKeyHandled) {
   1488             mBackKeyHandled = true;
   1489             mHandler.removeMessages(MSG_BACK_LONG_PRESS);
   1490         }
   1491     }
   1492 
   1493     private void powerPress(long eventTime, boolean interactive, int count) {
   1494         if (mScreenOnEarly && !mScreenOnFully) {
   1495             Slog.i(TAG, "Suppressed redundant power key press while "
   1496                     + "already in the process of turning the screen on.");
   1497             return;
   1498         }
   1499         Slog.d(TAG, "powerPress: eventTime=" + eventTime + " interactive=" + interactive
   1500                 + " count=" + count + " beganFromNonInteractive=" + mBeganFromNonInteractive +
   1501                 " mShortPressOnPowerBehavior=" + mShortPressOnPowerBehavior);
   1502 
   1503         if (count == 2) {
   1504             powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
   1505         } else if (count == 3) {
   1506             powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
   1507         } else if (interactive && !mBeganFromNonInteractive) {
   1508             switch (mShortPressOnPowerBehavior) {
   1509                 case SHORT_PRESS_POWER_NOTHING:
   1510                     break;
   1511                 case SHORT_PRESS_POWER_GO_TO_SLEEP:
   1512                     goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
   1513                     break;
   1514                 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
   1515                     goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
   1516                             PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
   1517                     break;
   1518                 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
   1519                     goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
   1520                             PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
   1521                     launchHomeFromHotKey();
   1522                     break;
   1523                 case SHORT_PRESS_POWER_GO_HOME:
   1524                     shortPressPowerGoHome();
   1525                     break;
   1526                 case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME: {
   1527                     if (mDismissImeOnBackKeyPressed) {
   1528                         if (mInputMethodManagerInternal == null) {
   1529                             mInputMethodManagerInternal =
   1530                                     LocalServices.getService(InputMethodManagerInternal.class);
   1531                         }
   1532                         if (mInputMethodManagerInternal != null) {
   1533                             mInputMethodManagerInternal.hideCurrentInputMethod();
   1534                         }
   1535                     } else {
   1536                         shortPressPowerGoHome();
   1537                     }
   1538                     break;
   1539                 }
   1540             }
   1541         }
   1542     }
   1543 
   1544     private void goToSleep(long eventTime, int reason, int flags) {
   1545         mRequestedOrGoingToSleep = true;
   1546         mPowerManager.goToSleep(eventTime, reason, flags);
   1547     }
   1548 
   1549     private void shortPressPowerGoHome() {
   1550         launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
   1551         if (isKeyguardShowingAndNotOccluded()) {
   1552             // Notify keyguard so it can do any special handling for the power button since the
   1553             // device will not power off and only launch home.
   1554             mKeyguardDelegate.onShortPowerPressedGoHome();
   1555         }
   1556     }
   1557 
   1558     private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) {
   1559         switch (behavior) {
   1560             case MULTI_PRESS_POWER_NOTHING:
   1561                 break;
   1562             case MULTI_PRESS_POWER_THEATER_MODE:
   1563                 if (!isUserSetupComplete()) {
   1564                     Slog.i(TAG, "Ignoring toggling theater mode - device not setup.");
   1565                     break;
   1566                 }
   1567 
   1568                 if (isTheaterModeEnabled()) {
   1569                     Slog.i(TAG, "Toggling theater mode off.");
   1570                     Settings.Global.putInt(mContext.getContentResolver(),
   1571                             Settings.Global.THEATER_MODE_ON, 0);
   1572                     if (!interactive) {
   1573                         wakeUpFromPowerKey(eventTime);
   1574                     }
   1575                 } else {
   1576                     Slog.i(TAG, "Toggling theater mode on.");
   1577                     Settings.Global.putInt(mContext.getContentResolver(),
   1578                             Settings.Global.THEATER_MODE_ON, 1);
   1579 
   1580                     if (mGoToSleepOnButtonPressTheaterMode && interactive) {
   1581                         goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
   1582                     }
   1583                 }
   1584                 break;
   1585             case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
   1586                 Slog.i(TAG, "Starting brightness boost.");
   1587                 if (!interactive) {
   1588                     wakeUpFromPowerKey(eventTime);
   1589                 }
   1590                 mPowerManager.boostScreenBrightness(eventTime);
   1591                 break;
   1592         }
   1593     }
   1594 
   1595     private int getMaxMultiPressPowerCount() {
   1596         if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
   1597             return 3;
   1598         }
   1599         if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
   1600             return 2;
   1601         }
   1602         return 1;
   1603     }
   1604 
   1605     private void powerLongPress() {
   1606         final int behavior = getResolvedLongPressOnPowerBehavior();
   1607         switch (behavior) {
   1608         case LONG_PRESS_POWER_NOTHING:
   1609             break;
   1610         case LONG_PRESS_POWER_GLOBAL_ACTIONS:
   1611             mPowerKeyHandled = true;
   1612             performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
   1613             showGlobalActionsInternal();
   1614             break;
   1615         case LONG_PRESS_POWER_SHUT_OFF:
   1616         case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
   1617             mPowerKeyHandled = true;
   1618             performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
   1619             sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
   1620             mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
   1621             break;
   1622         case LONG_PRESS_POWER_GO_TO_VOICE_ASSIST:
   1623             mPowerKeyHandled = true;
   1624             performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
   1625             final boolean keyguardActive = mKeyguardDelegate == null
   1626                     ? false
   1627                     : mKeyguardDelegate.isShowing();
   1628             if (!keyguardActive) {
   1629                 Intent intent = new Intent(Intent.ACTION_VOICE_ASSIST);
   1630                 if (mAllowStartActivityForLongPressOnPowerDuringSetup) {
   1631                     mContext.startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
   1632                 } else {
   1633                     startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
   1634                 }
   1635             }
   1636             break;
   1637         }
   1638     }
   1639 
   1640     private void powerVeryLongPress() {
   1641         switch (mVeryLongPressOnPowerBehavior) {
   1642         case VERY_LONG_PRESS_POWER_NOTHING:
   1643             break;
   1644         case VERY_LONG_PRESS_POWER_GLOBAL_ACTIONS:
   1645             mPowerKeyHandled = true;
   1646             performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
   1647             showGlobalActionsInternal();
   1648             break;
   1649         }
   1650     }
   1651 
   1652     private void backLongPress() {
   1653         mBackKeyHandled = true;
   1654 
   1655         switch (mLongPressOnBackBehavior) {
   1656             case LONG_PRESS_BACK_NOTHING:
   1657                 break;
   1658             case LONG_PRESS_BACK_GO_TO_VOICE_ASSIST:
   1659                 final boolean keyguardActive = mKeyguardDelegate == null
   1660                         ? false
   1661                         : mKeyguardDelegate.isShowing();
   1662                 if (!keyguardActive) {
   1663                     Intent intent = new Intent(Intent.ACTION_VOICE_ASSIST);
   1664                     startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
   1665                 }
   1666                 break;
   1667         }
   1668     }
   1669 
   1670     private void accessibilityShortcutActivated() {
   1671         mAccessibilityShortcutController.performAccessibilityShortcut();
   1672     }
   1673 
   1674     private void disposeInputConsumer(InputConsumer inputConsumer) {
   1675         if (inputConsumer != null) {
   1676             inputConsumer.dismiss();
   1677         }
   1678     }
   1679 
   1680     private void sleepPress() {
   1681         if (mShortPressOnSleepBehavior == SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME) {
   1682             launchHomeFromHotKey(false /* awakenDreams */, true /*respectKeyguard*/);
   1683         }
   1684     }
   1685 
   1686     private void sleepRelease(long eventTime) {
   1687         switch (mShortPressOnSleepBehavior) {
   1688             case SHORT_PRESS_SLEEP_GO_TO_SLEEP:
   1689             case SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME:
   1690                 Slog.i(TAG, "sleepRelease() calling goToSleep(GO_TO_SLEEP_REASON_SLEEP_BUTTON)");
   1691                 goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON, 0);
   1692                 break;
   1693         }
   1694     }
   1695 
   1696     private int getResolvedLongPressOnPowerBehavior() {
   1697         if (FactoryTest.isLongPressOnPowerOffEnabled()) {
   1698             return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
   1699         }
   1700         return mLongPressOnPowerBehavior;
   1701     }
   1702 
   1703     private boolean hasLongPressOnPowerBehavior() {
   1704         return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;
   1705     }
   1706 
   1707     private boolean hasVeryLongPressOnPowerBehavior() {
   1708         return mVeryLongPressOnPowerBehavior != VERY_LONG_PRESS_POWER_NOTHING;
   1709     }
   1710 
   1711     private boolean hasLongPressOnBackBehavior() {
   1712         return mLongPressOnBackBehavior != LONG_PRESS_BACK_NOTHING;
   1713     }
   1714 
   1715     private void interceptScreenshotChord() {
   1716         if (mScreenshotChordEnabled
   1717                 && mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered
   1718                 && !mA11yShortcutChordVolumeUpKeyTriggered) {
   1719             final long now = SystemClock.uptimeMillis();
   1720             if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
   1721                     && now <= mScreenshotChordPowerKeyTime
   1722                             + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
   1723                 mScreenshotChordVolumeDownKeyConsumed = true;
   1724                 cancelPendingPowerKeyAction();
   1725                 mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
   1726                 mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
   1727             }
   1728         }
   1729     }
   1730 
   1731     private void interceptAccessibilityShortcutChord() {
   1732         if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(isKeyguardLocked())
   1733                 && mScreenshotChordVolumeDownKeyTriggered && mA11yShortcutChordVolumeUpKeyTriggered
   1734                 && !mScreenshotChordPowerKeyTriggered) {
   1735             final long now = SystemClock.uptimeMillis();
   1736             if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
   1737                     && now <= mA11yShortcutChordVolumeUpKeyTime
   1738                     + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
   1739                 mScreenshotChordVolumeDownKeyConsumed = true;
   1740                 mA11yShortcutChordVolumeUpKeyConsumed = true;
   1741                 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_ACCESSIBILITY_SHORTCUT),
   1742                         getAccessibilityShortcutTimeout());
   1743             }
   1744         }
   1745     }
   1746 
   1747     private void interceptRingerToggleChord() {
   1748         if (mRingerToggleChord != Settings.Secure.VOLUME_HUSH_OFF
   1749                 && mScreenshotChordPowerKeyTriggered && mA11yShortcutChordVolumeUpKeyTriggered) {
   1750             final long now = SystemClock.uptimeMillis();
   1751             if (now <= mA11yShortcutChordVolumeUpKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
   1752                     && now <= mScreenshotChordPowerKeyTime
   1753                     + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
   1754                 mA11yShortcutChordVolumeUpKeyConsumed = true;
   1755                 cancelPendingPowerKeyAction();
   1756 
   1757                 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RINGER_TOGGLE_CHORD),
   1758                         getRingerToggleChordDelay());
   1759             }
   1760         }
   1761     }
   1762 
   1763     private long getAccessibilityShortcutTimeout() {
   1764         ViewConfiguration config = ViewConfiguration.get(mContext);
   1765         return Settings.Secure.getIntForUser(mContext.getContentResolver(),
   1766                 Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0, mCurrentUserId) == 0
   1767                 ? config.getAccessibilityShortcutKeyTimeout()
   1768                 : config.getAccessibilityShortcutKeyTimeoutAfterConfirmation();
   1769     }
   1770 
   1771     private long getScreenshotChordLongPressDelay() {
   1772         if (mKeyguardDelegate.isShowing()) {
   1773             // Double the time it takes to take a screenshot from the keyguard
   1774             return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER *
   1775                     ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
   1776         }
   1777         return ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout();
   1778     }
   1779 
   1780     private long getRingerToggleChordDelay() {
   1781         // Always timeout like a tap
   1782         return ViewConfiguration.getTapTimeout();
   1783     }
   1784 
   1785     private void cancelPendingScreenshotChordAction() {
   1786         mHandler.removeCallbacks(mScreenshotRunnable);
   1787     }
   1788 
   1789     private void cancelPendingAccessibilityShortcutAction() {
   1790         mHandler.removeMessages(MSG_ACCESSIBILITY_SHORTCUT);
   1791     }
   1792 
   1793     private void cancelPendingRingerToggleChordAction() {
   1794         mHandler.removeMessages(MSG_RINGER_TOGGLE_CHORD);
   1795     }
   1796 
   1797     private final Runnable mEndCallLongPress = new Runnable() {
   1798         @Override
   1799         public void run() {
   1800             mEndCallKeyHandled = true;
   1801             performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
   1802             showGlobalActionsInternal();
   1803         }
   1804     };
   1805 
   1806     private class ScreenshotRunnable implements Runnable {
   1807         private int mScreenshotType = TAKE_SCREENSHOT_FULLSCREEN;
   1808 
   1809         public void setScreenshotType(int screenshotType) {
   1810             mScreenshotType = screenshotType;
   1811         }
   1812 
   1813         @Override
   1814         public void run() {
   1815             mScreenshotHelper.takeScreenshot(mScreenshotType,
   1816                     mStatusBar != null && mStatusBar.isVisibleLw(),
   1817                     mNavigationBar != null && mNavigationBar.isVisibleLw(), mHandler);
   1818         }
   1819     }
   1820 
   1821     private final ScreenshotRunnable mScreenshotRunnable = new ScreenshotRunnable();
   1822 
   1823     @Override
   1824     public void showGlobalActions() {
   1825         mHandler.removeMessages(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
   1826         mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
   1827     }
   1828 
   1829     void showGlobalActionsInternal() {
   1830         if (mGlobalActions == null) {
   1831             mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
   1832         }
   1833         final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();
   1834         mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
   1835         if (keyguardShowing) {
   1836             // since it took two seconds of long press to bring this up,
   1837             // poke the wake lock so they have some time to see the dialog.
   1838             mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
   1839         }
   1840     }
   1841 
   1842     boolean isDeviceProvisioned() {
   1843         return Settings.Global.getInt(
   1844                 mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
   1845     }
   1846 
   1847     boolean isUserSetupComplete() {
   1848         boolean isSetupComplete = Settings.Secure.getIntForUser(mContext.getContentResolver(),
   1849                 Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
   1850         if (mHasFeatureLeanback) {
   1851             isSetupComplete &= isTvUserSetupComplete();
   1852         }
   1853         return isSetupComplete;
   1854     }
   1855 
   1856     private boolean isTvUserSetupComplete() {
   1857         return Settings.Secure.getIntForUser(mContext.getContentResolver(),
   1858                 Settings.Secure.TV_USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
   1859     }
   1860 
   1861     private void handleShortPressOnHome() {
   1862         // Turn on the connected TV and switch HDMI input if we're a HDMI playback device.
   1863         final HdmiControl hdmiControl = getHdmiControl();
   1864         if (hdmiControl != null) {
   1865             hdmiControl.turnOnTv();
   1866         }
   1867 
   1868         // If there's a dream running then use home to escape the dream
   1869         // but don't actually go home.
   1870         if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) {
   1871             mDreamManagerInternal.stopDream(false /*immediate*/);
   1872             return;
   1873         }
   1874 
   1875         // Go home!
   1876         launchHomeFromHotKey();
   1877     }
   1878 
   1879     /**
   1880      * Creates an accessor to HDMI control service that performs the operation of
   1881      * turning on TV (optional) and switching input to us. If HDMI control service
   1882      * is not available or we're not a HDMI playback device, the operation is no-op.
   1883      * @return {@link HdmiControl} instance if available, null otherwise.
   1884      */
   1885     private HdmiControl getHdmiControl() {
   1886         if (null == mHdmiControl) {
   1887             if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
   1888                 return null;
   1889             }
   1890             HdmiControlManager manager = (HdmiControlManager) mContext.getSystemService(
   1891                         Context.HDMI_CONTROL_SERVICE);
   1892             HdmiPlaybackClient client = null;
   1893             if (manager != null) {
   1894                 client = manager.getPlaybackClient();
   1895             }
   1896             mHdmiControl = new HdmiControl(client);
   1897         }
   1898         return mHdmiControl;
   1899     }
   1900 
   1901     private static class HdmiControl {
   1902         private final HdmiPlaybackClient mClient;
   1903 
   1904         private HdmiControl(HdmiPlaybackClient client) {
   1905             mClient = client;
   1906         }
   1907 
   1908         public void turnOnTv() {
   1909             if (mClient == null) {
   1910                 return;
   1911             }
   1912             mClient.oneTouchPlay(new OneTouchPlayCallback() {
   1913                 @Override
   1914                 public void onComplete(int result) {
   1915                     if (result != HdmiControlManager.RESULT_SUCCESS) {
   1916                         Log.w(TAG, "One touch play failed: " + result);
   1917                     }
   1918                 }
   1919             });
   1920         }
   1921     }
   1922 
   1923     private void handleLongPressOnHome(int deviceId) {
   1924         if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_NOTHING) {
   1925             return;
   1926         }
   1927         mHomeConsumed = true;
   1928         performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
   1929         switch (mLongPressOnHomeBehavior) {
   1930             case LONG_PRESS_HOME_ALL_APPS:
   1931                 launchAllAppsAction();
   1932                 break;
   1933             case LONG_PRESS_HOME_ASSIST:
   1934                 launchAssistAction(null, deviceId);
   1935                 break;
   1936             default:
   1937                 Log.w(TAG, "Undefined home long press behavior: " + mLongPressOnHomeBehavior);
   1938                 break;
   1939         }
   1940     }
   1941 
   1942     private void launchAllAppsAction() {
   1943         Intent intent = new Intent(Intent.ACTION_ALL_APPS);
   1944         if (mHasFeatureLeanback) {
   1945             final PackageManager pm = mContext.getPackageManager();
   1946             Intent intentLauncher = new Intent(Intent.ACTION_MAIN);
   1947             intentLauncher.addCategory(Intent.CATEGORY_HOME);
   1948             ResolveInfo resolveInfo = pm.resolveActivityAsUser(intentLauncher,
   1949                     PackageManager.MATCH_SYSTEM_ONLY,
   1950                     mCurrentUserId);
   1951             if (resolveInfo != null) {
   1952                 intent.setPackage(resolveInfo.activityInfo.packageName);
   1953             }
   1954         }
   1955         startActivityAsUser(intent, UserHandle.CURRENT);
   1956     }
   1957 
   1958     private void handleDoubleTapOnHome() {
   1959         if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
   1960             mHomeConsumed = true;
   1961             toggleRecentApps();
   1962         }
   1963     }
   1964 
   1965     private void showPictureInPictureMenu(KeyEvent event) {
   1966         if (DEBUG_INPUT) Log.d(TAG, "showPictureInPictureMenu event=" + event);
   1967         mHandler.removeMessages(MSG_SHOW_PICTURE_IN_PICTURE_MENU);
   1968         Message msg = mHandler.obtainMessage(MSG_SHOW_PICTURE_IN_PICTURE_MENU);
   1969         msg.setAsynchronous(true);
   1970         msg.sendToTarget();
   1971     }
   1972 
   1973     private void showPictureInPictureMenuInternal() {
   1974         StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
   1975         if (statusbar != null) {
   1976             statusbar.showPictureInPictureMenu();
   1977         }
   1978     }
   1979 
   1980     private final Runnable mHomeDoubleTapTimeoutRunnable = new Runnable() {
   1981         @Override
   1982         public void run() {
   1983             if (mHomeDoubleTapPending) {
   1984                 mHomeDoubleTapPending = false;
   1985                 handleShortPressOnHome();
   1986             }
   1987         }
   1988     };
   1989 
   1990     private boolean isRoundWindow() {
   1991         return mContext.getResources().getConfiguration().isScreenRound();
   1992     }
   1993 
   1994     /** {@inheritDoc} */
   1995     @Override
   1996     public void init(Context context, IWindowManager windowManager,
   1997             WindowManagerFuncs windowManagerFuncs) {
   1998         mContext = context;
   1999         mWindowManager = windowManager;
   2000         mWindowManagerFuncs = windowManagerFuncs;
   2001         mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
   2002         mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
   2003         mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
   2004         mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
   2005         mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
   2006         mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
   2007         mHasFeatureWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH);
   2008         mHasFeatureLeanback = mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK);
   2009         mAccessibilityShortcutController =
   2010                 new AccessibilityShortcutController(mContext, new Handler(), mCurrentUserId);
   2011         mLogger = new MetricsLogger();
   2012         // Init display burn-in protection
   2013         boolean burnInProtectionEnabled = context.getResources().getBoolean(
   2014                 com.android.internal.R.bool.config_enableBurnInProtection);
   2015         // Allow a system property to override this. Used by developer settings.
   2016         boolean burnInProtectionDevMode =
   2017                 SystemProperties.getBoolean("persist.debug.force_burn_in", false);
   2018         if (burnInProtectionEnabled || burnInProtectionDevMode) {
   2019             final int minHorizontal;
   2020             final int maxHorizontal;
   2021             final int minVertical;
   2022             final int maxVertical;
   2023             final int maxRadius;
   2024             if (burnInProtectionDevMode) {
   2025                 minHorizontal = -8;
   2026                 maxHorizontal = 8;
   2027                 minVertical = -8;
   2028                 maxVertical = -4;
   2029                 maxRadius = (isRoundWindow()) ? 6 : -1;
   2030             } else {
   2031                 Resources resources = context.getResources();
   2032                 minHorizontal = resources.getInteger(
   2033                         com.android.internal.R.integer.config_burnInProtectionMinHorizontalOffset);
   2034                 maxHorizontal = resources.getInteger(
   2035                         com.android.internal.R.integer.config_burnInProtectionMaxHorizontalOffset);
   2036                 minVertical = resources.getInteger(
   2037                         com.android.internal.R.integer.config_burnInProtectionMinVerticalOffset);
   2038                 maxVertical = resources.getInteger(
   2039                         com.android.internal.R.integer.config_burnInProtectionMaxVerticalOffset);
   2040                 maxRadius = resources.getInteger(
   2041                         com.android.internal.R.integer.config_burnInProtectionMaxRadius);
   2042             }
   2043             mBurnInProtectionHelper = new BurnInProtectionHelper(
   2044                     context, minHorizontal, maxHorizontal, minVertical, maxVertical, maxRadius);
   2045         }
   2046 
   2047         mHandler = new PolicyHandler();
   2048         mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
   2049         mOrientationListener = new MyOrientationListener(mContext, mHandler);
   2050         try {
   2051             mOrientationListener.setCurrentRotation(windowManager.getDefaultDisplayRotation());
   2052         } catch (RemoteException ex) { }
   2053         mSettingsObserver = new SettingsObserver(mHandler);
   2054         mSettingsObserver.observe();
   2055         mShortcutManager = new ShortcutManager(context);
   2056         mUiMode = context.getResources().getInteger(
   2057                 com.android.internal.R.integer.config_defaultUiModeType);
   2058         mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
   2059         mHomeIntent.addCategory(Intent.CATEGORY_HOME);
   2060         mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
   2061                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
   2062         mEnableCarDockHomeCapture = context.getResources().getBoolean(
   2063                 com.android.internal.R.bool.config_enableCarDockHomeLaunch);
   2064         mCarDockIntent =  new Intent(Intent.ACTION_MAIN, null);
   2065         mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
   2066         mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
   2067                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
   2068         mDeskDockIntent =  new Intent(Intent.ACTION_MAIN, null);
   2069         mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
   2070         mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
   2071                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
   2072         mVrHeadsetHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
   2073         mVrHeadsetHomeIntent.addCategory(Intent.CATEGORY_VR_HOME);
   2074         mVrHeadsetHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
   2075                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
   2076 
   2077         mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
   2078         mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
   2079                 "PhoneWindowManager.mBroadcastWakeLock");
   2080         mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
   2081                 "PhoneWindowManager.mPowerKeyWakeLock");
   2082         mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
   2083         mSupportAutoRotation = mContext.getResources().getBoolean(
   2084                 com.android.internal.R.bool.config_supportAutoRotation);
   2085         mLidOpenRotation = readRotation(
   2086                 com.android.internal.R.integer.config_lidOpenRotation);
   2087         mCarDockRotation = readRotation(
   2088                 com.android.internal.R.integer.config_carDockRotation);
   2089         mDeskDockRotation = readRotation(
   2090                 com.android.internal.R.integer.config_deskDockRotation);
   2091         mUndockedHdmiRotation = readRotation(
   2092                 com.android.internal.R.integer.config_undockedHdmiRotation);
   2093         mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
   2094                 com.android.internal.R.bool.config_carDockEnablesAccelerometer);
   2095         mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
   2096                 com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
   2097         mLidKeyboardAccessibility = mContext.getResources().getInteger(
   2098                 com.android.internal.R.integer.config_lidKeyboardAccessibility);
   2099         mLidNavigationAccessibility = mContext.getResources().getInteger(
   2100                 com.android.internal.R.integer.config_lidNavigationAccessibility);
   2101         mLidControlsScreenLock = mContext.getResources().getBoolean(
   2102                 com.android.internal.R.bool.config_lidControlsScreenLock);
   2103         mLidControlsSleep = mContext.getResources().getBoolean(
   2104                 com.android.internal.R.bool.config_lidControlsSleep);
   2105         mTranslucentDecorEnabled = mContext.getResources().getBoolean(
   2106                 com.android.internal.R.bool.config_enableTranslucentDecor);
   2107 
   2108         mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
   2109                 com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
   2110         mAllowTheaterModeWakeFromPowerKey = mAllowTheaterModeWakeFromKey
   2111                 || mContext.getResources().getBoolean(
   2112                     com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey);
   2113         mAllowTheaterModeWakeFromMotion = mContext.getResources().getBoolean(
   2114                 com.android.internal.R.bool.config_allowTheaterModeWakeFromMotion);
   2115         mAllowTheaterModeWakeFromMotionWhenNotDreaming = mContext.getResources().getBoolean(
   2116                 com.android.internal.R.bool.config_allowTheaterModeWakeFromMotionWhenNotDreaming);
   2117         mAllowTheaterModeWakeFromCameraLens = mContext.getResources().getBoolean(
   2118                 com.android.internal.R.bool.config_allowTheaterModeWakeFromCameraLens);
   2119         mAllowTheaterModeWakeFromLidSwitch = mContext.getResources().getBoolean(
   2120                 com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch);
   2121         mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean(
   2122                 com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture);
   2123 
   2124         mGoToSleepOnButtonPressTheaterMode = mContext.getResources().getBoolean(
   2125                 com.android.internal.R.bool.config_goToSleepOnButtonPressTheaterMode);
   2126 
   2127         mSupportLongPressPowerWhenNonInteractive = mContext.getResources().getBoolean(
   2128                 com.android.internal.R.bool.config_supportLongPressPowerWhenNonInteractive);
   2129 
   2130         mLongPressOnBackBehavior = mContext.getResources().getInteger(
   2131                 com.android.internal.R.integer.config_longPressOnBackBehavior);
   2132 
   2133         mShortPressOnPowerBehavior = mContext.getResources().getInteger(
   2134                 com.android.internal.R.integer.config_shortPressOnPowerBehavior);
   2135         mLongPressOnPowerBehavior = mContext.getResources().getInteger(
   2136                 com.android.internal.R.integer.config_longPressOnPowerBehavior);
   2137         mVeryLongPressOnPowerBehavior = mContext.getResources().getInteger(
   2138                 com.android.internal.R.integer.config_veryLongPressOnPowerBehavior);
   2139         mDoublePressOnPowerBehavior = mContext.getResources().getInteger(
   2140                 com.android.internal.R.integer.config_doublePressOnPowerBehavior);
   2141         mTriplePressOnPowerBehavior = mContext.getResources().getInteger(
   2142                 com.android.internal.R.integer.config_triplePressOnPowerBehavior);
   2143         mShortPressOnSleepBehavior = mContext.getResources().getInteger(
   2144                 com.android.internal.R.integer.config_shortPressOnSleepBehavior);
   2145         mVeryLongPressTimeout = mContext.getResources().getInteger(
   2146                 com.android.internal.R.integer.config_veryLongPressTimeout);
   2147         mAllowStartActivityForLongPressOnPowerDuringSetup = mContext.getResources().getBoolean(
   2148                 com.android.internal.R.bool.config_allowStartActivityForLongPressOnPowerInSetup);
   2149 
   2150         mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION;
   2151 
   2152         mHandleVolumeKeysInWM = mContext.getResources().getBoolean(
   2153                 com.android.internal.R.bool.config_handleVolumeKeysInWindowManager);
   2154 
   2155         readConfigurationDependentBehaviors();
   2156 
   2157         mAccessibilityManager = (AccessibilityManager) context.getSystemService(
   2158                 Context.ACCESSIBILITY_SERVICE);
   2159 
   2160         // register for dock events
   2161         IntentFilter filter = new IntentFilter();
   2162         filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
   2163         filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
   2164         filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
   2165         filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
   2166         filter.addAction(Intent.ACTION_DOCK_EVENT);
   2167         Intent intent = context.registerReceiver(mDockReceiver, filter);
   2168         if (intent != null) {
   2169             // Retrieve current sticky dock event broadcast.
   2170             mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
   2171                     Intent.EXTRA_DOCK_STATE_UNDOCKED);
   2172         }
   2173 
   2174         // register for dream-related broadcasts
   2175         filter = new IntentFilter();
   2176         filter.addAction(Intent.ACTION_DREAMING_STARTED);
   2177         filter.addAction(Intent.ACTION_DREAMING_STOPPED);
   2178         context.registerReceiver(mDreamReceiver, filter);
   2179 
   2180         // register for multiuser-relevant broadcasts
   2181         filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
   2182         context.registerReceiver(mMultiuserReceiver, filter);
   2183 
   2184         // monitor for system gestures
   2185         // TODO(multi-display): Needs to be display specific.
   2186         mSystemGestures = new SystemGesturesPointerEventListener(context,
   2187                 new SystemGesturesPointerEventListener.Callbacks() {
   2188                     @Override
   2189                     public void onSwipeFromTop() {
   2190                         if (mStatusBar != null) {
   2191                             requestTransientBars(mStatusBar);
   2192                         }
   2193                     }
   2194                     @Override
   2195                     public void onSwipeFromBottom() {
   2196                         if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_BOTTOM) {
   2197                             requestTransientBars(mNavigationBar);
   2198                         }
   2199                     }
   2200                     @Override
   2201                     public void onSwipeFromRight() {
   2202                         if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_RIGHT) {
   2203                             requestTransientBars(mNavigationBar);
   2204                         }
   2205                     }
   2206                     @Override
   2207                     public void onSwipeFromLeft() {
   2208                         if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_LEFT) {
   2209                             requestTransientBars(mNavigationBar);
   2210                         }
   2211                     }
   2212                     @Override
   2213                     public void onFling(int duration) {
   2214                         if (mPowerManagerInternal != null) {
   2215                             mPowerManagerInternal.powerHint(
   2216                                     PowerHint.INTERACTION, duration);
   2217                         }
   2218                     }
   2219                     @Override
   2220                     public void onDebug() {
   2221                         // no-op
   2222                     }
   2223                     @Override
   2224                     public void onDown() {
   2225                         mOrientationListener.onTouchStart();
   2226                     }
   2227                     @Override
   2228                     public void onUpOrCancel() {
   2229                         mOrientationListener.onTouchEnd();
   2230                     }
   2231                     @Override
   2232                     public void onMouseHoverAtTop() {
   2233                         mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
   2234                         Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
   2235                         msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
   2236                         mHandler.sendMessageDelayed(msg, 500);
   2237                     }
   2238                     @Override
   2239                     public void onMouseHoverAtBottom() {
   2240                         mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
   2241                         Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
   2242                         msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
   2243                         mHandler.sendMessageDelayed(msg, 500);
   2244                     }
   2245                     @Override
   2246                     public void onMouseLeaveFromEdge() {
   2247                         mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
   2248                     }
   2249                 });
   2250         mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext);
   2251         mWindowManagerFuncs.registerPointerEventListener(mSystemGestures);
   2252 
   2253         mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
   2254         mLongPressVibePattern = getLongIntArray(mContext.getResources(),
   2255                 com.android.internal.R.array.config_longPressVibePattern);
   2256         mCalendarDateVibePattern = getLongIntArray(mContext.getResources(),
   2257                 com.android.internal.R.array.config_calendarDateVibePattern);
   2258         mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
   2259                 com.android.internal.R.array.config_safeModeEnabledVibePattern);
   2260 
   2261         mScreenshotChordEnabled = mContext.getResources().getBoolean(
   2262                 com.android.internal.R.bool.config_enableScreenshotChord);
   2263 
   2264         mGlobalKeyManager = new GlobalKeyManager(mContext);
   2265 
   2266         // Controls rotation and the like.
   2267         initializeHdmiState();
   2268 
   2269         // Match current screen state.
   2270         if (!mPowerManager.isInteractive()) {
   2271             startedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
   2272             finishedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
   2273         }
   2274 
   2275         mWindowManagerInternal.registerAppTransitionListener(
   2276                 mStatusBarController.getAppTransitionListener());
   2277         mWindowManagerInternal.registerAppTransitionListener(new AppTransitionListener() {
   2278             @Override
   2279             public int onAppTransitionStartingLocked(int transit, IBinder openToken,
   2280                     IBinder closeToken, long duration, long statusBarAnimationStartTime,
   2281                     long statusBarAnimationDuration) {
   2282                 return handleStartTransitionForKeyguardLw(transit, duration);
   2283             }
   2284 
   2285             @Override
   2286             public void onAppTransitionCancelledLocked(int transit) {
   2287                 handleStartTransitionForKeyguardLw(transit, 0 /* duration */);
   2288             }
   2289         });
   2290         mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
   2291                 new StateCallback() {
   2292                     @Override
   2293                     public void onTrustedChanged() {
   2294                         mWindowManagerFuncs.notifyKeyguardTrustedChanged();
   2295                     }
   2296 
   2297                     @Override
   2298                     public void onShowingChanged() {
   2299                         mWindowManagerFuncs.onKeyguardShowingAndNotOccludedChanged();
   2300                     }
   2301                 });
   2302         mScreenshotHelper = new ScreenshotHelper(mContext);
   2303     }
   2304 
   2305     /**
   2306      * Read values from config.xml that may be overridden depending on
   2307      * the configuration of the device.
   2308      * eg. Disable long press on home goes to recents on sw600dp.
   2309      */
   2310     private void readConfigurationDependentBehaviors() {
   2311         final Resources res = mContext.getResources();
   2312 
   2313         mLongPressOnHomeBehavior = res.getInteger(
   2314                 com.android.internal.R.integer.config_longPressOnHomeBehavior);
   2315         if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||
   2316                 mLongPressOnHomeBehavior > LAST_LONG_PRESS_HOME_BEHAVIOR) {
   2317             mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
   2318         }
   2319 
   2320         mDoubleTapOnHomeBehavior = res.getInteger(
   2321                 com.android.internal.R.integer.config_doubleTapOnHomeBehavior);
   2322         if (mDoubleTapOnHomeBehavior < DOUBLE_TAP_HOME_NOTHING ||
   2323                 mDoubleTapOnHomeBehavior > DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
   2324             mDoubleTapOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
   2325         }
   2326 
   2327         mShortPressOnWindowBehavior = SHORT_PRESS_WINDOW_NOTHING;
   2328         if (mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
   2329             mShortPressOnWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE;
   2330         }
   2331 
   2332         mNavBarOpacityMode = res.getInteger(
   2333                 com.android.internal.R.integer.config_navBarOpacityMode);
   2334     }
   2335 
   2336     @Override
   2337     public void setInitialDisplaySize(Display display, int width, int height, int density) {
   2338         // This method might be called before the policy has been fully initialized
   2339         // or for other displays we don't care about.
   2340         // TODO(multi-display): Define policy for secondary displays.
   2341         if (mContext == null || display.getDisplayId() != DEFAULT_DISPLAY) {
   2342             return;
   2343         }
   2344         mDisplay = display;
   2345 
   2346         final Resources res = mContext.getResources();
   2347         int shortSize, longSize;
   2348         if (width > height) {
   2349             shortSize = height;
   2350             longSize = width;
   2351             mLandscapeRotation = Surface.ROTATION_0;
   2352             mSeascapeRotation = Surface.ROTATION_180;
   2353             if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
   2354                 mPortraitRotation = Surface.ROTATION_90;
   2355                 mUpsideDownRotation = Surface.ROTATION_270;
   2356             } else {
   2357                 mPortraitRotation = Surface.ROTATION_270;
   2358                 mUpsideDownRotation = Surface.ROTATION_90;
   2359             }
   2360         } else {
   2361             shortSize = width;
   2362             longSize = height;
   2363             mPortraitRotation = Surface.ROTATION_0;
   2364             mUpsideDownRotation = Surface.ROTATION_180;
   2365             if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
   2366                 mLandscapeRotation = Surface.ROTATION_270;
   2367                 mSeascapeRotation = Surface.ROTATION_90;
   2368             } else {
   2369                 mLandscapeRotation = Surface.ROTATION_90;
   2370                 mSeascapeRotation = Surface.ROTATION_270;
   2371             }
   2372         }
   2373 
   2374         // SystemUI (status bar) layout policy
   2375         int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
   2376         int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
   2377 
   2378         // Allow the navigation bar to move on non-square small devices (phones).
   2379         mNavigationBarCanMove = width != height && shortSizeDp < 600;
   2380 
   2381         mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
   2382 
   2383         // Allow a system property to override this. Used by the emulator.
   2384         // See also hasNavigationBar().
   2385         String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
   2386         if ("1".equals(navBarOverride)) {
   2387             mHasNavigationBar = false;
   2388         } else if ("0".equals(navBarOverride)) {
   2389             mHasNavigationBar = true;
   2390         }
   2391 
   2392         // For demo purposes, allow the rotation of the HDMI display to be controlled.
   2393         // By default, HDMI locks rotation to landscape.
   2394         if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
   2395             mDemoHdmiRotation = mPortraitRotation;
   2396         } else {
   2397             mDemoHdmiRotation = mLandscapeRotation;
   2398         }
   2399         mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
   2400 
   2401         // For demo purposes, allow the rotation of the remote display to be controlled.
   2402         // By default, remote display locks rotation to landscape.
   2403         if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
   2404             mDemoRotation = mPortraitRotation;
   2405         } else {
   2406             mDemoRotation = mLandscapeRotation;
   2407         }
   2408         mDemoRotationLock = SystemProperties.getBoolean(
   2409                 "persist.demo.rotationlock", false);
   2410 
   2411         // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
   2412         // http://developer.android.com/guide/practices/screens_support.html#range
   2413         // For car, ignore the dp limitation. It's physically impossible to rotate the car's screen
   2414         // so if the orientation is forced, we need to respect that no matter what.
   2415         final boolean isCar = mContext.getPackageManager().hasSystemFeature(
   2416                 PackageManager.FEATURE_AUTOMOTIVE);
   2417         // For TV, it's usually 960dp x 540dp, ignore the size limitation.
   2418         // so if the orientation is forced, we need to respect that no matter what.
   2419         final boolean isTv = mContext.getPackageManager().hasSystemFeature(
   2420                 PackageManager.FEATURE_LEANBACK);
   2421         mForceDefaultOrientation = ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv) &&
   2422                 res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
   2423                 // For debug purposes the next line turns this feature off with:
   2424                 // $ adb shell setprop config.override_forced_orient true
   2425                 // $ adb shell wm size reset
   2426                 !"true".equals(SystemProperties.get("config.override_forced_orient"));
   2427     }
   2428 
   2429     /**
   2430      * @return whether the navigation bar can be hidden, e.g. the device has a
   2431      *         navigation bar and touch exploration is not enabled
   2432      */
   2433     private boolean canHideNavigationBar() {
   2434         return mHasNavigationBar;
   2435     }
   2436 
   2437     @Override
   2438     public boolean isDefaultOrientationForced() {
   2439         return mForceDefaultOrientation;
   2440     }
   2441 
   2442     public void updateSettings() {
   2443         ContentResolver resolver = mContext.getContentResolver();
   2444         boolean updateRotation = false;
   2445         synchronized (mLock) {
   2446             mEndcallBehavior = Settings.System.getIntForUser(resolver,
   2447                     Settings.System.END_BUTTON_BEHAVIOR,
   2448                     Settings.System.END_BUTTON_BEHAVIOR_DEFAULT,
   2449                     UserHandle.USER_CURRENT);
   2450             mIncallPowerBehavior = Settings.Secure.getIntForUser(resolver,
   2451                     Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
   2452                     Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT,
   2453                     UserHandle.USER_CURRENT);
   2454             mIncallBackBehavior = Settings.Secure.getIntForUser(resolver,
   2455                     Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR,
   2456                     Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_DEFAULT,
   2457                     UserHandle.USER_CURRENT);
   2458             mSystemNavigationKeysEnabled = Settings.Secure.getIntForUser(resolver,
   2459                     Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED,
   2460                     0, UserHandle.USER_CURRENT) == 1;
   2461             mRingerToggleChord = Settings.Secure.getIntForUser(resolver,
   2462                     Settings.Secure.VOLUME_HUSH_GESTURE, VOLUME_HUSH_OFF,
   2463                     UserHandle.USER_CURRENT);
   2464             if (!mContext.getResources()
   2465                     .getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled)) {
   2466                 mRingerToggleChord = Settings.Secure.VOLUME_HUSH_OFF;
   2467             }
   2468             // Configure rotation suggestions.
   2469             int showRotationSuggestions = Settings.Secure.getIntForUser(resolver,
   2470                     Settings.Secure.SHOW_ROTATION_SUGGESTIONS,
   2471                     Settings.Secure.SHOW_ROTATION_SUGGESTIONS_DEFAULT,
   2472                     UserHandle.USER_CURRENT);
   2473             if (mShowRotationSuggestions != showRotationSuggestions) {
   2474                 mShowRotationSuggestions = showRotationSuggestions;
   2475                 updateOrientationListenerLp(); // Enable, disable the orientation listener
   2476             }
   2477 
   2478             // Configure wake gesture.
   2479             boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver,
   2480                     Settings.Secure.WAKE_GESTURE_ENABLED, 0,
   2481                     UserHandle.USER_CURRENT) != 0;
   2482             if (mWakeGestureEnabledSetting != wakeGestureEnabledSetting) {
   2483                 mWakeGestureEnabledSetting = wakeGestureEnabledSetting;
   2484                 updateWakeGestureListenerLp();
   2485             }
   2486 
   2487             // Configure rotation lock.
   2488             int userRotation = Settings.System.getIntForUser(resolver,
   2489                     Settings.System.USER_ROTATION, Surface.ROTATION_0,
   2490                     UserHandle.USER_CURRENT);
   2491             if (mUserRotation != userRotation) {
   2492                 mUserRotation = userRotation;
   2493                 updateRotation = true;
   2494             }
   2495             int userRotationMode = Settings.System.getIntForUser(resolver,
   2496                     Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
   2497                             WindowManagerPolicy.USER_ROTATION_FREE :
   2498                                     WindowManagerPolicy.USER_ROTATION_LOCKED;
   2499             if (mUserRotationMode != userRotationMode) {
   2500                 mUserRotationMode = userRotationMode;
   2501                 updateRotation = true;
   2502                 updateOrientationListenerLp();
   2503             }
   2504 
   2505             if (mSystemReady) {
   2506                 int pointerLocation = Settings.System.getIntForUser(resolver,
   2507                         Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT);
   2508                 if (mPointerLocationMode != pointerLocation) {
   2509                     mPointerLocationMode = pointerLocation;
   2510                     mHandler.sendEmptyMessage(pointerLocation != 0 ?
   2511                             MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
   2512                 }
   2513             }
   2514             // use screen off timeout setting as the timeout for the lockscreen
   2515             mLockScreenTimeout = Settings.System.getIntForUser(resolver,
   2516                     Settings.System.SCREEN_OFF_TIMEOUT, 0, UserHandle.USER_CURRENT);
   2517             String imId = Settings.Secure.getStringForUser(resolver,
   2518                     Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.USER_CURRENT);
   2519             boolean hasSoftInput = imId != null && imId.length() > 0;
   2520             if (mHasSoftInput != hasSoftInput) {
   2521                 mHasSoftInput = hasSoftInput;
   2522                 updateRotation = true;
   2523             }
   2524             if (mImmersiveModeConfirmation != null) {
   2525                 mImmersiveModeConfirmation.loadSetting(mCurrentUserId);
   2526             }
   2527         }
   2528         synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
   2529             PolicyControl.reloadFromSetting(mContext);
   2530         }
   2531         if (updateRotation) {
   2532             updateRotation(true);
   2533         }
   2534     }
   2535 
   2536     private void updateWakeGestureListenerLp() {
   2537         if (shouldEnableWakeGestureLp()) {
   2538             mWakeGestureListener.requestWakeUpTrigger();
   2539         } else {
   2540             mWakeGestureListener.cancelWakeUpTrigger();
   2541         }
   2542     }
   2543 
   2544     private boolean shouldEnableWakeGestureLp() {
   2545         return mWakeGestureEnabledSetting && !mAwake
   2546                 && (!mLidControlsSleep || mLidState != LID_CLOSED)
   2547                 && mWakeGestureListener.isSupported();
   2548     }
   2549 
   2550     private void enablePointerLocation() {
   2551         if (mPointerLocationView == null) {
   2552             mPointerLocationView = new PointerLocationView(mContext);
   2553             mPointerLocationView.setPrintCoords(false);
   2554             WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
   2555                     WindowManager.LayoutParams.MATCH_PARENT,
   2556                     WindowManager.LayoutParams.MATCH_PARENT);
   2557             lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
   2558             lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
   2559                     | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
   2560                     | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
   2561                     | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
   2562             lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
   2563             if (ActivityManager.isHighEndGfx()) {
   2564                 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
   2565                 lp.privateFlags |=
   2566                         WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
   2567             }
   2568             lp.format = PixelFormat.TRANSLUCENT;
   2569             lp.setTitle("PointerLocation");
   2570             WindowManager wm = (WindowManager) mContext.getSystemService(WINDOW_SERVICE);
   2571             lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
   2572             wm.addView(mPointerLocationView, lp);
   2573             mWindowManagerFuncs.registerPointerEventListener(mPointerLocationView);
   2574         }
   2575     }
   2576 
   2577     private void disablePointerLocation() {
   2578         if (mPointerLocationView != null) {
   2579             mWindowManagerFuncs.unregisterPointerEventListener(mPointerLocationView);
   2580             WindowManager wm = (WindowManager) mContext.getSystemService(WINDOW_SERVICE);
   2581             wm.removeView(mPointerLocationView);
   2582             mPointerLocationView = null;
   2583         }
   2584     }
   2585 
   2586     private int readRotation(int resID) {
   2587         try {
   2588             int rotation = mContext.getResources().getInteger(resID);
   2589             switch (rotation) {
   2590                 case 0:
   2591                     return Surface.ROTATION_0;
   2592                 case 90:
   2593                     return Surface.ROTATION_90;
   2594                 case 180:
   2595                     return Surface.ROTATION_180;
   2596                 case 270:
   2597                     return Surface.ROTATION_270;
   2598             }
   2599         } catch (Resources.NotFoundException e) {
   2600             // fall through
   2601         }
   2602         return -1;
   2603     }
   2604 
   2605     /** {@inheritDoc} */
   2606     @Override
   2607     public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) {
   2608         final int type = attrs.type;
   2609         final boolean isRoundedCornerOverlay =
   2610                 (attrs.privateFlags & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0;
   2611 
   2612         if (isRoundedCornerOverlay && mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
   2613                 != PERMISSION_GRANTED) {
   2614             return ADD_PERMISSION_DENIED;
   2615         }
   2616 
   2617         outAppOp[0] = AppOpsManager.OP_NONE;
   2618 
   2619         if (!((type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW)
   2620                 || (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW)
   2621                 || (type >= FIRST_SYSTEM_WINDOW && type <= LAST_SYSTEM_WINDOW))) {
   2622             return WindowManagerGlobal.ADD_INVALID_TYPE;
   2623         }
   2624 
   2625         if (type < FIRST_SYSTEM_WINDOW || type > LAST_SYSTEM_WINDOW) {
   2626             // Window manager will make sure these are okay.
   2627             return ADD_OKAY;
   2628         }
   2629 
   2630         if (!isSystemAlertWindowType(type)) {
   2631             switch (type) {
   2632                 case TYPE_TOAST:
   2633                     // Only apps that target older than O SDK can add window without a token, after
   2634                     // that we require a token so apps cannot add toasts directly as the token is
   2635                     // added by the notification system.
   2636                     // Window manager does the checking for this.
   2637                     outAppOp[0] = OP_TOAST_WINDOW;
   2638                     return ADD_OKAY;
   2639                 case TYPE_DREAM:
   2640                 case TYPE_INPUT_METHOD:
   2641                 case TYPE_WALLPAPER:
   2642                 case TYPE_PRESENTATION:
   2643                 case TYPE_PRIVATE_PRESENTATION:
   2644                 case TYPE_VOICE_INTERACTION:
   2645                 case TYPE_ACCESSIBILITY_OVERLAY:
   2646                 case TYPE_QS_DIALOG:
   2647                     // The window manager will check these.
   2648                     return ADD_OKAY;
   2649             }
   2650             return mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
   2651                     == PERMISSION_GRANTED ? ADD_OKAY : ADD_PERMISSION_DENIED;
   2652         }
   2653 
   2654         // Things get a little more interesting for alert windows...
   2655         outAppOp[0] = OP_SYSTEM_ALERT_WINDOW;
   2656 
   2657         final int callingUid = Binder.getCallingUid();
   2658         // system processes will be automatically granted privilege to draw
   2659         if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
   2660             return ADD_OKAY;
   2661         }
   2662 
   2663         ApplicationInfo appInfo;
   2664         try {
   2665             appInfo = mContext.getPackageManager().getApplicationInfoAsUser(
   2666                             attrs.packageName,
   2667                             0 /* flags */,
   2668                             UserHandle.getUserId(callingUid));
   2669         } catch (PackageManager.NameNotFoundException e) {
   2670             appInfo = null;
   2671         }
   2672 
   2673         if (appInfo == null || (type != TYPE_APPLICATION_OVERLAY && appInfo.targetSdkVersion >= O)) {
   2674             /**
   2675              * Apps targeting >= {@link Build.VERSION_CODES#O} are required to hold
   2676              * {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW} (system signature apps)
   2677              * permission to add alert windows that aren't
   2678              * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY}.
   2679              */
   2680             return (mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
   2681                     == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
   2682         }
   2683 
   2684         // check if user has enabled this operation. SecurityException will be thrown if this app
   2685         // has not been allowed by the user
   2686         final int mode = mAppOpsManager.noteOpNoThrow(outAppOp[0], callingUid, attrs.packageName);
   2687         switch (mode) {
   2688             case AppOpsManager.MODE_ALLOWED:
   2689             case AppOpsManager.MODE_IGNORED:
   2690                 // although we return ADD_OKAY for MODE_IGNORED, the added window will
   2691                 // actually be hidden in WindowManagerService
   2692                 return ADD_OKAY;
   2693             case AppOpsManager.MODE_ERRORED:
   2694                 // Don't crash legacy apps
   2695                 if (appInfo.targetSdkVersion < M) {
   2696                     return ADD_OKAY;
   2697                 }
   2698                 return ADD_PERMISSION_DENIED;
   2699             default:
   2700                 // in the default mode, we will make a decision here based on
   2701                 // checkCallingPermission()
   2702                 return (mContext.checkCallingOrSelfPermission(SYSTEM_ALERT_WINDOW)
   2703                         == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
   2704         }
   2705     }
   2706 
   2707     @Override
   2708     public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) {
   2709 
   2710         // If this switch statement is modified, modify the comment in the declarations of
   2711         // the type in {@link WindowManager.LayoutParams} as well.
   2712         switch (attrs.type) {
   2713             default:
   2714                 // These are the windows that by default are shown only to the user that created
   2715                 // them. If this needs to be overridden, set
   2716                 // {@link WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS} in
   2717                 // {@link WindowManager.LayoutParams}. Note that permission
   2718                 // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well.
   2719                 if ((attrs.privateFlags & PRIVATE_FLAG_SHOW_FOR_ALL_USERS) == 0) {
   2720                     return true;
   2721                 }
   2722                 break;
   2723 
   2724             // These are the windows that by default are shown to all users. However, to
   2725             // protect against spoofing, check permissions below.
   2726             case TYPE_APPLICATION_STARTING:
   2727             case TYPE_BOOT_PROGRESS:
   2728             case TYPE_DISPLAY_OVERLAY:
   2729             case TYPE_INPUT_CONSUMER:
   2730             case TYPE_KEYGUARD_DIALOG:
   2731             case TYPE_MAGNIFICATION_OVERLAY:
   2732             case TYPE_NAVIGATION_BAR:
   2733             case TYPE_NAVIGATION_BAR_PANEL:
   2734             case TYPE_PHONE:
   2735             case TYPE_POINTER:
   2736             case TYPE_PRIORITY_PHONE:
   2737             case TYPE_SEARCH_BAR:
   2738             case TYPE_STATUS_BAR:
   2739             case TYPE_STATUS_BAR_PANEL:
   2740             case TYPE_STATUS_BAR_SUB_PANEL:
   2741             case TYPE_SYSTEM_DIALOG:
   2742             case TYPE_VOLUME_OVERLAY:
   2743             case TYPE_PRESENTATION:
   2744             case TYPE_PRIVATE_PRESENTATION:
   2745             case TYPE_DOCK_DIVIDER:
   2746                 break;
   2747         }
   2748 
   2749         // Check if third party app has set window to system window type.
   2750         return mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW) != PERMISSION_GRANTED;
   2751     }
   2752 
   2753     @Override
   2754     public void adjustWindowParamsLw(WindowState win, WindowManager.LayoutParams attrs,
   2755             boolean hasStatusBarServicePermission) {
   2756 
   2757         final boolean isScreenDecor = (attrs.privateFlags & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0;
   2758         if (mScreenDecorWindows.contains(win)) {
   2759             if (!isScreenDecor) {
   2760                 // No longer has the flag set, so remove from the set.
   2761                 mScreenDecorWindows.remove(win);
   2762             }
   2763         } else if (isScreenDecor && hasStatusBarServicePermission) {
   2764             mScreenDecorWindows.add(win);
   2765         }
   2766 
   2767         switch (attrs.type) {
   2768             case TYPE_SYSTEM_OVERLAY:
   2769             case TYPE_SECURE_SYSTEM_OVERLAY:
   2770                 // These types of windows can't receive input events.
   2771                 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
   2772                         | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
   2773                 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
   2774                 break;
   2775             case TYPE_DREAM:
   2776             case TYPE_WALLPAPER:
   2777                 // Dreams and wallpapers don't have an app window token and can thus not be
   2778                 // letterboxed. Hence always let them extend under the cutout.
   2779                 attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
   2780                 break;
   2781             case TYPE_STATUS_BAR:
   2782 
   2783                 // If the Keyguard is in a hidden state (occluded by another window), we force to
   2784                 // remove the wallpaper and keyguard flag so that any change in-flight after setting
   2785                 // the keyguard as occluded wouldn't set these flags again.
   2786                 // See {@link #processKeyguardSetHiddenResultLw}.
   2787                 if (mKeyguardOccluded) {
   2788                     attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
   2789                     attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
   2790                 }
   2791                 break;
   2792 
   2793             case TYPE_SCREENSHOT:
   2794                 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
   2795                 break;
   2796 
   2797             case TYPE_TOAST:
   2798                 // While apps should use the dedicated toast APIs to add such windows
   2799                 // it possible legacy apps to add the window directly. Therefore, we
   2800                 // make windows added directly by the app behave as a toast as much
   2801                 // as possible in terms of timeout and animation.
   2802                 if (attrs.hideTimeoutMilliseconds < 0
   2803                         || attrs.hideTimeoutMilliseconds > TOAST_WINDOW_TIMEOUT) {
   2804                     attrs.hideTimeoutMilliseconds = TOAST_WINDOW_TIMEOUT;
   2805                 }
   2806                 attrs.windowAnimations = com.android.internal.R.style.Animation_Toast;
   2807                 break;
   2808         }
   2809 
   2810         if (attrs.type != TYPE_STATUS_BAR) {
   2811             // The status bar is the only window allowed to exhibit keyguard behavior.
   2812             attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
   2813         }
   2814     }
   2815 
   2816     private int getImpliedSysUiFlagsForLayout(LayoutParams attrs) {
   2817         int impliedFlags = 0;
   2818         if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
   2819             impliedFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
   2820         }
   2821         final boolean forceWindowDrawsStatusBarBackground =
   2822                 (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
   2823         if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
   2824                 || forceWindowDrawsStatusBarBackground
   2825                         && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) {
   2826             impliedFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
   2827         }
   2828         return impliedFlags;
   2829     }
   2830 
   2831     void readLidState() {
   2832         mLidState = mWindowManagerFuncs.getLidState();
   2833     }
   2834 
   2835     private void readCameraLensCoverState() {
   2836         mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState();
   2837     }
   2838 
   2839     private boolean isHidden(int accessibilityMode) {
   2840         switch (accessibilityMode) {
   2841             case 1:
   2842                 return mLidState == LID_CLOSED;
   2843             case 2:
   2844                 return mLidState == LID_OPEN;
   2845             default:
   2846                 return false;
   2847         }
   2848     }
   2849 
   2850     /** {@inheritDoc} */
   2851     @Override
   2852     public void adjustConfigurationLw(Configuration config, int keyboardPresence,
   2853             int navigationPresence) {
   2854         mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0;
   2855 
   2856         readConfigurationDependentBehaviors();
   2857         readLidState();
   2858 
   2859         if (config.keyboard == Configuration.KEYBOARD_NOKEYS
   2860                 || (keyboardPresence == PRESENCE_INTERNAL
   2861                         && isHidden(mLidKeyboardAccessibility))) {
   2862             config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
   2863             if (!mHasSoftInput) {
   2864                 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
   2865             }
   2866         }
   2867 
   2868         if (config.navigation == Configuration.NAVIGATION_NONAV
   2869                 || (navigationPresence == PRESENCE_INTERNAL
   2870                         && isHidden(mLidNavigationAccessibility))) {
   2871             config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
   2872         }
   2873     }
   2874 
   2875     @Override
   2876     public void onOverlayChangedLw() {
   2877         onConfigurationChanged();
   2878     }
   2879 
   2880     @Override
   2881     public void onConfigurationChanged() {
   2882         // TODO(multi-display): Define policy for secondary displays.
   2883         Context uiContext = getSystemUiContext();
   2884         final Resources res = uiContext.getResources();
   2885 
   2886         mStatusBarHeightForRotation[mPortraitRotation] =
   2887                 mStatusBarHeightForRotation[mUpsideDownRotation] = res.getDimensionPixelSize(
   2888                                 com.android.internal.R.dimen.status_bar_height_portrait);
   2889         mStatusBarHeightForRotation[mLandscapeRotation] =
   2890                 mStatusBarHeightForRotation[mSeascapeRotation] = res.getDimensionPixelSize(
   2891                         com.android.internal.R.dimen.status_bar_height_landscape);
   2892 
   2893         // Height of the navigation bar when presented horizontally at bottom
   2894         mNavigationBarHeightForRotationDefault[mPortraitRotation] =
   2895         mNavigationBarHeightForRotationDefault[mUpsideDownRotation] =
   2896                 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
   2897         mNavigationBarHeightForRotationDefault[mLandscapeRotation] =
   2898         mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize(
   2899                 com.android.internal.R.dimen.navigation_bar_height_landscape);
   2900 
   2901         // Width of the navigation bar when presented vertically along one side
   2902         mNavigationBarWidthForRotationDefault[mPortraitRotation] =
   2903         mNavigationBarWidthForRotationDefault[mUpsideDownRotation] =
   2904         mNavigationBarWidthForRotationDefault[mLandscapeRotation] =
   2905         mNavigationBarWidthForRotationDefault[mSeascapeRotation] =
   2906                 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
   2907 
   2908         if (ALTERNATE_CAR_MODE_NAV_SIZE) {
   2909             // Height of the navigation bar when presented horizontally at bottom
   2910             mNavigationBarHeightForRotationInCarMode[mPortraitRotation] =
   2911             mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] =
   2912                     res.getDimensionPixelSize(
   2913                             com.android.internal.R.dimen.navigation_bar_height_car_mode);
   2914             mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] =
   2915             mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize(
   2916                     com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode);
   2917 
   2918             // Width of the navigation bar when presented vertically along one side
   2919             mNavigationBarWidthForRotationInCarMode[mPortraitRotation] =
   2920             mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] =
   2921             mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] =
   2922             mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] =
   2923                     res.getDimensionPixelSize(
   2924                             com.android.internal.R.dimen.navigation_bar_width_car_mode);
   2925         }
   2926     }
   2927 
   2928     @VisibleForTesting
   2929     Context getSystemUiContext() {
   2930         return ActivityThread.currentActivityThread().getSystemUiContext();
   2931     }
   2932 
   2933     @Override
   2934     public int getMaxWallpaperLayer() {
   2935         return getWindowLayerFromTypeLw(TYPE_STATUS_BAR);
   2936     }
   2937 
   2938     private int getNavigationBarWidth(int rotation, int uiMode) {
   2939         if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
   2940             return mNavigationBarWidthForRotationInCarMode[rotation];
   2941         } else {
   2942             return mNavigationBarWidthForRotationDefault[rotation];
   2943         }
   2944     }
   2945 
   2946     @Override
   2947     public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
   2948             int displayId, DisplayCutout displayCutout) {
   2949         int width = fullWidth;
   2950         // TODO(multi-display): Support navigation bar on secondary displays.
   2951         if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) {
   2952             // For a basic navigation bar, when we are in landscape mode we place
   2953             // the navigation bar to the side.
   2954             if (mNavigationBarCanMove && fullWidth > fullHeight) {
   2955                 width -= getNavigationBarWidth(rotation, uiMode);
   2956             }
   2957         }
   2958         if (displayCutout != null) {
   2959             width -= displayCutout.getSafeInsetLeft() + displayCutout.getSafeInsetRight();
   2960         }
   2961         return width;
   2962     }
   2963 
   2964     private int getNavigationBarHeight(int rotation, int uiMode) {
   2965         if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
   2966             return mNavigationBarHeightForRotationInCarMode[rotation];
   2967         } else {
   2968             return mNavigationBarHeightForRotationDefault[rotation];
   2969         }
   2970     }
   2971 
   2972     @Override
   2973     public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
   2974             int displayId, DisplayCutout displayCutout) {
   2975         int height = fullHeight;
   2976         // TODO(multi-display): Support navigation bar on secondary displays.
   2977         if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) {
   2978             // For a basic navigation bar, when we are in portrait mode we place
   2979             // the navigation bar to the bottom.
   2980             if (!mNavigationBarCanMove || fullWidth < fullHeight) {
   2981                 height -= getNavigationBarHeight(rotation, uiMode);
   2982             }
   2983         }
   2984         if (displayCutout != null) {
   2985             height -= displayCutout.getSafeInsetTop() + displayCutout.getSafeInsetBottom();
   2986         }
   2987         return height;
   2988     }
   2989 
   2990     @Override
   2991     public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
   2992             int displayId, DisplayCutout displayCutout) {
   2993         return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode, displayId,
   2994                 displayCutout);
   2995     }
   2996 
   2997     @Override
   2998     public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
   2999             int displayId, DisplayCutout displayCutout) {
   3000         // There is a separate status bar at the top of the display.  We don't count that as part
   3001         // of the fixed decor, since it can hide; however, for purposes of configurations,
   3002         // we do want to exclude it since applications can't generally use that part
   3003         // of the screen.
   3004         // TODO(multi-display): Support status bars on secondary displays.
   3005         if (displayId == DEFAULT_DISPLAY) {
   3006             int statusBarHeight = mStatusBarHeightForRotation[rotation];
   3007             if (displayCutout != null) {
   3008                 // If there is a cutout, it may already have accounted for some part of the status
   3009                 // bar height.
   3010                 statusBarHeight = Math.max(0, statusBarHeight - displayCutout.getSafeInsetTop());
   3011             }
   3012             return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayId,
   3013                     displayCutout) - statusBarHeight;
   3014         }
   3015         return fullHeight;
   3016     }
   3017 
   3018     @Override
   3019     public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) {
   3020         return attrs.type == TYPE_STATUS_BAR;
   3021     }
   3022 
   3023     @Override
   3024     public boolean canBeHiddenByKeyguardLw(WindowState win) {
   3025         switch (win.getAttrs().type) {
   3026             case TYPE_STATUS_BAR:
   3027             case TYPE_NAVIGATION_BAR:
   3028             case TYPE_WALLPAPER:
   3029             case TYPE_DREAM:
   3030                 return false;
   3031             default:
   3032                 // Hide only windows below the keyguard host window.
   3033                 return getWindowLayerLw(win) < getWindowLayerFromTypeLw(TYPE_STATUS_BAR);
   3034         }
   3035     }
   3036 
   3037     private boolean shouldBeHiddenByKeyguard(WindowState win, WindowState imeTarget) {
   3038 
   3039         // Keyguard visibility of window from activities are determined over activity visibility.
   3040         if (win.getAppToken() != null) {
   3041             return false;
   3042         }
   3043 
   3044         final LayoutParams attrs = win.getAttrs();
   3045         final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleLw() &&
   3046                 ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0
   3047                         || !canBeHiddenByKeyguardLw(imeTarget));
   3048 
   3049         // Show IME over the keyguard if the target allows it
   3050         boolean allowWhenLocked = (win.isInputMethodWindow() || imeTarget == this)
   3051                 && showImeOverKeyguard;
   3052 
   3053         if (isKeyguardLocked() && isKeyguardOccluded()) {
   3054             // Show SHOW_WHEN_LOCKED windows if Keyguard is occluded.
   3055             allowWhenLocked |= (attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
   3056                     // Show error dialogs over apps that are shown on lockscreen
   3057                     || (attrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
   3058         }
   3059 
   3060         boolean keyguardLocked = isKeyguardLocked();
   3061         boolean hideDockDivider = attrs.type == TYPE_DOCK_DIVIDER
   3062                 && !mWindowManagerInternal.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
   3063         // If AOD is showing, the IME should be hidden. However, sometimes the AOD is considered
   3064         // hidden because it's in the process of hiding, but it's still being shown on screen.
   3065         // In that case, we want to continue hiding the IME until the windows have completed
   3066         // drawing. This way, we know that the IME can be safely shown since the other windows are
   3067         // now shown.
   3068         final boolean hideIme =
   3069                 win.isInputMethodWindow() && (mAodShowing || !mWindowManagerDrawComplete);
   3070         return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == DEFAULT_DISPLAY)
   3071                 || hideDockDivider || hideIme;
   3072     }
   3073 
   3074     /** {@inheritDoc} */
   3075     @Override
   3076     public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme,
   3077             CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon,
   3078             int logo, int windowFlags, Configuration overrideConfig, int displayId) {
   3079         if (!SHOW_SPLASH_SCREENS) {
   3080             return null;
   3081         }
   3082         if (packageName == null) {
   3083             return null;
   3084         }
   3085 
   3086         WindowManager wm = null;
   3087         View view = null;
   3088 
   3089         try {
   3090             Context context = mContext;
   3091             if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen " + packageName
   3092                     + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
   3093                     + Integer.toHexString(theme));
   3094 
   3095             // Obtain proper context to launch on the right display.
   3096             final Context displayContext = getDisplayContext(context, displayId);
   3097             if (displayContext == null) {
   3098                 // Can't show splash screen on requested display, so skip showing at all.
   3099                 return null;
   3100             }
   3101             context = displayContext;
   3102 
   3103             if (theme != context.getThemeResId() || labelRes != 0) {
   3104                 try {
   3105                     context = context.createPackageContext(packageName, CONTEXT_RESTRICTED);
   3106                     context.setTheme(theme);
   3107                 } catch (PackageManager.NameNotFoundException e) {
   3108                     // Ignore
   3109                 }
   3110             }
   3111 
   3112             if (overrideConfig != null && !overrideConfig.equals(EMPTY)) {
   3113                 if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: creating context based"
   3114                         + " on overrideConfig" + overrideConfig + " for splash screen");
   3115                 final Context overrideContext = context.createConfigurationContext(overrideConfig);
   3116                 overrideContext.setTheme(theme);
   3117                 final TypedArray typedArray = overrideContext.obtainStyledAttributes(
   3118                         com.android.internal.R.styleable.Window);
   3119                 final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
   3120                 if (resId != 0 && overrideContext.getDrawable(resId) != null) {
   3121                     // We want to use the windowBackground for the override context if it is
   3122                     // available, otherwise we use the default one to make sure a themed starting
   3123                     // window is displayed for the app.
   3124                     if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: apply overrideConfig"
   3125                             + overrideConfig + " to starting window resId=" + resId);
   3126                     context = overrideContext;
   3127                 }
   3128                 typedArray.recycle();
   3129             }
   3130 
   3131             final PhoneWindow win = new PhoneWindow(context);
   3132             win.setIsStartingWindow(true);
   3133 
   3134             CharSequence label = context.getResources().getText(labelRes, null);
   3135             // Only change the accessibility title if the label is localized
   3136             if (label != null) {
   3137                 win.setTitle(label, true);
   3138             } else {
   3139                 win.setTitle(nonLocalizedLabel, false);
   3140             }
   3141 
   3142             win.setType(
   3143                 WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
   3144 
   3145             synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
   3146                 // Assumes it's safe to show starting windows of launched apps while
   3147                 // the keyguard is being hidden. This is okay because starting windows never show
   3148                 // secret information.
   3149                 if (mKeyguardOccluded) {
   3150                     windowFlags |= FLAG_SHOW_WHEN_LOCKED;
   3151                 }
   3152             }
   3153 
   3154             // Force the window flags: this is a fake window, so it is not really
   3155             // touchable or focusable by the user.  We also add in the ALT_FOCUSABLE_IM
   3156             // flag because we do know that the next window will take input
   3157             // focus, so we want to get the IME window up on top of us right away.
   3158             win.setFlags(
   3159                 windowFlags|
   3160                 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
   3161                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
   3162                 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
   3163                 windowFlags|
   3164                 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
   3165                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
   3166                 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
   3167 
   3168             win.setDefaultIcon(icon);
   3169             win.setDefaultLogo(logo);
   3170 
   3171             win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
   3172                     WindowManager.LayoutParams.MATCH_PARENT);
   3173 
   3174             final WindowManager.LayoutParams params = win.getAttributes();
   3175             params.token = appToken;
   3176             params.packageName = packageName;
   3177             params.windowAnimations = win.getWindowStyle().getResourceId(
   3178                     com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
   3179             params.privateFlags |=
   3180                     WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
   3181             params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
   3182 
   3183             if (!compatInfo.supportsScreen()) {
   3184                 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
   3185             }
   3186 
   3187             params.setTitle("Splash Screen " + packageName);
   3188             addSplashscreenContent(win, context);
   3189 
   3190             wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
   3191             view = win.getDecorView();
   3192 
   3193             if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "Adding splash screen window for "
   3194                 + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null));
   3195 
   3196             wm.addView(view, params);
   3197 
   3198             // Only return the view if it was successfully added to the
   3199             // window manager... which we can tell by it having a parent.
   3200             return view.getParent() != null ? new SplashScreenSurface(view, appToken) : null;
   3201         } catch (WindowManager.BadTokenException e) {
   3202             // ignore
   3203             Log.w(TAG, appToken + " already running, starting window not displayed. " +
   3204                     e.getMessage());
   3205         } catch (RuntimeException e) {
   3206             // don't crash if something else bad happens, for example a
   3207             // failure loading resources because we are loading from an app
   3208             // on external storage that has been unmounted.
   3209             Log.w(TAG, appToken + " failed creating starting window", e);
   3210         } finally {
   3211             if (view != null && view.getParent() == null) {
   3212                 Log.w(TAG, "view not successfully added to wm, removing view");
   3213                 wm.removeViewImmediate(view);
   3214             }
   3215         }
   3216 
   3217         return null;
   3218     }
   3219 
   3220     private void addSplashscreenContent(PhoneWindow win, Context ctx) {
   3221         final TypedArray a = ctx.obtainStyledAttributes(R.styleable.Window);
   3222         final int resId = a.getResourceId(R.styleable.Window_windowSplashscreenContent, 0);
   3223         a.recycle();
   3224         if (resId == 0) {
   3225             return;
   3226         }
   3227         final Drawable drawable = ctx.getDrawable(resId);
   3228         if (drawable == null) {
   3229             return;
   3230         }
   3231 
   3232         // We wrap this into a view so the system insets get applied to the drawable.
   3233         final View v = new View(ctx);
   3234         v.setBackground(drawable);
   3235         win.setContentView(v);
   3236     }
   3237 
   3238     /** Obtain proper context for showing splash screen on the provided display. */
   3239     private Context getDisplayContext(Context context, int displayId) {
   3240         if (displayId == DEFAULT_DISPLAY) {
   3241             // The default context fits.
   3242             return context;
   3243         }
   3244 
   3245         final DisplayManager dm = (DisplayManager) context.getSystemService(DISPLAY_SERVICE);
   3246         final Display targetDisplay = dm.getDisplay(displayId);
   3247         if (targetDisplay == null) {
   3248             // Failed to obtain the non-default display where splash screen should be shown,
   3249             // lets not show at all.
   3250             return null;
   3251         }
   3252 
   3253         return context.createDisplayContext(targetDisplay);
   3254     }
   3255 
   3256     /**
   3257      * Preflight adding a window to the system.
   3258      *
   3259      * Currently enforces that three window types are singletons:
   3260      * <ul>
   3261      * <li>STATUS_BAR_TYPE</li>
   3262      * <li>KEYGUARD_TYPE</li>
   3263      * </ul>
   3264      *
   3265      * @param win The window to be added
   3266      * @param attrs Information about the window to be added
   3267      *
   3268      * @return If ok, WindowManagerImpl.ADD_OKAY.  If too many singletons,
   3269      * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
   3270      */
   3271     @Override
   3272     public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
   3273 
   3274         if ((attrs.privateFlags & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0) {
   3275             mContext.enforceCallingOrSelfPermission(
   3276                     android.Manifest.permission.STATUS_BAR_SERVICE,
   3277                     "PhoneWindowManager");
   3278             mScreenDecorWindows.add(win);
   3279         }
   3280 
   3281         switch (attrs.type) {
   3282             case TYPE_STATUS_BAR:
   3283                 mContext.enforceCallingOrSelfPermission(
   3284                         android.Manifest.permission.STATUS_BAR_SERVICE,
   3285                         "PhoneWindowManager");
   3286                 if (mStatusBar != null) {
   3287                     if (mStatusBar.isAlive()) {
   3288                         return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
   3289                     }
   3290                 }
   3291                 mStatusBar = win;
   3292                 mStatusBarController.setWindow(win);
   3293                 setKeyguardOccludedLw(mKeyguardOccluded, true /* force */);
   3294                 break;
   3295             case TYPE_NAVIGATION_BAR:
   3296                 mContext.enforceCallingOrSelfPermission(
   3297                         android.Manifest.permission.STATUS_BAR_SERVICE,
   3298                         "PhoneWindowManager");
   3299                 if (mNavigationBar != null) {
   3300                     if (mNavigationBar.isAlive()) {
   3301                         return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
   3302                     }
   3303                 }
   3304                 mNavigationBar = win;
   3305                 mNavigationBarController.setWindow(win);
   3306                 mNavigationBarController.setOnBarVisibilityChangedListener(
   3307                         mNavBarVisibilityListener, true);
   3308                 if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
   3309                 break;
   3310             case TYPE_NAVIGATION_BAR_PANEL:
   3311             case TYPE_STATUS_BAR_PANEL:
   3312             case TYPE_STATUS_BAR_SUB_PANEL:
   3313             case TYPE_VOICE_INTERACTION_STARTING:
   3314                 mContext.enforceCallingOrSelfPermission(
   3315                         android.Manifest.permission.STATUS_BAR_SERVICE,
   3316                         "PhoneWindowManager");
   3317                 break;
   3318         }
   3319         return ADD_OKAY;
   3320     }
   3321 
   3322     /** {@inheritDoc} */
   3323     @Override
   3324     public void removeWindowLw(WindowState win) {
   3325         if (mStatusBar == win) {
   3326             mStatusBar = null;
   3327             mStatusBarController.setWindow(null);
   3328         } else if (mNavigationBar == win) {
   3329             mNavigationBar = null;
   3330             mNavigationBarController.setWindow(null);
   3331         }
   3332         mScreenDecorWindows.remove(win);
   3333     }
   3334 
   3335     static final boolean PRINT_ANIM = false;
   3336 
   3337     /** {@inheritDoc} */
   3338     @Override
   3339     public int selectAnimationLw(WindowState win, int transit) {
   3340         if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
   3341               + ": transit=" + transit);
   3342         if (win == mStatusBar) {
   3343             final boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
   3344             final boolean expanded = win.getAttrs().height == MATCH_PARENT
   3345                     && win.getAttrs().width == MATCH_PARENT;
   3346             if (isKeyguard || expanded) {
   3347                 return -1;
   3348             }
   3349             if (transit == TRANSIT_EXIT
   3350                     || transit == TRANSIT_HIDE) {
   3351                 return R.anim.dock_top_exit;
   3352             } else if (transit == TRANSIT_ENTER
   3353                     || transit == TRANSIT_SHOW) {
   3354                 return R.anim.dock_top_enter;
   3355             }
   3356         } else if (win == mNavigationBar) {
   3357             if (win.getAttrs().windowAnimations != 0) {
   3358                 return 0;
   3359             }
   3360             // This can be on either the bottom or the right or the left.
   3361             if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
   3362                 if (transit == TRANSIT_EXIT
   3363                         || transit == TRANSIT_HIDE) {
   3364                     if (isKeyguardShowingAndNotOccluded()) {
   3365                         return R.anim.dock_bottom_exit_keyguard;
   3366                     } else {
   3367                         return R.anim.dock_bottom_exit;
   3368                     }
   3369                 } else if (transit == TRANSIT_ENTER
   3370                         || transit == TRANSIT_SHOW) {
   3371                     return R.anim.dock_bottom_enter;
   3372                 }
   3373             } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
   3374                 if (transit == TRANSIT_EXIT
   3375                         || transit == TRANSIT_HIDE) {
   3376                     return R.anim.dock_right_exit;
   3377                 } else if (transit == TRANSIT_ENTER
   3378                         || transit == TRANSIT_SHOW) {
   3379                     return R.anim.dock_right_enter;
   3380                 }
   3381             } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
   3382                 if (transit == TRANSIT_EXIT
   3383                         || transit == TRANSIT_HIDE) {
   3384                     return R.anim.dock_left_exit;
   3385                 } else if (transit == TRANSIT_ENTER
   3386                         || transit == TRANSIT_SHOW) {
   3387                     return R.anim.dock_left_enter;
   3388                 }
   3389             }
   3390         } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) {
   3391             return selectDockedDividerAnimationLw(win, transit);
   3392         }
   3393 
   3394         if (transit == TRANSIT_PREVIEW_DONE) {
   3395             if (win.hasAppShownWindows()) {
   3396                 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
   3397                 return com.android.internal.R.anim.app_starting_exit;
   3398             }
   3399         } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
   3400                 && transit == TRANSIT_ENTER) {
   3401             // Special case: we are animating in a dream, while the keyguard
   3402             // is shown.  We don't want an animation on the dream, because
   3403             // we need it shown immediately with the keyguard animating away
   3404             // to reveal it.
   3405             return -1;
   3406         }
   3407 
   3408         return 0;
   3409     }
   3410 
   3411     private int selectDockedDividerAnimationLw(WindowState win, int transit) {
   3412         int insets = mWindowManagerFuncs.getDockedDividerInsetsLw();
   3413 
   3414         // If the divider is behind the navigation bar, don't animate.
   3415         final Rect frame = win.getFrameLw();
   3416         final boolean behindNavBar = mNavigationBar != null
   3417                 && ((mNavigationBarPosition == NAV_BAR_BOTTOM
   3418                         && frame.top + insets >= mNavigationBar.getFrameLw().top)
   3419                 || (mNavigationBarPosition == NAV_BAR_RIGHT
   3420                         && frame.left + insets >= mNavigationBar.getFrameLw().left)
   3421                 || (mNavigationBarPosition == NAV_BAR_LEFT
   3422                         && frame.right - insets <= mNavigationBar.getFrameLw().right));
   3423         final boolean landscape = frame.height() > frame.width();
   3424         final boolean offscreenLandscape = landscape && (frame.right - insets <= 0
   3425                 || frame.left + insets >= win.getDisplayFrameLw().right);
   3426         final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0
   3427                 || frame.bottom + insets >= win.getDisplayFrameLw().bottom);
   3428         final boolean offscreen = offscreenLandscape || offscreenPortrait;
   3429         if (behindNavBar || offscreen) {
   3430             return 0;
   3431         }
   3432         if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
   3433             return R.anim.fade_in;
   3434         } else if (transit == TRANSIT_EXIT) {
   3435             return R.anim.fade_out;
   3436         } else {
   3437             return 0;
   3438         }
   3439     }
   3440 
   3441     @Override
   3442     public void selectRotationAnimationLw(int anim[]) {
   3443         // If the screen is off or non-interactive, force a jumpcut.
   3444         final boolean forceJumpcut = !mScreenOnFully || !okToAnimate();
   3445         if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
   3446                 + mTopFullscreenOpaqueWindowState + " rotationAnimation="
   3447                 + (mTopFullscreenOpaqueWindowState == null ?
   3448                         "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation)
   3449                 + " forceJumpcut=" + forceJumpcut);
   3450         if (forceJumpcut) {
   3451             anim[0] = R.anim.rotation_animation_jump_exit;
   3452             anim[1] = R.anim.rotation_animation_enter;
   3453             return;
   3454         }
   3455         if (mTopFullscreenOpaqueWindowState != null) {
   3456             int animationHint = mTopFullscreenOpaqueWindowState.getRotationAnimationHint();
   3457             if (animationHint < 0 && mTopIsFullscreen) {
   3458                 animationHint = mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation;
   3459             }
   3460             switch (animationHint) {
   3461                 case ROTATION_ANIMATION_CROSSFADE:
   3462                 case ROTATION_ANIMATION_SEAMLESS: // Crossfade is fallback for seamless.
   3463                     anim[0] = R.anim.rotation_animation_xfade_exit;
   3464                     anim[1] = R.anim.rotation_animation_enter;
   3465                     break;
   3466                 case ROTATION_ANIMATION_JUMPCUT:
   3467                     anim[0] = R.anim.rotation_animation_jump_exit;
   3468                     anim[1] = R.anim.rotation_animation_enter;
   3469                     break;
   3470                 case ROTATION_ANIMATION_ROTATE:
   3471                 default:
   3472                     anim[0] = anim[1] = 0;
   3473                     break;
   3474             }
   3475         } else {
   3476             anim[0] = anim[1] = 0;
   3477         }
   3478     }
   3479 
   3480     @Override
   3481     public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId,
   3482             boolean forceDefault) {
   3483         switch (exitAnimId) {
   3484             case R.anim.rotation_animation_xfade_exit:
   3485             case R.anim.rotation_animation_jump_exit:
   3486                 // These are the only cases that matter.
   3487                 if (forceDefault) {
   3488                     return false;
   3489                 }
   3490                 int anim[] = new int[2];
   3491                 selectRotationAnimationLw(anim);
   3492                 return (exitAnimId == anim[0] && enterAnimId == anim[1]);
   3493             default:
   3494                 return true;
   3495         }
   3496     }
   3497 
   3498     @Override
   3499     public Animation createHiddenByKeyguardExit(boolean onWallpaper,
   3500             boolean goingToNotificationShade) {
   3501         if (goingToNotificationShade) {
   3502             return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
   3503         }
   3504 
   3505         AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ?
   3506                     R.anim.lock_screen_behind_enter_wallpaper :
   3507                     R.anim.lock_screen_behind_enter);
   3508 
   3509         // TODO: Use XML interpolators when we have log interpolators available in XML.
   3510         final List<Animation> animations = set.getAnimations();
   3511         for (int i = animations.size() - 1; i >= 0; --i) {
   3512             animations.get(i).setInterpolator(mLogDecelerateInterpolator);
   3513         }
   3514 
   3515         return set;
   3516     }
   3517 
   3518 
   3519     @Override
   3520     public Animation createKeyguardWallpaperExit(boolean goingToNotificationShade) {
   3521         if (goingToNotificationShade) {
   3522             return null;
   3523         } else {
   3524             return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
   3525         }
   3526     }
   3527 
   3528     private static void awakenDreams() {
   3529         IDreamManager dreamManager = getDreamManager();
   3530         if (dreamManager != null) {
   3531             try {
   3532                 dreamManager.awaken();
   3533             } catch (RemoteException e) {
   3534                 // fine, stay asleep then
   3535             }
   3536         }
   3537     }
   3538 
   3539     static IDreamManager getDreamManager() {
   3540         return IDreamManager.Stub.asInterface(
   3541                 ServiceManager.checkService(DreamService.DREAM_SERVICE));
   3542     }
   3543 
   3544     TelecomManager getTelecommService() {
   3545         return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
   3546     }
   3547 
   3548     static IAudioService getAudioService() {
   3549         IAudioService audioService = IAudioService.Stub.asInterface(
   3550                 ServiceManager.checkService(Context.AUDIO_SERVICE));
   3551         if (audioService == null) {
   3552             Log.w(TAG, "Unable to find IAudioService interface.");
   3553         }
   3554         return audioService;
   3555     }
   3556 
   3557     boolean keyguardOn() {
   3558         return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode();
   3559     }
   3560 
   3561     private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
   3562             WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
   3563             WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
   3564         };
   3565 
   3566     /** {@inheritDoc} */
   3567     @Override
   3568     public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
   3569         final boolean keyguardOn = keyguardOn();
   3570         final int keyCode = event.getKeyCode();
   3571         final int repeatCount = event.getRepeatCount();
   3572         final int metaState = event.getMetaState();
   3573         final int flags = event.getFlags();
   3574         final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
   3575         final boolean canceled = event.isCanceled();
   3576 
   3577         if (DEBUG_INPUT) {
   3578             Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
   3579                     + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
   3580                     + " canceled=" + canceled);
   3581         }
   3582 
   3583         // If we think we might have a volume down & power key chord on the way
   3584         // but we're not sure, then tell the dispatcher to wait a little while and
   3585         // try again later before dispatching.
   3586         if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
   3587             if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
   3588                 final long now = SystemClock.uptimeMillis();
   3589                 final long timeoutTime = mScreenshotChordVolumeDownKeyTime
   3590                         + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
   3591                 if (now < timeoutTime) {
   3592                     return timeoutTime - now;
   3593                 }
   3594             }
   3595             if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
   3596                     && mScreenshotChordVolumeDownKeyConsumed) {
   3597                 if (!down) {
   3598                     mScreenshotChordVolumeDownKeyConsumed = false;
   3599                 }
   3600                 return -1;
   3601             }
   3602         }
   3603 
   3604         // If an accessibility shortcut might be partially complete, hold off dispatching until we
   3605         // know if it is complete or not
   3606         if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(false)
   3607                 && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
   3608             if (mScreenshotChordVolumeDownKeyTriggered ^ mA11yShortcutChordVolumeUpKeyTriggered) {
   3609                 final long now = SystemClock.uptimeMillis();
   3610                 final long timeoutTime = (mScreenshotChordVolumeDownKeyTriggered
   3611                         ? mScreenshotChordVolumeDownKeyTime : mA11yShortcutChordVolumeUpKeyTime)
   3612                         + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
   3613                 if (now < timeoutTime) {
   3614                     return timeoutTime - now;
   3615                 }
   3616             }
   3617             if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && mScreenshotChordVolumeDownKeyConsumed) {
   3618                 if (!down) {
   3619                     mScreenshotChordVolumeDownKeyConsumed = false;
   3620                 }
   3621                 return -1;
   3622             }
   3623             if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mA11yShortcutChordVolumeUpKeyConsumed) {
   3624                 if (!down) {
   3625                     mA11yShortcutChordVolumeUpKeyConsumed = false;
   3626                 }
   3627                 return -1;
   3628             }
   3629         }
   3630 
   3631         // If a ringer toggle chord could be on the way but we're not sure, then tell the dispatcher
   3632         // to wait a little while and try again later before dispatching.
   3633         if (mRingerToggleChord != VOLUME_HUSH_OFF && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
   3634             if (mA11yShortcutChordVolumeUpKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
   3635                 final long now = SystemClock.uptimeMillis();
   3636                 final long timeoutTime = mA11yShortcutChordVolumeUpKeyTime
   3637                         + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
   3638                 if (now < timeoutTime) {
   3639                     return timeoutTime - now;
   3640                 }
   3641             }
   3642             if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mA11yShortcutChordVolumeUpKeyConsumed) {
   3643                 if (!down) {
   3644                     mA11yShortcutChordVolumeUpKeyConsumed = false;
   3645                 }
   3646                 return -1;
   3647             }
   3648         }
   3649 
   3650         // Cancel any pending meta actions if we see any other keys being pressed between the down
   3651         // of the meta key and its corresponding up.
   3652         if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
   3653             mPendingMetaAction = false;
   3654         }
   3655         // Any key that is not Alt or Meta cancels Caps Lock combo tracking.
   3656         if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) {
   3657             mPendingCapsLockToggle = false;
   3658         }
   3659 
   3660         // First we always handle the home key here, so applications
   3661         // can never break it, although if keyguard is on, we do let
   3662         // it handle it, because that gives us the correct 5 second
   3663         // timeout.
   3664         if (keyCode == KeyEvent.KEYCODE_HOME) {
   3665 
   3666             // If we have released the home key, and didn't do anything else
   3667             // while it was pressed, then it is time to go home!
   3668             if (!down) {
   3669                 cancelPreloadRecentApps();
   3670 
   3671                 mHomePressed = false;
   3672                 if (mHomeConsumed) {
   3673                     mHomeConsumed = false;
   3674                     return -1;
   3675                 }
   3676 
   3677                 if (canceled) {
   3678                     Log.i(TAG, "Ignoring HOME; event canceled.");
   3679                     return -1;
   3680                 }
   3681 
   3682                 // Delay handling home if a double-tap is possible.
   3683                 if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
   3684                     mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
   3685                     mHomeDoubleTapPending = true;
   3686                     mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
   3687                             ViewConfiguration.getDoubleTapTimeout());
   3688                     return -1;
   3689                 }
   3690 
   3691                 handleShortPressOnHome();
   3692                 return -1;
   3693             }
   3694 
   3695             // If a system window has focus, then it doesn't make sense
   3696             // right now to interact with applications.
   3697             WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
   3698             if (attrs != null) {
   3699                 final int type = attrs.type;
   3700                 if (type == TYPE_KEYGUARD_DIALOG
   3701                         || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
   3702                     // the "app" is keyguard, so give it the key
   3703                     return 0;
   3704                 }
   3705                 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
   3706                 for (int i=0; i<typeCount; i++) {
   3707                     if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
   3708                         // don't do anything, but also don't pass it to the app
   3709                         return -1;
   3710                     }
   3711                 }
   3712             }
   3713 
   3714             // Remember that home is pressed and handle special actions.
   3715             if (repeatCount == 0) {
   3716                 mHomePressed = true;
   3717                 if (mHomeDoubleTapPending) {
   3718                     mHomeDoubleTapPending = false;
   3719                     mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
   3720                     handleDoubleTapOnHome();
   3721                 } else if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
   3722                     preloadRecentApps();
   3723                 }
   3724             } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
   3725                 if (!keyguardOn) {
   3726                     handleLongPressOnHome(event.getDeviceId());
   3727                 }
   3728             }
   3729             return -1;
   3730         } else if (keyCode == KeyEvent.KEYCODE_MENU) {
   3731             // Hijack modified menu keys for debugging features
   3732             final int chordBug = KeyEvent.META_SHIFT_ON;
   3733 
   3734             if (down && repeatCount == 0) {
   3735                 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
   3736                     Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
   3737                     mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
   3738                             null, null, null, 0, null, null);
   3739                     return -1;
   3740                 }
   3741             }
   3742         } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
   3743             if (down) {
   3744                 if (repeatCount == 0) {
   3745                     mSearchKeyShortcutPending = true;
   3746                     mConsumeSearchKeyUp = false;
   3747                 }
   3748             } else {
   3749                 mSearchKeyShortcutPending = false;
   3750                 if (mConsumeSearchKeyUp) {
   3751                     mConsumeSearchKeyUp = false;
   3752                     return -1;
   3753                 }
   3754             }
   3755             return 0;
   3756         } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
   3757             if (!keyguardOn) {
   3758                 if (down && repeatCount == 0) {
   3759                     preloadRecentApps();
   3760                 } else if (!down) {
   3761                     toggleRecentApps();
   3762                 }
   3763             }
   3764             return -1;
   3765         } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) {
   3766             if (down) {
   3767                 IStatusBarService service = getStatusBarService();
   3768                 if (service != null) {
   3769                     try {
   3770                         service.expandNotificationsPanel();
   3771                     } catch (RemoteException e) {
   3772                         // do nothing.
   3773                     }
   3774                 }
   3775             }
   3776         } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed()
   3777                 && event.isCtrlPressed()) {
   3778             if (down && repeatCount == 0) {
   3779                 int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION
   3780                         : TAKE_SCREENSHOT_FULLSCREEN;
   3781                 mScreenshotRunnable.setScreenshotType(type);
   3782                 mHandler.post(mScreenshotRunnable);
   3783                 return -1;
   3784             }
   3785         } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
   3786             if (down && repeatCount == 0 && !isKeyguardLocked()) {
   3787                 toggleKeyboardShortcutsMenu(event.getDeviceId());
   3788             }
   3789         } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
   3790             Slog.wtf(TAG, "KEYCODE_ASSIST should be handled in interceptKeyBeforeQueueing");
   3791             return -1;
   3792         } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
   3793             Slog.wtf(TAG, "KEYCODE_VOICE_ASSIST should be handled in interceptKeyBeforeQueueing");
   3794             return -1;
   3795         } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
   3796             if (down && repeatCount == 0) {
   3797                 mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
   3798                 mHandler.post(mScreenshotRunnable);
   3799             }
   3800             return -1;
   3801         } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP
   3802                 || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) {
   3803             if (down) {
   3804                 int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
   3805 
   3806                 // Disable autobrightness if it's on
   3807                 int auto = Settings.System.getIntForUser(
   3808                         mContext.getContentResolver(),
   3809                         Settings.System.SCREEN_BRIGHTNESS_MODE,
   3810                         Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
   3811                         UserHandle.USER_CURRENT_OR_SELF);
   3812                 if (auto != 0) {
   3813                     Settings.System.putIntForUser(mContext.getContentResolver(),
   3814                             Settings.System.SCREEN_BRIGHTNESS_MODE,
   3815                             Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
   3816                             UserHandle.USER_CURRENT_OR_SELF);
   3817                 }
   3818 
   3819                 int min = mPowerManager.getMinimumScreenBrightnessSetting();
   3820                 int max = mPowerManager.getMaximumScreenBrightnessSetting();
   3821                 int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction;
   3822                 int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
   3823                         Settings.System.SCREEN_BRIGHTNESS,
   3824                         mPowerManager.getDefaultScreenBrightnessSetting(),
   3825                         UserHandle.USER_CURRENT_OR_SELF);
   3826                 brightness += step;
   3827                 // Make sure we don't go beyond the limits.
   3828                 brightness = Math.min(max, brightness);
   3829                 brightness = Math.max(min, brightness);
   3830 
   3831                 Settings.System.putIntForUser(mContext.getContentResolver(),
   3832                         Settings.System.SCREEN_BRIGHTNESS, brightness,
   3833                         UserHandle.USER_CURRENT_OR_SELF);
   3834                 startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
   3835                         UserHandle.CURRENT_OR_SELF);
   3836             }
   3837             return -1;
   3838         } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
   3839                 || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
   3840                 || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
   3841             if (mUseTvRouting || mHandleVolumeKeysInWM) {
   3842                 // On TVs or when the configuration is enabled, volume keys never
   3843                 // go to the foreground app.
   3844                 dispatchDirectAudioEvent(event);
   3845                 return -1;
   3846             }
   3847 
   3848             // If the device is in VR mode and keys are "internal" (e.g. on the side of the
   3849             // device), then drop the volume keys and don't forward it to the application/dispatch
   3850             // the audio event.
   3851             if (mPersistentVrModeEnabled) {
   3852                 final InputDevice d = event.getDevice();
   3853                 if (d != null && !d.isExternal()) {
   3854                     return -1;
   3855                 }
   3856             }
   3857         } else if (keyCode == KeyEvent.KEYCODE_TAB && event.isMetaPressed()) {
   3858             // Pass through keyboard navigation keys.
   3859             return 0;
   3860         } else if (mHasFeatureLeanback && interceptBugreportGestureTv(keyCode, down)) {
   3861             return -1;
   3862         } else if (mHasFeatureLeanback && interceptAccessibilityGestureTv(keyCode, down)) {
   3863             return -1;
   3864         } else if (keyCode == KeyEvent.KEYCODE_ALL_APPS) {
   3865             if (!down) {
   3866                 mHandler.removeMessages(MSG_HANDLE_ALL_APPS);
   3867                 Message msg = mHandler.obtainMessage(MSG_HANDLE_ALL_APPS);
   3868                 msg.setAsynchronous(true);
   3869                 msg.sendToTarget();
   3870             }
   3871             return -1;
   3872         }
   3873 
   3874         // Toggle Caps Lock on META-ALT.
   3875         boolean actionTriggered = false;
   3876         if (KeyEvent.isModifierKey(keyCode)) {
   3877             if (!mPendingCapsLockToggle) {
   3878                 // Start tracking meta state for combo.
   3879                 mInitialMetaState = mMetaState;
   3880                 mPendingCapsLockToggle = true;
   3881             } else if (event.getAction() == KeyEvent.ACTION_UP) {
   3882                 int altOnMask = mMetaState & KeyEvent.META_ALT_MASK;
   3883                 int metaOnMask = mMetaState & KeyEvent.META_META_MASK;
   3884 
   3885                 // Check for Caps Lock toggle
   3886                 if ((metaOnMask != 0) && (altOnMask != 0)) {
   3887                     // Check if nothing else is pressed
   3888                     if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) {
   3889                         // Handle Caps Lock Toggle
   3890                         mInputManagerInternal.toggleCapsLock(event.getDeviceId());
   3891                         actionTriggered = true;
   3892                     }
   3893                 }
   3894 
   3895                 // Always stop tracking when key goes up.
   3896                 mPendingCapsLockToggle = false;
   3897             }
   3898         }
   3899         // Store current meta state to be able to evaluate it later.
   3900         mMetaState = metaState;
   3901 
   3902         if (actionTriggered) {
   3903             return -1;
   3904         }
   3905 
   3906         if (KeyEvent.isMetaKey(keyCode)) {
   3907             if (down) {
   3908                 mPendingMetaAction = true;
   3909             } else if (mPendingMetaAction) {
   3910                 launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId());
   3911             }
   3912             return -1;
   3913         }
   3914 
   3915         // Shortcuts are invoked through Search+key, so intercept those here
   3916         // Any printing key that is chorded with Search should be consumed
   3917         // even if no shortcut was invoked.  This prevents text from being
   3918         // inadvertently inserted when using a keyboard that has built-in macro
   3919         // shortcut keys (that emit Search+x) and some of them are not registered.
   3920         if (mSearchKeyShortcutPending) {
   3921             final KeyCharacterMap kcm = event.getKeyCharacterMap();
   3922             if (kcm.isPrintingKey(keyCode)) {
   3923                 mConsumeSearchKeyUp = true;
   3924                 mSearchKeyShortcutPending = false;
   3925                 if (down && repeatCount == 0 && !keyguardOn) {
   3926                     Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
   3927                     if (shortcutIntent != null) {
   3928                         shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   3929                         try {
   3930                             startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
   3931                             dismissKeyboardShortcutsMenu();
   3932                         } catch (ActivityNotFoundException ex) {
   3933                             Slog.w(TAG, "Dropping shortcut key combination because "
   3934                                     + "the activity to which it is registered was not found: "
   3935                                     + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);
   3936                         }
   3937                     } else {
   3938                         Slog.i(TAG, "Dropping unregistered shortcut key combination: "
   3939                                 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));
   3940                     }
   3941                 }
   3942                 return -1;
   3943             }
   3944         }
   3945 
   3946         // Invoke shortcuts using Meta.
   3947         if (down && repeatCount == 0 && !keyguardOn
   3948                 && (metaState & KeyEvent.META_META_ON) != 0) {
   3949             final KeyCharacterMap kcm = event.getKeyCharacterMap();
   3950             if (kcm.isPrintingKey(keyCode)) {
   3951                 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
   3952                         metaState & ~(KeyEvent.META_META_ON
   3953                                 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
   3954                 if (shortcutIntent != null) {
   3955                     shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   3956                     try {
   3957                         startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
   3958                         dismissKeyboardShortcutsMenu();
   3959                     } catch (ActivityNotFoundException ex) {
   3960                         Slog.w(TAG, "Dropping shortcut key combination because "
   3961                                 + "the activity to which it is registered was not found: "
   3962                                 + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
   3963                     }
   3964                     return -1;
   3965                 }
   3966             }
   3967         }
   3968 
   3969         // Handle application launch keys.
   3970         if (down && repeatCount == 0 && !keyguardOn) {
   3971             String category = sApplicationLaunchKeyCategories.get(keyCode);
   3972             if (category != null) {
   3973                 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
   3974                 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   3975                 try {
   3976                     startActivityAsUser(intent, UserHandle.CURRENT);
   3977                     dismissKeyboardShortcutsMenu();
   3978                 } catch (ActivityNotFoundException ex) {
   3979                     Slog.w(TAG, "Dropping application launch key because "
   3980                             + "the activity to which it is registered was not found: "
   3981                             + "keyCode=" + keyCode + ", category=" + category, ex);
   3982                 }
   3983                 return -1;
   3984             }
   3985         }
   3986 
   3987         // Display task switcher for ALT-TAB.
   3988         if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
   3989             if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
   3990                 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
   3991                 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
   3992                     mRecentAppsHeldModifiers = shiftlessModifiers;
   3993                     showRecentApps(true);
   3994                     return -1;
   3995                 }
   3996             }
   3997         } else if (!down && mRecentAppsHeldModifiers != 0
   3998                 && (metaState & mRecentAppsHeldModifiers) == 0) {
   3999             mRecentAppsHeldModifiers = 0;
   4000             hideRecentApps(true, false);
   4001         }
   4002 
   4003         // Handle keyboard layout switching.
   4004         // TODO: Deprecate this behavior when we fully migrate to IME subtype-based layout rotation.
   4005         if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_SPACE
   4006                 && ((metaState & KeyEvent.META_CTRL_MASK) != 0)) {
   4007             int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
   4008             mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
   4009             return -1;
   4010         }
   4011 
   4012         // Handle input method switching.
   4013         if (down && repeatCount == 0
   4014                 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
   4015                         || (keyCode == KeyEvent.KEYCODE_SPACE
   4016                                 && (metaState & KeyEvent.META_META_MASK) != 0))) {
   4017             final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0;
   4018             mWindowManagerFuncs.switchInputMethod(forwardDirection);
   4019             return -1;
   4020         }
   4021         if (mLanguageSwitchKeyPressed && !down
   4022                 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
   4023                         || keyCode == KeyEvent.KEYCODE_SPACE)) {
   4024             mLanguageSwitchKeyPressed = false;
   4025             return -1;
   4026         }
   4027 
   4028         if (isValidGlobalKey(keyCode)
   4029                 && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
   4030             return -1;
   4031         }
   4032 
   4033         if (down) {
   4034             long shortcutCode = keyCode;
   4035             if (event.isCtrlPressed()) {
   4036                 shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
   4037             }
   4038 
   4039             if (event.isAltPressed()) {
   4040                 shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
   4041             }
   4042 
   4043             if (event.isShiftPressed()) {
   4044                 shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
   4045             }
   4046 
   4047             if (event.isMetaPressed()) {
   4048                 shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE;
   4049             }
   4050 
   4051             IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode);
   4052             if (shortcutService != null) {
   4053                 try {
   4054                     if (isUserSetupComplete()) {
   4055                         shortcutService.notifyShortcutKeyPressed(shortcutCode);
   4056                     }
   4057                 } catch (RemoteException e) {
   4058                     mShortcutKeyServices.delete(shortcutCode);
   4059                 }
   4060                 return -1;
   4061             }
   4062         }
   4063 
   4064         // Reserve all the META modifier combos for system behavior
   4065         if ((metaState & KeyEvent.META_META_ON) != 0) {
   4066             return -1;
   4067         }
   4068 
   4069         // Let the application handle the key.
   4070         return 0;
   4071     }
   4072 
   4073     /**
   4074      * TV only: recognizes a remote control gesture for capturing a bug report.
   4075      */
   4076     private boolean interceptBugreportGestureTv(int keyCode, boolean down) {
   4077         // The bugreport capture chord is a long press on DPAD CENTER and BACK simultaneously.
   4078         if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
   4079             mBugreportTvKey1Pressed = down;
   4080         } else if (keyCode == KeyEvent.KEYCODE_BACK) {
   4081             mBugreportTvKey2Pressed = down;
   4082         }
   4083 
   4084         if (mBugreportTvKey1Pressed && mBugreportTvKey2Pressed) {
   4085             if (!mBugreportTvScheduled) {
   4086                 mBugreportTvScheduled = true;
   4087                 Message msg = Message.obtain(mHandler, MSG_BUGREPORT_TV);
   4088                 msg.setAsynchronous(true);
   4089                 mHandler.sendMessageDelayed(msg, BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS);
   4090             }
   4091         } else if (mBugreportTvScheduled) {
   4092             mHandler.removeMessages(MSG_BUGREPORT_TV);
   4093             mBugreportTvScheduled = false;
   4094         }
   4095 
   4096         return mBugreportTvScheduled;
   4097     }
   4098 
   4099     /**
   4100      * TV only: recognizes a remote control gesture as Accessibility shortcut.
   4101      * Shortcut: Long press (BACK + DPAD_DOWN)
   4102      */
   4103     private boolean interceptAccessibilityGestureTv(int keyCode, boolean down) {
   4104         if (keyCode == KeyEvent.KEYCODE_BACK) {
   4105             mAccessibilityTvKey1Pressed = down;
   4106         } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
   4107             mAccessibilityTvKey2Pressed = down;
   4108         }
   4109 
   4110         if (mAccessibilityTvKey1Pressed && mAccessibilityTvKey2Pressed) {
   4111             if (!mAccessibilityTvScheduled) {
   4112                 mAccessibilityTvScheduled = true;
   4113                 Message msg = Message.obtain(mHandler, MSG_ACCESSIBILITY_TV);
   4114                 msg.setAsynchronous(true);
   4115                 mHandler.sendMessageDelayed(msg, getAccessibilityShortcutTimeout());
   4116             }
   4117         } else if (mAccessibilityTvScheduled) {
   4118             mHandler.removeMessages(MSG_ACCESSIBILITY_TV);
   4119             mAccessibilityTvScheduled = false;
   4120         }
   4121 
   4122         return mAccessibilityTvScheduled;
   4123     }
   4124 
   4125     private void requestFullBugreport() {
   4126         if ("1".equals(SystemProperties.get("ro.debuggable"))
   4127                 || Settings.Global.getInt(mContext.getContentResolver(),
   4128                         Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) == 1) {
   4129             try {
   4130                 ActivityManager.getService()
   4131                         .requestBugReport(ActivityManager.BUGREPORT_OPTION_FULL);
   4132             } catch (RemoteException e) {
   4133                 Slog.e(TAG, "Error taking bugreport", e);
   4134             }
   4135         }
   4136     }
   4137 
   4138     /** {@inheritDoc} */
   4139     @Override
   4140     public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
   4141         // Note: This method is only called if the initial down was unhandled.
   4142         if (DEBUG_INPUT) {
   4143             Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
   4144                     + ", flags=" + event.getFlags()
   4145                     + ", keyCode=" + event.getKeyCode()
   4146                     + ", scanCode=" + event.getScanCode()
   4147                     + ", metaState=" + event.getMetaState()
   4148                     + ", repeatCount=" + event.getRepeatCount()
   4149                     + ", policyFlags=" + policyFlags);
   4150         }
   4151 
   4152         KeyEvent fallbackEvent = null;
   4153         if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
   4154             final KeyCharacterMap kcm = event.getKeyCharacterMap();
   4155             final int keyCode = event.getKeyCode();
   4156             final int metaState = event.getMetaState();
   4157             final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
   4158                     && event.getRepeatCount() == 0;
   4159 
   4160             // Check for fallback actions specified by the key character map.
   4161             final FallbackAction fallbackAction;
   4162             if (initialDown) {
   4163                 fallbackAction = kcm.getFallbackAction(keyCode, metaState);
   4164             } else {
   4165                 fallbackAction = mFallbackActions.get(keyCode);
   4166             }
   4167 
   4168             if (fallbackAction != null) {
   4169                 if (DEBUG_INPUT) {
   4170                     Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode
   4171                             + " metaState=" + Integer.toHexString(fallbackAction.metaState));
   4172                 }
   4173 
   4174                 final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
   4175                 fallbackEvent = KeyEvent.obtain(
   4176                         event.getDownTime(), event.getEventTime(),
   4177                         event.getAction(), fallbackAction.keyCode,
   4178                         event.getRepeatCount(), fallbackAction.metaState,
   4179                         event.getDeviceId(), event.getScanCode(),
   4180                         flags, event.getSource(), null);
   4181 
   4182                 if (!interceptFallback(win, fallbackEvent, policyFlags)) {
   4183                     fallbackEvent.recycle();
   4184                     fallbackEvent = null;
   4185                 }
   4186 
   4187                 if (initialDown) {
   4188                     mFallbackActions.put(keyCode, fallbackAction);
   4189                 } else if (event.getAction() == KeyEvent.ACTION_UP) {
   4190                     mFallbackActions.remove(keyCode);
   4191                     fallbackAction.recycle();
   4192                 }
   4193             }
   4194         }
   4195 
   4196         if (DEBUG_INPUT) {
   4197             if (fallbackEvent == null) {
   4198                 Slog.d(TAG, "No fallback.");
   4199             } else {
   4200                 Slog.d(TAG, "Performing fallback: " + fallbackEvent);
   4201             }
   4202         }
   4203         return fallbackEvent;
   4204     }
   4205 
   4206     private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
   4207         int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
   4208         if ((actions & ACTION_PASS_TO_USER) != 0) {
   4209             long delayMillis = interceptKeyBeforeDispatching(
   4210                     win, fallbackEvent, policyFlags);
   4211             if (delayMillis == 0) {
   4212                 return true;
   4213             }
   4214         }
   4215         return false;
   4216     }
   4217 
   4218     @Override
   4219     public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
   4220             throws RemoteException {
   4221         synchronized (mLock) {
   4222             IShortcutService service = mShortcutKeyServices.get(shortcutCode);
   4223             if (service != null && service.asBinder().pingBinder()) {
   4224                 throw new RemoteException("Key already exists.");
   4225             }
   4226 
   4227             mShortcutKeyServices.put(shortcutCode, shortcutService);
   4228         }
   4229     }
   4230 
   4231     @Override
   4232     public void onKeyguardOccludedChangedLw(boolean occluded) {
   4233         if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
   4234             mPendingKeyguardOccluded = occluded;
   4235             mKeyguardOccludedChanged = true;
   4236         } else {
   4237             setKeyguardOccludedLw(occluded, false /* force */);
   4238         }
   4239     }
   4240 
   4241     private int handleStartTransitionForKeyguardLw(int transit, long duration) {
   4242         if (mKeyguardOccludedChanged) {
   4243             if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded="
   4244                     + mPendingKeyguardOccluded);
   4245             mKeyguardOccludedChanged = false;
   4246             if (setKeyguardOccludedLw(mPendingKeyguardOccluded, false /* force */)) {
   4247                 return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER;
   4248             }
   4249         }
   4250         if (AppTransition.isKeyguardGoingAwayTransit(transit)) {
   4251             if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation");
   4252             startKeyguardExitAnimation(SystemClock.uptimeMillis(), duration);
   4253         }
   4254         return 0;
   4255     }
   4256 
   4257     private void launchAssistLongPressAction() {
   4258         performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
   4259         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
   4260 
   4261         // launch the search activity
   4262         Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
   4263         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   4264         try {
   4265             // TODO: This only stops the factory-installed search manager.
   4266             // Need to formalize an API to handle others
   4267             SearchManager searchManager = getSearchManager();
   4268             if (searchManager != null) {
   4269                 searchManager.stopSearch();
   4270             }
   4271             startActivityAsUser(intent, UserHandle.CURRENT);
   4272         } catch (ActivityNotFoundException e) {
   4273             Slog.w(TAG, "No activity to handle assist long press action.", e);
   4274         }
   4275     }
   4276 
   4277     private void launchAssistAction(String hint, int deviceId) {
   4278         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
   4279         if (!isUserSetupComplete()) {
   4280             // Disable opening assist window during setup
   4281             return;
   4282         }
   4283         Bundle args = null;
   4284         if (deviceId > Integer.MIN_VALUE) {
   4285             args = new Bundle();
   4286             args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
   4287         }
   4288         if ((mContext.getResources().getConfiguration().uiMode
   4289                 & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
   4290             // On TV, use legacy handling until assistants are implemented in the proper way.
   4291             ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
   4292                     .launchLegacyAssist(hint, UserHandle.myUserId(), args);
   4293         } else {
   4294             if (hint != null) {
   4295                 if (args == null) {
   4296                     args = new Bundle();
   4297                 }
   4298                 args.putBoolean(hint, true);
   4299             }
   4300             StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
   4301             if (statusbar != null) {
   4302                 statusbar.startAssist(args);
   4303             }
   4304         }
   4305     }
   4306 
   4307     private void startActivityAsUser(Intent intent, UserHandle handle) {
   4308         if (isUserSetupComplete()) {
   4309             mContext.startActivityAsUser(intent, handle);
   4310         } else {
   4311             Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent);
   4312         }
   4313     }
   4314 
   4315     private SearchManager getSearchManager() {
   4316         if (mSearchManager == null) {
   4317             mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
   4318         }
   4319         return mSearchManager;
   4320     }
   4321 
   4322     private void preloadRecentApps() {
   4323         mPreloadedRecentApps = true;
   4324         StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
   4325         if (statusbar != null) {
   4326             statusbar.preloadRecentApps();
   4327         }
   4328     }
   4329 
   4330     private void cancelPreloadRecentApps() {
   4331         if (mPreloadedRecentApps) {
   4332             mPreloadedRecentApps = false;
   4333             StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
   4334             if (statusbar != null) {
   4335                 statusbar.cancelPreloadRecentApps();
   4336             }
   4337         }
   4338     }
   4339 
   4340     private void toggleRecentApps() {
   4341         mPreloadedRecentApps = false; // preloading no longer needs to be canceled
   4342         StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
   4343         if (statusbar != null) {
   4344             statusbar.toggleRecentApps();
   4345         }
   4346     }
   4347 
   4348     @Override
   4349     public void showRecentApps() {
   4350         mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
   4351         mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS).sendToTarget();
   4352     }
   4353 
   4354     private void showRecentApps(boolean triggeredFromAltTab) {
   4355         mPreloadedRecentApps = false; // preloading no longer needs to be canceled
   4356         StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
   4357         if (statusbar != null) {
   4358             statusbar.showRecentApps(triggeredFromAltTab);
   4359         }
   4360     }
   4361 
   4362     private void toggleKeyboardShortcutsMenu(int deviceId) {
   4363         StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
   4364         if (statusbar != null) {
   4365             statusbar.toggleKeyboardShortcutsMenu(deviceId);
   4366         }
   4367     }
   4368 
   4369     private void dismissKeyboardShortcutsMenu() {
   4370         StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
   4371         if (statusbar != null) {
   4372             statusbar.dismissKeyboardShortcutsMenu();
   4373         }
   4374     }
   4375 
   4376     private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
   4377         mPreloadedRecentApps = false; // preloading no longer needs to be canceled
   4378         StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
   4379         if (statusbar != null) {
   4380             statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
   4381         }
   4382     }
   4383 
   4384     void launchHomeFromHotKey() {
   4385         launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/);
   4386     }
   4387 
   4388     /**
   4389      * A home key -> launch home action was detected.  Take the appropriate action
   4390      * given the situation with the keyguard.
   4391      */
   4392     void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) {
   4393         // Abort possibly stuck animations.
   4394         mHandler.post(mWindowManagerFuncs::triggerAnimationFailsafe);
   4395 
   4396         if (respectKeyguard) {
   4397             if (isKeyguardShowingAndNotOccluded()) {
   4398                 // don't launch home if keyguard showing
   4399                 return;
   4400             } else if (mKeyguardOccluded && mKeyguardDelegate.isShowing()) {
   4401                 mKeyguardDelegate.dismiss(new KeyguardDismissCallback() {
   4402                     @Override
   4403                     public void onDismissSucceeded() throws RemoteException {
   4404                         mHandler.post(() -> {
   4405                             startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
   4406                         });
   4407                     }
   4408                 }, null /* message */);
   4409                 return;
   4410             } else if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) {
   4411                 // when in keyguard restricted mode, must first verify unlock
   4412                 // before launching home
   4413                 mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
   4414                     @Override
   4415                     public void onKeyguardExitResult(boolean success) {
   4416                         if (success) {
   4417                             startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
   4418                         }
   4419                     }
   4420                 });
   4421                 return;
   4422             }
   4423         }
   4424 
   4425         // no keyguard stuff to worry about, just launch home!
   4426         if (mRecentsVisible) {
   4427             try {
   4428                 ActivityManager.getService().stopAppSwitches();
   4429             } catch (RemoteException e) {}
   4430 
   4431             // Hide Recents and notify it to launch Home
   4432             if (awakenFromDreams) {
   4433                 awakenDreams();
   4434             }
   4435             hideRecentApps(false, true);
   4436         } else {
   4437             // Otherwise, just launch Home
   4438             startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
   4439         }
   4440     }
   4441 
   4442     private final Runnable mClearHideNavigationFlag = new Runnable() {
   4443         @Override
   4444         public void run() {
   4445             synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
   4446                 // Clear flags.
   4447                 mForceClearedSystemUiFlags &=
   4448                         ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
   4449             }
   4450             mWindowManagerFuncs.reevaluateStatusBarVisibility();
   4451         }
   4452     };
   4453 
   4454     /**
   4455      * Input handler used while nav bar is hidden.  Captures any touch on the screen,
   4456      * to determine when the nav bar should be shown and prevent applications from
   4457      * receiving those touches.
   4458      */
   4459     final class HideNavInputEventReceiver extends InputEventReceiver {
   4460         public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
   4461             super(inputChannel, looper);
   4462         }
   4463 
   4464         @Override
   4465         public void onInputEvent(InputEvent event, int displayId) {
   4466             boolean handled = false;
   4467             try {
   4468                 if (event instanceof MotionEvent
   4469                         && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
   4470                     final MotionEvent motionEvent = (MotionEvent)event;
   4471                     if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
   4472                         // When the user taps down, we re-show the nav bar.
   4473                         boolean changed = false;
   4474                         synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
   4475                             if (mInputConsumer == null) {
   4476                                 return;
   4477                             }
   4478                             // Any user activity always causes us to show the
   4479                             // navigation controls, if they had been hidden.
   4480                             // We also clear the low profile and only content
   4481                             // flags so that tapping on the screen will atomically
   4482                             // restore all currently hidden screen decorations.
   4483                             int newVal = mResettingSystemUiFlags |
   4484                                     View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
   4485                                     View.SYSTEM_UI_FLAG_LOW_PROFILE |
   4486                                     View.SYSTEM_UI_FLAG_FULLSCREEN;
   4487                             if (mResettingSystemUiFlags != newVal) {
   4488                                 mResettingSystemUiFlags = newVal;
   4489                                 changed = true;
   4490                             }
   4491                             // We don't allow the system's nav bar to be hidden
   4492                             // again for 1 second, to prevent applications from
   4493                             // spamming us and keeping it from being shown.
   4494                             newVal = mForceClearedSystemUiFlags |
   4495                                     View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
   4496                             if (mForceClearedSystemUiFlags != newVal) {
   4497                                 mForceClearedSystemUiFlags = newVal;
   4498                                 changed = true;
   4499                                 mHandler.postDelayed(mClearHideNavigationFlag, 1000);
   4500                             }
   4501                         }
   4502                         if (changed) {
   4503                             mWindowManagerFuncs.reevaluateStatusBarVisibility();
   4504                         }
   4505                     }
   4506                 }
   4507             } finally {
   4508                 finishInputEvent(event, handled);
   4509             }
   4510         }
   4511     }
   4512 
   4513     @Override
   4514     public void setRecentsVisibilityLw(boolean visible) {
   4515         mRecentsVisible = visible;
   4516     }
   4517 
   4518     @Override
   4519     public void setPipVisibilityLw(boolean visible) {
   4520         mPictureInPictureVisible = visible;
   4521     }
   4522 
   4523     @Override
   4524     public void setNavBarVirtualKeyHapticFeedbackEnabledLw(boolean enabled) {
   4525         mNavBarVirtualKeyHapticFeedbackEnabled = enabled;
   4526     }
   4527 
   4528     @Override
   4529     public int adjustSystemUiVisibilityLw(int visibility) {
   4530         mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
   4531         mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
   4532 
   4533         // Reset any bits in mForceClearingStatusBarVisibility that
   4534         // are now clear.
   4535         mResettingSystemUiFlags &= visibility;
   4536         // Clear any bits in the new visibility that are currently being
   4537         // force cleared, before reporting it.
   4538         return visibility & ~mResettingSystemUiFlags
   4539                 & ~mForceClearedSystemUiFlags;
   4540     }
   4541 
   4542     @Override
   4543     // TODO: Should probably be moved into DisplayFrames.
   4544     public boolean getLayoutHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
   4545             DisplayFrames displayFrames, Rect outFrame, Rect outContentInsets, Rect outStableInsets,
   4546             Rect outOutsets, DisplayCutout.ParcelableWrapper outDisplayCutout) {
   4547         final int fl = PolicyControl.getWindowFlags(null, attrs);
   4548         final int pfl = attrs.privateFlags;
   4549         final int requestedSysUiVis = PolicyControl.getSystemUiVisibility(null, attrs);
   4550         final int sysUiVis = requestedSysUiVis | getImpliedSysUiFlagsForLayout(attrs);
   4551         final int displayRotation = displayFrames.mRotation;
   4552         final int displayWidth = displayFrames.mDisplayWidth;
   4553         final int displayHeight = displayFrames.mDisplayHeight;
   4554 
   4555         final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
   4556         if (useOutsets) {
   4557             int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
   4558             if (outset > 0) {
   4559                 if (displayRotation == Surface.ROTATION_0) {
   4560                     outOutsets.bottom += outset;
   4561                 } else if (displayRotation == Surface.ROTATION_90) {
   4562                     outOutsets.right += outset;
   4563                 } else if (displayRotation == Surface.ROTATION_180) {
   4564                     outOutsets.top += outset;
   4565                 } else if (displayRotation == Surface.ROTATION_270) {
   4566                     outOutsets.left += outset;
   4567                 }
   4568             }
   4569         }
   4570 
   4571         final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) != 0;
   4572         final boolean layoutInScreenAndInsetDecor = layoutInScreen &&
   4573                 (fl & FLAG_LAYOUT_INSET_DECOR) != 0;
   4574         final boolean screenDecor = (pfl & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0;
   4575 
   4576         if (layoutInScreenAndInsetDecor && !screenDecor) {
   4577             int availRight, availBottom;
   4578             if (canHideNavigationBar() &&
   4579                     (sysUiVis & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
   4580                 outFrame.set(displayFrames.mUnrestricted);
   4581                 availRight = displayFrames.mUnrestricted.right;
   4582                 availBottom = displayFrames.mUnrestricted.bottom;
   4583             } else {
   4584                 outFrame.set(displayFrames.mRestricted);
   4585                 availRight = displayFrames.mRestricted.right;
   4586                 availBottom = displayFrames.mRestricted.bottom;
   4587             }
   4588             outStableInsets.set(displayFrames.mStable.left, displayFrames.mStable.top,
   4589                     availRight - displayFrames.mStable.right,
   4590                     availBottom - displayFrames.mStable.bottom);
   4591 
   4592             if ((sysUiVis & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
   4593                 if ((fl & FLAG_FULLSCREEN) != 0) {
   4594                     outContentInsets.set(displayFrames.mStableFullscreen.left,
   4595                             displayFrames.mStableFullscreen.top,
   4596                             availRight - displayFrames.mStableFullscreen.right,
   4597                             availBottom - displayFrames.mStableFullscreen.bottom);
   4598                 } else {
   4599                     outContentInsets.set(outStableInsets);
   4600                 }
   4601             } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
   4602                 outContentInsets.setEmpty();
   4603             } else {
   4604                 outContentInsets.set(displayFrames.mCurrent.left, displayFrames.mCurrent.top,
   4605                         availRight - displayFrames.mCurrent.right,
   4606                         availBottom - displayFrames.mCurrent.bottom);
   4607             }
   4608 
   4609             if (taskBounds != null) {
   4610                 calculateRelevantTaskInsets(taskBounds, outContentInsets,
   4611                         displayWidth, displayHeight);
   4612                 calculateRelevantTaskInsets(taskBounds, outStableInsets,
   4613                         displayWidth, displayHeight);
   4614                 outFrame.intersect(taskBounds);
   4615             }
   4616             outDisplayCutout.set(displayFrames.mDisplayCutout.calculateRelativeTo(outFrame)
   4617                     .getDisplayCutout());
   4618             return mForceShowSystemBars;
   4619         } else {
   4620             if (layoutInScreen) {
   4621                 outFrame.set(displayFrames.mUnrestricted);
   4622             } else {
   4623                 outFrame.set(displayFrames.mStable);
   4624             }
   4625             if (taskBounds != null) {
   4626                 outFrame.intersect(taskBounds);
   4627             }
   4628 
   4629             outContentInsets.setEmpty();
   4630             outStableInsets.setEmpty();
   4631             outDisplayCutout.set(DisplayCutout.NO_CUTOUT);
   4632             return mForceShowSystemBars;
   4633         }
   4634     }
   4635 
   4636     /**
   4637      * For any given task bounds, the insets relevant for these bounds given the insets relevant
   4638      * for the entire display.
   4639      */
   4640     private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth,
   4641             int displayHeight) {
   4642         mTmpRect.set(0, 0, displayWidth, displayHeight);
   4643         mTmpRect.inset(inOutInsets);
   4644         mTmpRect.intersect(taskBounds);
   4645         int leftInset = mTmpRect.left - taskBounds.left;
   4646         int topInset = mTmpRect.top - taskBounds.top;
   4647         int rightInset = taskBounds.right - mTmpRect.right;
   4648         int bottomInset = taskBounds.bottom - mTmpRect.bottom;
   4649         inOutInsets.set(leftInset, topInset, rightInset, bottomInset);
   4650     }
   4651 
   4652     private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
   4653         return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
   4654                 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
   4655     }
   4656 
   4657     /** {@inheritDoc} */
   4658     @Override
   4659     public void beginLayoutLw(DisplayFrames displayFrames, int uiMode) {
   4660         displayFrames.onBeginLayout();
   4661         // TODO(multi-display): This doesn't seem right...Maybe only apply to default display?
   4662         mSystemGestures.screenWidth = displayFrames.mUnrestricted.width();
   4663         mSystemGestures.screenHeight = displayFrames.mUnrestricted.height();
   4664         mDockLayer = 0x10000000;
   4665         mStatusBarLayer = -1;
   4666 
   4667         // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
   4668         final Rect pf = mTmpParentFrame;
   4669         final Rect df = mTmpDisplayFrame;
   4670         final Rect of = mTmpOverscanFrame;
   4671         final Rect vf = mTmpVisibleFrame;
   4672         final Rect dcf = mTmpDecorFrame;
   4673         vf.set(displayFrames.mDock);
   4674         of.set(displayFrames.mDock);
   4675         df.set(displayFrames.mDock);
   4676         pf.set(displayFrames.mDock);
   4677         dcf.setEmpty();  // Decor frame N/A for system bars.
   4678 
   4679         if (displayFrames.mDisplayId == DEFAULT_DISPLAY) {
   4680             // For purposes of putting out fake window up to steal focus, we will
   4681             // drive nav being hidden only by whether it is requested.
   4682             final int sysui = mLastSystemUiFlags;
   4683             boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
   4684             boolean navTranslucent = (sysui
   4685                     & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
   4686             boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
   4687             boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
   4688             boolean navAllowedHidden = immersive || immersiveSticky;
   4689             navTranslucent &= !immersiveSticky;  // transient trumps translucent
   4690             boolean isKeyguardShowing = isStatusBarKeyguard() && !mKeyguardOccluded;
   4691             if (!isKeyguardShowing) {
   4692                 navTranslucent &= areTranslucentBarsAllowed();
   4693             }
   4694             boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null
   4695                     && mStatusBar.getAttrs().height == MATCH_PARENT
   4696                     && mStatusBar.getAttrs().width == MATCH_PARENT;
   4697 
   4698             // When the navigation bar isn't visible, we put up a fake input window to catch all
   4699             // touch events. This way we can detect when the user presses anywhere to bring back the
   4700             // nav bar and ensure the application doesn't see the event.
   4701             if (navVisible || navAllowedHidden) {
   4702                 if (mInputConsumer != null) {
   4703                     mHandler.sendMessage(
   4704                             mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
   4705                     mInputConsumer = null;
   4706                 }
   4707             } else if (mInputConsumer == null && mStatusBar != null && canHideNavigationBar()) {
   4708                 mInputConsumer = mWindowManagerFuncs.createInputConsumer(mHandler.getLooper(),
   4709                         INPUT_CONSUMER_NAVIGATION,
   4710                         (channel, looper) -> new HideNavInputEventReceiver(channel, looper));
   4711                 // As long as mInputConsumer is active, hover events are not dispatched to the app
   4712                 // and the pointer icon is likely to become stale. Hide it to avoid confusion.
   4713                 InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL);
   4714             }
   4715 
   4716             // For purposes of positioning and showing the nav bar, if we have decided that it can't
   4717             // be hidden (because of the screen aspect ratio), then take that into account.
   4718             navVisible |= !canHideNavigationBar();
   4719 
   4720             boolean updateSysUiVisibility = layoutNavigationBar(displayFrames, uiMode, dcf,
   4721                     navVisible, navTranslucent, navAllowedHidden, statusBarExpandedNotKeyguard);
   4722             if (DEBUG_LAYOUT) Slog.i(TAG, "mDock rect:" + displayFrames.mDock);
   4723             updateSysUiVisibility |= layoutStatusBar(
   4724                     displayFrames, pf, df, of, vf, dcf, sysui, isKeyguardShowing);
   4725             if (updateSysUiVisibility) {
   4726                 updateSystemUiVisibilityLw();
   4727             }
   4728         }
   4729         layoutScreenDecorWindows(displayFrames, pf, df, dcf);
   4730 
   4731         if (displayFrames.mDisplayCutoutSafe.top > displayFrames.mUnrestricted.top) {
   4732             // Make sure that the zone we're avoiding for the cutout is at least as tall as the
   4733             // status bar; otherwise fullscreen apps will end up cutting halfway into the status
   4734             // bar.
   4735             displayFrames.mDisplayCutoutSafe.top = Math.max(displayFrames.mDisplayCutoutSafe.top,
   4736                     displayFrames.mStable.top);
   4737         }
   4738     }
   4739 
   4740     private void layoutScreenDecorWindows(DisplayFrames displayFrames, Rect pf, Rect df, Rect dcf) {
   4741         if (mScreenDecorWindows.isEmpty()) {
   4742             return;
   4743         }
   4744 
   4745         final int displayId = displayFrames.mDisplayId;
   4746         final Rect dockFrame = displayFrames.mDock;
   4747         final int displayHeight = displayFrames.mDisplayHeight;
   4748         final int displayWidth = displayFrames.mDisplayWidth;
   4749 
   4750         for (int i = mScreenDecorWindows.size() - 1; i >= 0; --i) {
   4751             final WindowState w = mScreenDecorWindows.valueAt(i);
   4752             if (w.getDisplayId() != displayId || !w.isVisibleLw()) {
   4753                 // Skip if not on the same display or not visible.
   4754                 continue;
   4755             }
   4756 
   4757             w.computeFrameLw(pf /* parentFrame */, df /* displayFrame */, df /* overlayFrame */,
   4758                     df /* contentFrame */, df /* visibleFrame */, dcf /* decorFrame */,
   4759                     df /* stableFrame */, df /* outsetFrame */, displayFrames.mDisplayCutout,
   4760                     false /* parentFrameWasClippedByDisplayCutout */);
   4761             final Rect frame = w.getFrameLw();
   4762 
   4763             if (frame.left <= 0 && frame.top <= 0) {
   4764                 // Docked at left or top.
   4765                 if (frame.bottom >= displayHeight) {
   4766                     // Docked left.
   4767                     dockFrame.left = Math.max(frame.right, dockFrame.left);
   4768                 } else if (frame.right >= displayWidth ) {
   4769                     // Docked top.
   4770                     dockFrame.top = Math.max(frame.bottom, dockFrame.top);
   4771                 } else {
   4772                     Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w
   4773                             + " not docked on left or top of display. frame=" + frame
   4774                             + " displayWidth=" + displayWidth + " displayHeight=" + displayHeight);
   4775                 }
   4776             } else if (frame.right >= displayWidth && frame.bottom >= displayHeight) {
   4777                 // Docked at right or bottom.
   4778                 if (frame.top <= 0) {
   4779                     // Docked right.
   4780                     dockFrame.right = Math.min(frame.left, dockFrame.right);
   4781                 } else if (frame.left <= 0) {
   4782                     // Docked bottom.
   4783                     dockFrame.bottom = Math.min(frame.top, dockFrame.bottom);
   4784                 } else {
   4785                     Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w
   4786                             + " not docked on right or bottom" + " of display. frame=" + frame
   4787                             + " displayWidth=" + displayWidth + " displayHeight=" + displayHeight);
   4788                 }
   4789             } else {
   4790                 // Screen decor windows are required to be docked on one of the sides of the screen.
   4791                 Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w
   4792                         + " not docked on one of the sides of the display. frame=" + frame
   4793                         + " displayWidth=" + displayWidth + " displayHeight=" + displayHeight);
   4794             }
   4795         }
   4796 
   4797         displayFrames.mRestricted.set(dockFrame);
   4798         displayFrames.mCurrent.set(dockFrame);
   4799         displayFrames.mVoiceContent.set(dockFrame);
   4800         displayFrames.mSystem.set(dockFrame);
   4801         displayFrames.mContent.set(dockFrame);
   4802         displayFrames.mRestrictedOverscan.set(dockFrame);
   4803     }
   4804 
   4805     private boolean layoutStatusBar(DisplayFrames displayFrames, Rect pf, Rect df, Rect of, Rect vf,
   4806             Rect dcf, int sysui, boolean isKeyguardShowing) {
   4807         // decide where the status bar goes ahead of time
   4808         if (mStatusBar == null) {
   4809             return false;
   4810         }
   4811         // apply any navigation bar insets
   4812         of.set(displayFrames.mUnrestricted);
   4813         df.set(displayFrames.mUnrestricted);
   4814         pf.set(displayFrames.mUnrestricted);
   4815         vf.set(displayFrames.mStable);
   4816 
   4817         mStatusBarLayer = mStatusBar.getSurfaceLayer();
   4818 
   4819         // Let the status bar determine its size.
   4820         mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
   4821                 vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
   4822                 dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */,
   4823                 displayFrames.mDisplayCutout, false /* parentFrameWasClippedByDisplayCutout */);
   4824 
   4825         // For layout, the status bar is always at the top with our fixed height.
   4826         displayFrames.mStable.top = displayFrames.mUnrestricted.top
   4827                 + mStatusBarHeightForRotation[displayFrames.mRotation];
   4828         // Make sure the status bar covers the entire cutout height
   4829         displayFrames.mStable.top = Math.max(displayFrames.mStable.top,
   4830                 displayFrames.mDisplayCutoutSafe.top);
   4831 
   4832         // Tell the bar controller where the collapsed status bar content is
   4833         mTmpRect.set(mStatusBar.getContentFrameLw());
   4834         mTmpRect.intersect(displayFrames.mDisplayCutoutSafe);
   4835         mTmpRect.top = mStatusBar.getContentFrameLw().top;  // Ignore top display cutout inset
   4836         mTmpRect.bottom = displayFrames.mStable.top;  // Use collapsed status bar size
   4837         mStatusBarController.setContentFrame(mTmpRect);
   4838 
   4839         boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
   4840         boolean statusBarTranslucent = (sysui
   4841                 & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
   4842         if (!isKeyguardShowing) {
   4843             statusBarTranslucent &= areTranslucentBarsAllowed();
   4844         }
   4845 
   4846         // If the status bar is hidden, we don't want to cause windows behind it to scroll.
   4847         if (mStatusBar.isVisibleLw() && !statusBarTransient) {
   4848             // Status bar may go away, so the screen area it occupies is available to apps but just
   4849             // covering them when the status bar is visible.
   4850             final Rect dockFrame = displayFrames.mDock;
   4851             dockFrame.top = displayFrames.mStable.top;
   4852             displayFrames.mContent.set(dockFrame);
   4853             displayFrames.mVoiceContent.set(dockFrame);
   4854             displayFrames.mCurrent.set(dockFrame);
   4855 
   4856             if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " + String.format(
   4857                     "dock=%s content=%s cur=%s", dockFrame.toString(),
   4858                     displayFrames.mContent.toString(), displayFrames.mCurrent.toString()));
   4859 
   4860             if (!mStatusBar.isAnimatingLw() && !statusBarTranslucent
   4861                     && !mStatusBarController.wasRecentlyTranslucent()) {
   4862                 // If the opaque status bar is currently requested to be visible, and not in the
   4863                 // process of animating on or off, then we can tell the app that it is covered by it.
   4864                 displayFrames.mSystem.top = displayFrames.mStable.top;
   4865             }
   4866         }
   4867         return mStatusBarController.checkHiddenLw();
   4868     }
   4869 
   4870     private boolean layoutNavigationBar(DisplayFrames displayFrames, int uiMode, Rect dcf,
   4871             boolean navVisible, boolean navTranslucent, boolean navAllowedHidden,
   4872             boolean statusBarExpandedNotKeyguard) {
   4873         if (mNavigationBar == null) {
   4874             return false;
   4875         }
   4876         boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
   4877         // Force the navigation bar to its appropriate place and size. We need to do this directly,
   4878         // instead of relying on it to bubble up from the nav bar, because this needs to change
   4879         // atomically with screen rotations.
   4880         final int rotation = displayFrames.mRotation;
   4881         final int displayHeight = displayFrames.mDisplayHeight;
   4882         final int displayWidth = displayFrames.mDisplayWidth;
   4883         final Rect dockFrame = displayFrames.mDock;
   4884         mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight, rotation);
   4885 
   4886         final Rect cutoutSafeUnrestricted = mTmpRect;
   4887         cutoutSafeUnrestricted.set(displayFrames.mUnrestricted);
   4888         cutoutSafeUnrestricted.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
   4889 
   4890         if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
   4891             // It's a system nav bar or a portrait screen; nav bar goes on bottom.
   4892             final int top = cutoutSafeUnrestricted.bottom
   4893                     - getNavigationBarHeight(rotation, uiMode);
   4894             mTmpNavigationFrame.set(0, top, displayWidth, displayFrames.mUnrestricted.bottom);
   4895             displayFrames.mStable.bottom = displayFrames.mStableFullscreen.bottom = top;
   4896             if (transientNavBarShowing) {
   4897                 mNavigationBarController.setBarShowingLw(true);
   4898             } else if (navVisible) {
   4899                 mNavigationBarController.setBarShowingLw(true);
   4900                 dockFrame.bottom = displayFrames.mRestricted.bottom
   4901                         = displayFrames.mRestrictedOverscan.bottom = top;
   4902             } else {
   4903                 // We currently want to hide the navigation UI - unless we expanded the status bar.
   4904                 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
   4905             }
   4906             if (navVisible && !navTranslucent && !navAllowedHidden
   4907                     && !mNavigationBar.isAnimatingLw()
   4908                     && !mNavigationBarController.wasRecentlyTranslucent()) {
   4909                 // If the opaque nav bar is currently requested to be visible and not in the process
   4910                 // of animating on or off, then we can tell the app that it is covered by it.
   4911                 displayFrames.mSystem.bottom = top;
   4912             }
   4913         } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
   4914             // Landscape screen; nav bar goes to the right.
   4915             final int left = cutoutSafeUnrestricted.right
   4916                     - getNavigationBarWidth(rotation, uiMode);
   4917             mTmpNavigationFrame.set(left, 0, displayFrames.mUnrestricted.right, displayHeight);
   4918             displayFrames.mStable.right = displayFrames.mStableFullscreen.right = left;
   4919             if (transientNavBarShowing) {
   4920                 mNavigationBarController.setBarShowingLw(true);
   4921             } else if (navVisible) {
   4922                 mNavigationBarController.setBarShowingLw(true);
   4923                 dockFrame.right = displayFrames.mRestricted.right
   4924                         = displayFrames.mRestrictedOverscan.right = left;
   4925             } else {
   4926                 // We currently want to hide the navigation UI - unless we expanded the status bar.
   4927                 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
   4928             }
   4929             if (navVisible && !navTranslucent && !navAllowedHidden
   4930                     && !mNavigationBar.isAnimatingLw()
   4931                     && !mNavigationBarController.wasRecentlyTranslucent()) {
   4932                 // If the nav bar is currently requested to be visible, and not in the process of
   4933                 // animating on or off, then we can tell the app that it is covered by it.
   4934                 displayFrames.mSystem.right = left;
   4935             }
   4936         } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
   4937             // Seascape screen; nav bar goes to the left.
   4938             final int right = cutoutSafeUnrestricted.left
   4939                     + getNavigationBarWidth(rotation, uiMode);
   4940             mTmpNavigationFrame.set(displayFrames.mUnrestricted.left, 0, right, displayHeight);
   4941             displayFrames.mStable.left = displayFrames.mStableFullscreen.left = right;
   4942             if (transientNavBarShowing) {
   4943                 mNavigationBarController.setBarShowingLw(true);
   4944             } else if (navVisible) {
   4945                 mNavigationBarController.setBarShowingLw(true);
   4946                 dockFrame.left = displayFrames.mRestricted.left =
   4947                         displayFrames.mRestrictedOverscan.left = right;
   4948             } else {
   4949                 // We currently want to hide the navigation UI - unless we expanded the status bar.
   4950                 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
   4951             }
   4952             if (navVisible && !navTranslucent && !navAllowedHidden
   4953                     && !mNavigationBar.isAnimatingLw()
   4954                     && !mNavigationBarController.wasRecentlyTranslucent()) {
   4955                 // If the nav bar is currently requested to be visible, and not in the process of
   4956                 // animating on or off, then we can tell the app that it is covered by it.
   4957                 displayFrames.mSystem.left = right;
   4958             }
   4959         }
   4960 
   4961         // Make sure the content and current rectangles are updated to account for the restrictions
   4962         // from the navigation bar.
   4963         displayFrames.mCurrent.set(dockFrame);
   4964         displayFrames.mVoiceContent.set(dockFrame);
   4965         displayFrames.mContent.set(dockFrame);
   4966         mStatusBarLayer = mNavigationBar.getSurfaceLayer();
   4967         // And compute the final frame.
   4968         mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
   4969                 mTmpNavigationFrame, displayFrames.mDisplayCutoutSafe, mTmpNavigationFrame, dcf,
   4970                 mTmpNavigationFrame, displayFrames.mDisplayCutoutSafe,
   4971                 displayFrames.mDisplayCutout, false /* parentFrameWasClippedByDisplayCutout */);
   4972         mNavigationBarController.setContentFrame(mNavigationBar.getContentFrameLw());
   4973 
   4974         if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
   4975         return mNavigationBarController.checkHiddenLw();
   4976     }
   4977 
   4978     @NavigationBarPosition
   4979     private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
   4980         if (mNavigationBarCanMove && displayWidth > displayHeight) {
   4981             if (displayRotation == Surface.ROTATION_270) {
   4982                 return NAV_BAR_LEFT;
   4983             } else {
   4984                 return NAV_BAR_RIGHT;
   4985             }
   4986         }
   4987         return NAV_BAR_BOTTOM;
   4988     }
   4989 
   4990     /** {@inheritDoc} */
   4991     @Override
   4992     public int getSystemDecorLayerLw() {
   4993         if (mStatusBar != null && mStatusBar.isVisibleLw()) {
   4994             return mStatusBar.getSurfaceLayer();
   4995         }
   4996 
   4997         if (mNavigationBar != null && mNavigationBar.isVisibleLw()) {
   4998             return mNavigationBar.getSurfaceLayer();
   4999         }
   5000 
   5001         return 0;
   5002     }
   5003 
   5004     private void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
   5005             boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf,
   5006             DisplayFrames displayFrames) {
   5007         if (!win.isInputMethodTarget() && attached.isInputMethodTarget()) {
   5008             // Here's a special case: if the child window is not the 'dock window'
   5009             // or input method target, and the window it is attached to is below
   5010             // the dock window, then the frames we computed for the window it is
   5011             // attached to can not be used because the dock is effectively part
   5012             // of the underlying window and the attached window is floating on top
   5013             // of the whole thing. So, we ignore the attached window and explicitly
   5014             // compute the frames that would be appropriate without the dock.
   5015             vf.set(displayFrames.mDock);
   5016             cf.set(displayFrames.mDock);
   5017             of.set(displayFrames.mDock);
   5018             df.set(displayFrames.mDock);
   5019         } else {
   5020             // The effective display frame of the attached window depends on whether it is taking
   5021             // care of insetting its content. If not, we need to use the parent's content frame so
   5022             // that the entire window is positioned within that content. Otherwise we can use the
   5023             // overscan frame and let the attached window take care of positioning its content
   5024             // appropriately.
   5025             if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
   5026                 // Set the content frame of the attached window to the parent's decor frame
   5027                 // (same as content frame when IME isn't present) if specifically requested by
   5028                 // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
   5029                 // Otherwise, use the overscan frame.
   5030                 cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
   5031                         ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
   5032             } else {
   5033                 // If the window is resizing, then we want to base the content frame on our attached
   5034                 // content frame to resize...however, things can be tricky if the attached window is
   5035                 // NOT in resize mode, in which case its content frame will be larger.
   5036                 // Ungh. So to deal with that, make sure the content frame we end up using is not
   5037                 // covering the IM dock.
   5038                 cf.set(attached.getContentFrameLw());
   5039                 if (attached.isVoiceInteraction()) {
   5040                     cf.intersectUnchecked(displayFrames.mVoiceContent);
   5041                 } else if (win.isInputMethodTarget() || attached.isInputMethodTarget()) {
   5042                     cf.intersectUnchecked(displayFrames.mContent);
   5043                 }
   5044             }
   5045             df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
   5046             of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
   5047             vf.set(attached.getVisibleFrameLw());
   5048         }
   5049         // The LAYOUT_IN_SCREEN flag is used to determine whether the attached window should be
   5050         // positioned relative to its parent or the entire screen.
   5051         pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 ? attached.getFrameLw() : df);
   5052     }
   5053 
   5054     private void applyStableConstraints(int sysui, int fl, Rect r, DisplayFrames displayFrames) {
   5055         if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) == 0) {
   5056             return;
   5057         }
   5058         // If app is requesting a stable layout, don't let the content insets go below the stable
   5059         // values.
   5060         if ((fl & FLAG_FULLSCREEN) != 0) {
   5061             r.intersectUnchecked(displayFrames.mStableFullscreen);
   5062         } else {
   5063             r.intersectUnchecked(displayFrames.mStable);
   5064         }
   5065     }
   5066 
   5067     private boolean canReceiveInput(WindowState win) {
   5068         boolean notFocusable =
   5069                 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
   5070         boolean altFocusableIm =
   5071                 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
   5072         boolean notFocusableForIm = notFocusable ^ altFocusableIm;
   5073         return !notFocusableForIm;
   5074     }
   5075 
   5076     /** {@inheritDoc} */
   5077     @Override
   5078     public void layoutWindowLw(WindowState win, WindowState attached, DisplayFrames displayFrames) {
   5079         // We've already done the navigation bar, status bar, and all screen decor windows. If the
   5080         // status bar can receive input, we need to layout it again to accommodate for the IME
   5081         // window.
   5082         if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar
   5083                 || mScreenDecorWindows.contains(win)) {
   5084             return;
   5085         }
   5086         final WindowManager.LayoutParams attrs = win.getAttrs();
   5087         final boolean isDefaultDisplay = win.isDefaultDisplay();
   5088         final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
   5089                 (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
   5090         if (needsToOffsetInputMethodTarget) {
   5091             if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
   5092             offsetInputMethodWindowLw(mLastInputMethodWindow, displayFrames);
   5093         }
   5094 
   5095         final int type = attrs.type;
   5096         final int fl = PolicyControl.getWindowFlags(win, attrs);
   5097         final int pfl = attrs.privateFlags;
   5098         final int sim = attrs.softInputMode;
   5099         final int requestedSysUiFl = PolicyControl.getSystemUiVisibility(null, attrs);
   5100         final int sysUiFl = requestedSysUiFl | getImpliedSysUiFlagsForLayout(attrs);
   5101 
   5102         final Rect pf = mTmpParentFrame;
   5103         final Rect df = mTmpDisplayFrame;
   5104         final Rect of = mTmpOverscanFrame;
   5105         final Rect cf = mTmpContentFrame;
   5106         final Rect vf = mTmpVisibleFrame;
   5107         final Rect dcf = mTmpDecorFrame;
   5108         final Rect sf = mTmpStableFrame;
   5109         Rect osf = null;
   5110         dcf.setEmpty();
   5111 
   5112         final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
   5113                 && mNavigationBar != null && mNavigationBar.isVisibleLw());
   5114 
   5115         final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
   5116 
   5117         final boolean requestedFullscreen = (fl & FLAG_FULLSCREEN) != 0
   5118                 || (requestedSysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
   5119 
   5120         final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) == FLAG_LAYOUT_IN_SCREEN;
   5121         final boolean layoutInsetDecor = (fl & FLAG_LAYOUT_INSET_DECOR) == FLAG_LAYOUT_INSET_DECOR;
   5122 
   5123         sf.set(displayFrames.mStable);
   5124 
   5125         if (type == TYPE_INPUT_METHOD) {
   5126             vf.set(displayFrames.mDock);
   5127             cf.set(displayFrames.mDock);
   5128             of.set(displayFrames.mDock);
   5129             df.set(displayFrames.mDock);
   5130             pf.set(displayFrames.mDock);
   5131             // IM dock windows layout below the nav bar...
   5132             pf.bottom = df.bottom = of.bottom = displayFrames.mUnrestricted.bottom;
   5133             // ...with content insets above the nav bar
   5134             cf.bottom = vf.bottom = displayFrames.mStable.bottom;
   5135             if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
   5136                 // The status bar forces the navigation bar while it's visible. Make sure the IME
   5137                 // avoids the navigation bar in that case.
   5138                 if (mNavigationBarPosition == NAV_BAR_RIGHT) {
   5139                     pf.right = df.right = of.right = cf.right = vf.right =
   5140                             displayFrames.mStable.right;
   5141                 } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
   5142                     pf.left = df.left = of.left = cf.left = vf.left = displayFrames.mStable.left;
   5143                 }
   5144             }
   5145             // IM dock windows always go to the bottom of the screen.
   5146             attrs.gravity = Gravity.BOTTOM;
   5147             mDockLayer = win.getSurfaceLayer();
   5148         } else if (type == TYPE_VOICE_INTERACTION) {
   5149             of.set(displayFrames.mUnrestricted);
   5150             df.set(displayFrames.mUnrestricted);
   5151             pf.set(displayFrames.mUnrestricted);
   5152             if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
   5153                 cf.set(displayFrames.mDock);
   5154             } else {
   5155                 cf.set(displayFrames.mContent);
   5156             }
   5157             if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
   5158                 vf.set(displayFrames.mCurrent);
   5159             } else {
   5160                 vf.set(cf);
   5161             }
   5162         } else if (type == TYPE_WALLPAPER) {
   5163            layoutWallpaper(displayFrames, pf, df, of, cf);
   5164         } else if (win == mStatusBar) {
   5165             of.set(displayFrames.mUnrestricted);
   5166             df.set(displayFrames.mUnrestricted);
   5167             pf.set(displayFrames.mUnrestricted);
   5168             cf.set(displayFrames.mStable);
   5169             vf.set(displayFrames.mStable);
   5170 
   5171             if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
   5172                 cf.bottom = displayFrames.mContent.bottom;
   5173             } else {
   5174                 cf.bottom = displayFrames.mDock.bottom;
   5175                 vf.bottom = displayFrames.mContent.bottom;
   5176             }
   5177         } else {
   5178             dcf.set(displayFrames.mSystem);
   5179             final boolean inheritTranslucentDecor =
   5180                     (attrs.privateFlags & PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0;
   5181             final boolean isAppWindow =
   5182                     type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW;
   5183             final boolean topAtRest =
   5184                     win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
   5185             if (isAppWindow && !inheritTranslucentDecor && !topAtRest) {
   5186                 if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
   5187                         && (fl & FLAG_FULLSCREEN) == 0
   5188                         && (fl & FLAG_TRANSLUCENT_STATUS) == 0
   5189                         && (fl & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
   5190                         && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) {
   5191                     // Ensure policy decor includes status bar
   5192                     dcf.top = displayFrames.mStable.top;
   5193                 }
   5194                 if ((fl & FLAG_TRANSLUCENT_NAVIGATION) == 0
   5195                         && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
   5196                         && (fl & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
   5197                     // Ensure policy decor includes navigation bar
   5198                     dcf.bottom = displayFrames.mStable.bottom;
   5199                     dcf.right = displayFrames.mStable.right;
   5200                 }
   5201             }
   5202 
   5203             if (layoutInScreen && layoutInsetDecor) {
   5204                 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
   5205                             + "): IN_SCREEN, INSET_DECOR");
   5206                 // This is the case for a normal activity window: we want it to cover all of the
   5207                 // screen space, and it can take care of moving its contents to account for screen
   5208                 // decorations that intrude into that space.
   5209                 if (attached != null) {
   5210                     // If this window is attached to another, our display
   5211                     // frame is the same as the one we are attached to.
   5212                     setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf,
   5213                             displayFrames);
   5214                 } else {
   5215                     if (type == TYPE_STATUS_BAR_PANEL || type == TYPE_STATUS_BAR_SUB_PANEL) {
   5216                         // Status bar panels are the only windows who can go on top of the status
   5217                         // bar. They are protected by the STATUS_BAR_SERVICE permission, so they
   5218                         // have the same privileges as the status bar itself.
   5219                         //
   5220                         // However, they should still dodge the navigation bar if it exists.
   5221 
   5222                         pf.left = df.left = of.left = hasNavBar
   5223                                 ? displayFrames.mDock.left : displayFrames.mUnrestricted.left;
   5224                         pf.top = df.top = of.top = displayFrames.mUnrestricted.top;
   5225                         pf.right = df.right = of.right = hasNavBar
   5226                                 ? displayFrames.mRestricted.right
   5227                                 : displayFrames.mUnrestricted.right;
   5228                         pf.bottom = df.bottom = of.bottom = hasNavBar
   5229                                 ? displayFrames.mRestricted.bottom
   5230                                 : displayFrames.mUnrestricted.bottom;
   5231 
   5232                         if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
   5233                                         "Laying out status bar window: (%d,%d - %d,%d)",
   5234                                         pf.left, pf.top, pf.right, pf.bottom));
   5235                     } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
   5236                             && type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW) {
   5237                         // Asking to layout into the overscan region, so give it that pure
   5238                         // unrestricted area.
   5239                         of.set(displayFrames.mOverscan);
   5240                         df.set(displayFrames.mOverscan);
   5241                         pf.set(displayFrames.mOverscan);
   5242                     } else if (canHideNavigationBar()
   5243                             && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
   5244                             && (type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW
   5245                             || type == TYPE_VOLUME_OVERLAY)) {
   5246                         // Asking for layout as if the nav bar is hidden, lets the application
   5247                         // extend into the unrestricted overscan screen area. We only do this for
   5248                         // application windows and certain system windows to ensure no window that
   5249                         // can be above the nav bar can do this.
   5250                         df.set(displayFrames.mOverscan);
   5251                         pf.set(displayFrames.mOverscan);
   5252                         // We need to tell the app about where the frame inside the overscan is, so
   5253                         // it can inset its content by that amount -- it didn't ask to actually
   5254                         // extend itself into the overscan region.
   5255                         of.set(displayFrames.mUnrestricted);
   5256                     } else {
   5257                         df.set(displayFrames.mRestrictedOverscan);
   5258                         pf.set(displayFrames.mRestrictedOverscan);
   5259                         // We need to tell the app about where the frame inside the overscan
   5260                         // is, so it can inset its content by that amount -- it didn't ask
   5261                         // to actually extend itself into the overscan region.
   5262                         of.set(displayFrames.mUnrestricted);
   5263                     }
   5264 
   5265                     if ((fl & FLAG_FULLSCREEN) == 0) {
   5266                         if (win.isVoiceInteraction()) {
   5267                             cf.set(displayFrames.mVoiceContent);
   5268                         } else {
   5269                             if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
   5270                                 cf.set(displayFrames.mDock);
   5271                             } else {
   5272                                 cf.set(displayFrames.mContent);
   5273                             }
   5274                         }
   5275                     } else {
   5276                         // Full screen windows are always given a layout that is as if the status
   5277                         // bar and other transient decors are gone. This is to avoid bad states when
   5278                         // moving from a window that is not hiding the status bar to one that is.
   5279                         cf.set(displayFrames.mRestricted);
   5280                     }
   5281                     applyStableConstraints(sysUiFl, fl, cf, displayFrames);
   5282                     if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
   5283                         vf.set(displayFrames.mCurrent);
   5284                     } else {
   5285                         vf.set(cf);
   5286                     }
   5287                 }
   5288             } else if (layoutInScreen || (sysUiFl
   5289                     & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
   5290                             | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
   5291                 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
   5292                         + "): IN_SCREEN");
   5293                 // A window that has requested to fill the entire screen just
   5294                 // gets everything, period.
   5295                 if (type == TYPE_STATUS_BAR_PANEL || type == TYPE_STATUS_BAR_SUB_PANEL) {
   5296                     cf.set(displayFrames.mUnrestricted);
   5297                     of.set(displayFrames.mUnrestricted);
   5298                     df.set(displayFrames.mUnrestricted);
   5299                     pf.set(displayFrames.mUnrestricted);
   5300                     if (hasNavBar) {
   5301                         pf.left = df.left = of.left = cf.left = displayFrames.mDock.left;
   5302                         pf.right = df.right = of.right = cf.right = displayFrames.mRestricted.right;
   5303                         pf.bottom = df.bottom = of.bottom = cf.bottom =
   5304                                 displayFrames.mRestricted.bottom;
   5305                     }
   5306                     if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
   5307                             "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
   5308                             pf.left, pf.top, pf.right, pf.bottom));
   5309                 } else if (type == TYPE_NAVIGATION_BAR || type == TYPE_NAVIGATION_BAR_PANEL) {
   5310                     // The navigation bar has Real Ultimate Power.
   5311                     of.set(displayFrames.mUnrestricted);
   5312                     df.set(displayFrames.mUnrestricted);
   5313                     pf.set(displayFrames.mUnrestricted);
   5314                     if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
   5315                                     "Laying out navigation bar window: (%d,%d - %d,%d)",
   5316                                     pf.left, pf.top, pf.right, pf.bottom));
   5317                 } else if ((type == TYPE_SECURE_SYSTEM_OVERLAY || type == TYPE_SCREENSHOT)
   5318                         && ((fl & FLAG_FULLSCREEN) != 0)) {
   5319                     // Fullscreen secure system overlays get what they ask for. Screenshot region
   5320                     // selection overlay should also expand to full screen.
   5321                     cf.set(displayFrames.mOverscan);
   5322                     of.set(displayFrames.mOverscan);
   5323                     df.set(displayFrames.mOverscan);
   5324                     pf.set(displayFrames.mOverscan);
   5325                 } else if (type == TYPE_BOOT_PROGRESS) {
   5326                     // Boot progress screen always covers entire display.
   5327                     cf.set(displayFrames.mOverscan);
   5328                     of.set(displayFrames.mOverscan);
   5329                     df.set(displayFrames.mOverscan);
   5330                     pf.set(displayFrames.mOverscan);
   5331                 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
   5332                         && type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW) {
   5333                     // Asking to layout into the overscan region, so give it that pure unrestricted
   5334                     // area.
   5335                     cf.set(displayFrames.mOverscan);
   5336                     of.set(displayFrames.mOverscan);
   5337                     df.set(displayFrames.mOverscan);
   5338                     pf.set(displayFrames.mOverscan);
   5339                 } else if (canHideNavigationBar()
   5340                         && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
   5341                         && (type == TYPE_STATUS_BAR
   5342                             || type == TYPE_TOAST
   5343                             || type == TYPE_DOCK_DIVIDER
   5344                             || type == TYPE_VOICE_INTERACTION_STARTING
   5345                             || (type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW))) {
   5346                     // Asking for layout as if the nav bar is hidden, lets the
   5347                     // application extend into the unrestricted screen area.  We
   5348                     // only do this for application windows (or toasts) to ensure no window that
   5349                     // can be above the nav bar can do this.
   5350                     // XXX This assumes that an app asking for this will also
   5351                     // ask for layout in only content.  We can't currently figure out
   5352                     // what the screen would be if only laying out to hide the nav bar.
   5353                     cf.set(displayFrames.mUnrestricted);
   5354                     of.set(displayFrames.mUnrestricted);
   5355                     df.set(displayFrames.mUnrestricted);
   5356                     pf.set(displayFrames.mUnrestricted);
   5357                 } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
   5358                     of.set(displayFrames.mRestricted);
   5359                     df.set(displayFrames.mRestricted);
   5360                     pf.set(displayFrames.mRestricted);
   5361                     if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
   5362                         cf.set(displayFrames.mDock);
   5363                     } else {
   5364                         cf.set(displayFrames.mContent);
   5365                     }
   5366                 } else {
   5367                     cf.set(displayFrames.mRestricted);
   5368                     of.set(displayFrames.mRestricted);
   5369                     df.set(displayFrames.mRestricted);
   5370                     pf.set(displayFrames.mRestricted);
   5371                 }
   5372 
   5373                 applyStableConstraints(sysUiFl, fl, cf,displayFrames);
   5374 
   5375                 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
   5376                     vf.set(displayFrames.mCurrent);
   5377                 } else {
   5378                     vf.set(cf);
   5379                 }
   5380             } else if (attached != null) {
   5381                 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
   5382                         + "): attached to " + attached);
   5383                 // A child window should be placed inside of the same visible
   5384                 // frame that its parent had.
   5385                 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf,
   5386                         displayFrames);
   5387             } else {
   5388                 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
   5389                         "): normal window");
   5390                 // Otherwise, a normal window must be placed inside the content
   5391                 // of all screen decorations.
   5392                 if (type == TYPE_STATUS_BAR_PANEL) {
   5393                     // Status bar panels can go on
   5394                     // top of the status bar. They are protected by the STATUS_BAR_SERVICE
   5395                     // permission, so they have the same privileges as the status bar itself.
   5396                     cf.set(displayFrames.mRestricted);
   5397                     of.set(displayFrames.mRestricted);
   5398                     df.set(displayFrames.mRestricted);
   5399                     pf.set(displayFrames.mRestricted);
   5400                 } else if (type == TYPE_TOAST || type == TYPE_SYSTEM_ALERT) {
   5401                     // These dialogs are stable to interim decor changes.
   5402                     cf.set(displayFrames.mStable);
   5403                     of.set(displayFrames.mStable);
   5404                     df.set(displayFrames.mStable);
   5405                     pf.set(displayFrames.mStable);
   5406                 } else {
   5407                     pf.set(displayFrames.mContent);
   5408                     if (win.isVoiceInteraction()) {
   5409                         cf.set(displayFrames.mVoiceContent);
   5410                         of.set(displayFrames.mVoiceContent);
   5411                         df.set(displayFrames.mVoiceContent);
   5412                     } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
   5413                         cf.set(displayFrames.mDock);
   5414                         of.set(displayFrames.mDock);
   5415                         df.set(displayFrames.mDock);
   5416                     } else {
   5417                         cf.set(displayFrames.mContent);
   5418                         of.set(displayFrames.mContent);
   5419                         df.set(displayFrames.mContent);
   5420                     }
   5421                     if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
   5422                         vf.set(displayFrames.mCurrent);
   5423                     } else {
   5424                         vf.set(cf);
   5425                     }
   5426                 }
   5427             }
   5428         }
   5429 
   5430         boolean parentFrameWasClippedByDisplayCutout = false;
   5431         final int cutoutMode = attrs.layoutInDisplayCutoutMode;
   5432         final boolean attachedInParent = attached != null && !layoutInScreen;
   5433         final boolean requestedHideNavigation =
   5434                 (requestedSysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
   5435 
   5436         // TYPE_BASE_APPLICATION windows are never considered floating here because they don't get
   5437         // cropped / shifted to the displayFrame in WindowState.
   5438         final boolean floatingInScreenWindow = !attrs.isFullscreen() && layoutInScreen
   5439                 && type != TYPE_BASE_APPLICATION;
   5440 
   5441         // Ensure that windows with a DEFAULT or NEVER display cutout mode are laid out in
   5442         // the cutout safe zone.
   5443         if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
   5444             final Rect displayCutoutSafeExceptMaybeBars = mTmpDisplayCutoutSafeExceptMaybeBarsRect;
   5445             displayCutoutSafeExceptMaybeBars.set(displayFrames.mDisplayCutoutSafe);
   5446             if (layoutInScreen && layoutInsetDecor && !requestedFullscreen
   5447                     && cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT) {
   5448                 // At the top we have the status bar, so apps that are
   5449                 // LAYOUT_IN_SCREEN | LAYOUT_INSET_DECOR but not FULLSCREEN
   5450                 // already expect that there's an inset there and we don't need to exclude
   5451                 // the window from that area.
   5452                 displayCutoutSafeExceptMaybeBars.top = Integer.MIN_VALUE;
   5453             }
   5454             if (layoutInScreen && layoutInsetDecor && !requestedHideNavigation
   5455                     && cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT) {
   5456                 // Same for the navigation bar.
   5457                 switch (mNavigationBarPosition) {
   5458                     case NAV_BAR_BOTTOM:
   5459                         displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
   5460                         break;
   5461                     case NAV_BAR_RIGHT:
   5462                         displayCutoutSafeExceptMaybeBars.right = Integer.MAX_VALUE;
   5463                         break;
   5464                     case NAV_BAR_LEFT:
   5465                         displayCutoutSafeExceptMaybeBars.left = Integer.MIN_VALUE;
   5466                         break;
   5467                 }
   5468             }
   5469             if (type == TYPE_INPUT_METHOD && mNavigationBarPosition == NAV_BAR_BOTTOM) {
   5470                 // The IME can always extend under the bottom cutout if the navbar is there.
   5471                 displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
   5472             }
   5473             // Windows that are attached to a parent and laid out in said parent already avoid
   5474             // the cutout according to that parent and don't need to be further constrained.
   5475             // Floating IN_SCREEN windows get what they ask for and lay out in the full screen.
   5476             // They will later be cropped or shifted using the displayFrame in WindowState,
   5477             // which prevents overlap with the DisplayCutout.
   5478             if (!attachedInParent && !floatingInScreenWindow) {
   5479                 mTmpRect.set(pf);
   5480                 pf.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
   5481                 parentFrameWasClippedByDisplayCutout |= !mTmpRect.equals(pf);
   5482             }
   5483             // Make sure that NO_LIMITS windows clipped to the display don't extend under the
   5484             // cutout.
   5485             df.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
   5486         }
   5487 
   5488         // Content should never appear in the cutout.
   5489         cf.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
   5490 
   5491         // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
   5492         // Also, we don't allow windows in multi-window mode to extend out of the screen.
   5493         if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && type != TYPE_SYSTEM_ERROR
   5494                 && !win.isInMultiWindowMode()) {
   5495             df.left = df.top = -10000;
   5496             df.right = df.bottom = 10000;
   5497             if (type != TYPE_WALLPAPER) {
   5498                 of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
   5499                 of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
   5500             }
   5501         }
   5502 
   5503         // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we
   5504         // need to provide information to the clients that want to pretend that you can draw there.
   5505         // We only want to apply outsets to certain types of windows. For example, we never want to
   5506         // apply the outsets to floating dialogs, because they wouldn't make sense there.
   5507         final boolean useOutsets = shouldUseOutsets(attrs, fl);
   5508         if (isDefaultDisplay && useOutsets) {
   5509             osf = mTmpOutsetFrame;
   5510             osf.set(cf.left, cf.top, cf.right, cf.bottom);
   5511             int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
   5512             if (outset > 0) {
   5513                 int rotation = displayFrames.mRotation;
   5514                 if (rotation == Surface.ROTATION_0) {
   5515                     osf.bottom += outset;
   5516                 } else if (rotation == Surface.ROTATION_90) {
   5517                     osf.right += outset;
   5518                 } else if (rotation == Surface.ROTATION_180) {
   5519                     osf.top -= outset;
   5520                 } else if (rotation == Surface.ROTATION_270) {
   5521                     osf.left -= outset;
   5522                 }
   5523                 if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset
   5524                         + " with rotation " + rotation + ", result: " + osf);
   5525             }
   5526         }
   5527 
   5528         if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
   5529                 + ": sim=#" + Integer.toHexString(sim)
   5530                 + " attach=" + attached + " type=" + type
   5531                 + String.format(" flags=0x%08x", fl)
   5532                 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
   5533                 + " of=" + of.toShortString()
   5534                 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
   5535                 + " dcf=" + dcf.toShortString()
   5536                 + " sf=" + sf.toShortString()
   5537                 + " osf=" + (osf == null ? "null" : osf.toShortString()));
   5538 
   5539         win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf, displayFrames.mDisplayCutout,
   5540                 parentFrameWasClippedByDisplayCutout);
   5541         // Dock windows carve out the bottom of the screen, so normal windows
   5542         // can't appear underneath them.
   5543         if (type == TYPE_INPUT_METHOD && win.isVisibleLw()
   5544                 && !win.getGivenInsetsPendingLw()) {
   5545             setLastInputMethodWindowLw(null, null);
   5546             offsetInputMethodWindowLw(win, displayFrames);
   5547         }
   5548         if (type == TYPE_VOICE_INTERACTION && win.isVisibleLw()
   5549                 && !win.getGivenInsetsPendingLw()) {
   5550             offsetVoiceInputWindowLw(win, displayFrames);
   5551         }
   5552     }
   5553 
   5554     private void layoutWallpaper(DisplayFrames displayFrames, Rect pf, Rect df, Rect of, Rect cf) {
   5555         // The wallpaper has Real Ultimate Power, but we want to tell it about the overscan area.
   5556         df.set(displayFrames.mOverscan);
   5557         pf.set(displayFrames.mOverscan);
   5558         cf.set(displayFrames.mUnrestricted);
   5559         of.set(displayFrames.mUnrestricted);
   5560     }
   5561 
   5562     private void offsetInputMethodWindowLw(WindowState win, DisplayFrames displayFrames) {
   5563         int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
   5564         top += win.getGivenContentInsetsLw().top;
   5565         displayFrames.mContent.bottom = Math.min(displayFrames.mContent.bottom, top);
   5566         displayFrames.mVoiceContent.bottom = Math.min(displayFrames.mVoiceContent.bottom, top);
   5567         top = win.getVisibleFrameLw().top;
   5568         top += win.getGivenVisibleInsetsLw().top;
   5569         displayFrames.mCurrent.bottom = Math.min(displayFrames.mCurrent.bottom, top);
   5570         if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
   5571                 + displayFrames.mDock.bottom + " mContentBottom="
   5572                 + displayFrames.mContent.bottom + " mCurBottom=" + displayFrames.mCurrent.bottom);
   5573     }
   5574 
   5575     private void offsetVoiceInputWindowLw(WindowState win, DisplayFrames displayFrames) {
   5576         int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
   5577         top += win.getGivenContentInsetsLw().top;
   5578         displayFrames.mVoiceContent.bottom = Math.min(displayFrames.mVoiceContent.bottom, top);
   5579     }
   5580 
   5581     /** {@inheritDoc} */
   5582     @Override
   5583     public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
   5584         mTopFullscreenOpaqueWindowState = null;
   5585         mTopFullscreenOpaqueOrDimmingWindowState = null;
   5586         mTopDockedOpaqueWindowState = null;
   5587         mTopDockedOpaqueOrDimmingWindowState = null;
   5588         mForceStatusBar = false;
   5589         mForceStatusBarFromKeyguard = false;
   5590         mForceStatusBarTransparent = false;
   5591         mForcingShowNavBar = false;
   5592         mForcingShowNavBarLayer = -1;
   5593 
   5594         mAllowLockscreenWhenOn = false;
   5595         mShowingDream = false;
   5596         mWindowSleepTokenNeeded = false;
   5597     }
   5598 
   5599     /** {@inheritDoc} */
   5600     @Override
   5601     public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
   5602             WindowState attached, WindowState imeTarget) {
   5603         final boolean affectsSystemUi = win.canAffectSystemUiFlags();
   5604         if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": affectsSystemUi=" + affectsSystemUi);
   5605         applyKeyguardPolicyLw(win, imeTarget);
   5606         final int fl = PolicyControl.getWindowFlags(win, attrs);
   5607         if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi
   5608                 && attrs.type == TYPE_INPUT_METHOD) {
   5609             mForcingShowNavBar = true;
   5610             mForcingShowNavBarLayer = win.getSurfaceLayer();
   5611         }
   5612         if (attrs.type == TYPE_STATUS_BAR) {
   5613             if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
   5614                 mForceStatusBarFromKeyguard = true;
   5615             }
   5616             if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
   5617                 mForceStatusBarTransparent = true;
   5618             }
   5619         }
   5620 
   5621         boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
   5622                 && attrs.type < FIRST_SYSTEM_WINDOW;
   5623         final int windowingMode = win.getWindowingMode();
   5624         final boolean inFullScreenOrSplitScreenSecondaryWindowingMode =
   5625                 windowingMode == WINDOWING_MODE_FULLSCREEN
   5626                         || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
   5627         if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi) {
   5628             if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
   5629                 mForceStatusBar = true;
   5630             }
   5631             if (attrs.type == TYPE_DREAM) {
   5632                 // If the lockscreen was showing when the dream started then wait
   5633                 // for the dream to draw before hiding the lockscreen.
   5634                 if (!mDreamingLockscreen
   5635                         || (win.isVisibleLw() && win.hasDrawnLw())) {
   5636                     mShowingDream = true;
   5637                     appWindow = true;
   5638                 }
   5639             }
   5640 
   5641             // For app windows that are not attached, we decide if all windows in the app they
   5642             // represent should be hidden or if we should hide the lockscreen. For attached app
   5643             // windows we defer the decision to the window it is attached to.
   5644             if (appWindow && attached == null) {
   5645                 if (attrs.isFullscreen() && inFullScreenOrSplitScreenSecondaryWindowingMode) {
   5646                     if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
   5647                     mTopFullscreenOpaqueWindowState = win;
   5648                     if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
   5649                         mTopFullscreenOpaqueOrDimmingWindowState = win;
   5650                     }
   5651                     if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
   5652                         mAllowLockscreenWhenOn = true;
   5653                     }
   5654                 }
   5655             }
   5656         }
   5657 
   5658         // Voice interaction overrides both top fullscreen and top docked.
   5659         if (affectsSystemUi && win.getAttrs().type == TYPE_VOICE_INTERACTION) {
   5660             if (mTopFullscreenOpaqueWindowState == null) {
   5661                 mTopFullscreenOpaqueWindowState = win;
   5662                 if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
   5663                     mTopFullscreenOpaqueOrDimmingWindowState = win;
   5664                 }
   5665             }
   5666             if (mTopDockedOpaqueWindowState == null) {
   5667                 mTopDockedOpaqueWindowState = win;
   5668                 if (mTopDockedOpaqueOrDimmingWindowState == null) {
   5669                     mTopDockedOpaqueOrDimmingWindowState = win;
   5670                 }
   5671             }
   5672         }
   5673 
   5674         // Keep track of the window if it's dimming but not necessarily fullscreen.
   5675         if (mTopFullscreenOpaqueOrDimmingWindowState == null && affectsSystemUi
   5676                 && win.isDimming() && inFullScreenOrSplitScreenSecondaryWindowingMode) {
   5677             mTopFullscreenOpaqueOrDimmingWindowState = win;
   5678         }
   5679 
   5680         // We need to keep track of the top "fullscreen" opaque window for the docked stack
   5681         // separately, because both the "real fullscreen" opaque window and the one for the docked
   5682         // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
   5683         if (mTopDockedOpaqueWindowState == null && affectsSystemUi && appWindow && attached == null
   5684                 && attrs.isFullscreen() && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
   5685             mTopDockedOpaqueWindowState = win;
   5686             if (mTopDockedOpaqueOrDimmingWindowState == null) {
   5687                 mTopDockedOpaqueOrDimmingWindowState = win;
   5688             }
   5689         }
   5690 
   5691         // Also keep track of any windows that are dimming but not necessarily fullscreen in the
   5692         // docked stack.
   5693         if (mTopDockedOpaqueOrDimmingWindowState == null && affectsSystemUi && win.isDimming()
   5694                 && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
   5695             mTopDockedOpaqueOrDimmingWindowState = win;
   5696         }
   5697 
   5698         // Take note if a window wants to acquire a sleep token.
   5699         if (win.isVisibleLw() && (attrs.privateFlags & PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN) != 0
   5700                 && win.canAcquireSleepToken()) {
   5701             mWindowSleepTokenNeeded = true;
   5702         }
   5703     }
   5704 
   5705     private void applyKeyguardPolicyLw(WindowState win, WindowState imeTarget) {
   5706         if (canBeHiddenByKeyguardLw(win)) {
   5707             if (shouldBeHiddenByKeyguard(win, imeTarget)) {
   5708                 win.hideLw(false /* doAnimation */);
   5709             } else {
   5710                 win.showLw(false /* doAnimation */);
   5711             }
   5712         }
   5713     }
   5714 
   5715     /** {@inheritDoc} */
   5716     @Override
   5717     public int finishPostLayoutPolicyLw() {
   5718         int changes = 0;
   5719         boolean topIsFullscreen = false;
   5720 
   5721         final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
   5722                 ? mTopFullscreenOpaqueWindowState.getAttrs()
   5723                 : null;
   5724 
   5725         // If we are not currently showing a dream then remember the current
   5726         // lockscreen state.  We will use this to determine whether the dream
   5727         // started while the lockscreen was showing and remember this state
   5728         // while the dream is showing.
   5729         if (!mShowingDream) {
   5730             mDreamingLockscreen = isKeyguardShowingAndNotOccluded();
   5731             if (mDreamingSleepTokenNeeded) {
   5732                 mDreamingSleepTokenNeeded = false;
   5733                 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
   5734             }
   5735         } else {
   5736             if (!mDreamingSleepTokenNeeded) {
   5737                 mDreamingSleepTokenNeeded = true;
   5738                 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget();
   5739             }
   5740         }
   5741 
   5742         if (mStatusBar != null) {
   5743             if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
   5744                     + " forcefkg=" + mForceStatusBarFromKeyguard
   5745                     + " top=" + mTopFullscreenOpaqueWindowState);
   5746             boolean shouldBeTransparent = mForceStatusBarTransparent
   5747                     && !mForceStatusBar
   5748                     && !mForceStatusBarFromKeyguard;
   5749             if (!shouldBeTransparent) {
   5750                 mStatusBarController.setShowTransparent(false /* transparent */);
   5751             } else if (!mStatusBar.isVisibleLw()) {
   5752                 mStatusBarController.setShowTransparent(true /* transparent */);
   5753             }
   5754 
   5755             WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs();
   5756             boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT
   5757                     && statusBarAttrs.width == MATCH_PARENT;
   5758             boolean topAppHidesStatusBar = topAppHidesStatusBar();
   5759             if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
   5760                     || statusBarExpanded) {
   5761                 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
   5762                 if (mStatusBarController.setBarShowingLw(true)) {
   5763                     changes |= FINISH_LAYOUT_REDO_LAYOUT;
   5764                 }
   5765                 // Maintain fullscreen layout until incoming animation is complete.
   5766                 topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
   5767                 // Transient status bar on the lockscreen is not allowed
   5768                 if ((mForceStatusBarFromKeyguard || statusBarExpanded)
   5769                         && mStatusBarController.isTransientShowing()) {
   5770                     mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
   5771                             mLastSystemUiFlags, mLastSystemUiFlags);
   5772                 }
   5773             } else if (mTopFullscreenOpaqueWindowState != null) {
   5774                 topIsFullscreen = topAppHidesStatusBar;
   5775                 // The subtle difference between the window for mTopFullscreenOpaqueWindowState
   5776                 // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
   5777                 // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
   5778                 // case though.
   5779                 if (mStatusBarController.isTransientShowing()) {
   5780                     if (mStatusBarController.setBarShowingLw(true)) {
   5781                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
   5782                     }
   5783                 } else if (topIsFullscreen
   5784                         && !mWindowManagerInternal.isStackVisible(WINDOWING_MODE_FREEFORM)
   5785                         && !mWindowManagerInternal.isStackVisible(
   5786                                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
   5787                     if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
   5788                     if (mStatusBarController.setBarShowingLw(false)) {
   5789                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
   5790                     } else {
   5791                         if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
   5792                     }
   5793                 } else {
   5794                     if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
   5795                     if (mStatusBarController.setBarShowingLw(true)) {
   5796                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
   5797                     }
   5798                     topAppHidesStatusBar = false;
   5799                 }
   5800             }
   5801             mStatusBarController.setTopAppHidesStatusBar(topAppHidesStatusBar);
   5802         }
   5803 
   5804         if (mTopIsFullscreen != topIsFullscreen) {
   5805             if (!topIsFullscreen) {
   5806                 // Force another layout when status bar becomes fully shown.
   5807                 changes |= FINISH_LAYOUT_REDO_LAYOUT;
   5808             }
   5809             mTopIsFullscreen = topIsFullscreen;
   5810         }
   5811 
   5812         if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
   5813             // If the navigation bar has been hidden or shown, we need to do another
   5814             // layout pass to update that window.
   5815             changes |= FINISH_LAYOUT_REDO_LAYOUT;
   5816         }
   5817 
   5818         if (mShowingDream != mLastShowingDream) {
   5819             mLastShowingDream = mShowingDream;
   5820             mWindowManagerFuncs.notifyShowingDreamChanged();
   5821         }
   5822 
   5823         updateWindowSleepToken();
   5824 
   5825         // update since mAllowLockscreenWhenOn might have changed
   5826         updateLockScreenTimeout();
   5827         return changes;
   5828     }
   5829 
   5830     private void updateWindowSleepToken() {
   5831         if (mWindowSleepTokenNeeded && !mLastWindowSleepTokenNeeded) {
   5832             mHandler.removeCallbacks(mReleaseSleepTokenRunnable);
   5833             mHandler.post(mAcquireSleepTokenRunnable);
   5834         } else if (!mWindowSleepTokenNeeded && mLastWindowSleepTokenNeeded) {
   5835             mHandler.removeCallbacks(mAcquireSleepTokenRunnable);
   5836             mHandler.post(mReleaseSleepTokenRunnable);
   5837         }
   5838         mLastWindowSleepTokenNeeded = mWindowSleepTokenNeeded;
   5839     }
   5840 
   5841     /**
   5842      * @return Whether the top app should hide the statusbar based on the top fullscreen opaque
   5843      *         window.
   5844      */
   5845     private boolean topAppHidesStatusBar() {
   5846         if (mTopFullscreenOpaqueWindowState == null) {
   5847             return false;
   5848         }
   5849         final int fl = PolicyControl.getWindowFlags(null,
   5850                 mTopFullscreenOpaqueWindowState.getAttrs());
   5851         if (localLOGV) {
   5852             Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw());
   5853             Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
   5854                     + " lp.flags=0x" + Integer.toHexString(fl));
   5855         }
   5856         return (fl & LayoutParams.FLAG_FULLSCREEN) != 0
   5857                 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
   5858     }
   5859 
   5860     /**
   5861      * Updates the occluded state of the Keyguard.
   5862      *
   5863      * @return Whether the flags have changed and we have to redo the layout.
   5864      */
   5865     private boolean setKeyguardOccludedLw(boolean isOccluded, boolean force) {
   5866         if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded);
   5867         final boolean wasOccluded = mKeyguardOccluded;
   5868         final boolean showing = mKeyguardDelegate.isShowing();
   5869         final boolean changed = wasOccluded != isOccluded || force;
   5870         if (!isOccluded && changed && showing) {
   5871             mKeyguardOccluded = false;
   5872             mKeyguardDelegate.setOccluded(false, true /* animate */);
   5873             if (mStatusBar != null) {
   5874                 mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
   5875                 if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
   5876                     mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
   5877                 }
   5878             }
   5879             return true;
   5880         } else if (isOccluded && changed && showing) {
   5881             mKeyguardOccluded = true;
   5882             mKeyguardDelegate.setOccluded(true, false /* animate */);
   5883             if (mStatusBar != null) {
   5884                 mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
   5885                 mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
   5886             }
   5887             return true;
   5888         } else if (changed) {
   5889             mKeyguardOccluded = isOccluded;
   5890             mKeyguardDelegate.setOccluded(isOccluded, false /* animate */);
   5891             return false;
   5892         } else {
   5893             return false;
   5894         }
   5895     }
   5896 
   5897     private boolean isStatusBarKeyguard() {
   5898         return mStatusBar != null
   5899                 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
   5900     }
   5901 
   5902     @Override
   5903     public boolean allowAppAnimationsLw() {
   5904         return !mShowingDream;
   5905     }
   5906 
   5907     @Override
   5908     public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
   5909         mFocusedWindow = newFocus;
   5910         if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
   5911             // If the navigation bar has been hidden or shown, we need to do another
   5912             // layout pass to update that window.
   5913             return FINISH_LAYOUT_REDO_LAYOUT;
   5914         }
   5915         return 0;
   5916     }
   5917 
   5918     /** {@inheritDoc} */
   5919     @Override
   5920     public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
   5921         // lid changed state
   5922         final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
   5923         if (newLidState == mLidState) {
   5924             return;
   5925         }
   5926 
   5927         mLidState = newLidState;
   5928         applyLidSwitchState();
   5929         updateRotation(true);
   5930 
   5931         if (lidOpen) {
   5932             wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
   5933                     "android.policy:LID");
   5934         } else if (!mLidControlsSleep) {
   5935             mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
   5936         }
   5937     }
   5938 
   5939     @Override
   5940     public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
   5941         int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
   5942         if (mCameraLensCoverState == lensCoverState) {
   5943             return;
   5944         }
   5945         if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
   5946                 lensCoverState == CAMERA_LENS_UNCOVERED) {
   5947             Intent intent;
   5948             final boolean keyguardActive = mKeyguardDelegate == null ? false :
   5949                     mKeyguardDelegate.isShowing();
   5950             if (keyguardActive) {
   5951                 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
   5952             } else {
   5953                 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
   5954             }
   5955             wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
   5956                     "android.policy:CAMERA_COVER");
   5957             startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
   5958         }
   5959         mCameraLensCoverState = lensCoverState;
   5960     }
   5961 
   5962     void setHdmiPlugged(boolean plugged) {
   5963         if (mHdmiPlugged != plugged) {
   5964             mHdmiPlugged = plugged;
   5965             updateRotation(true, true);
   5966             Intent intent = new Intent(ACTION_HDMI_PLUGGED);
   5967             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
   5968             intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
   5969             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
   5970         }
   5971     }
   5972 
   5973     void initializeHdmiState() {
   5974         final int oldMask = StrictMode.allowThreadDiskReadsMask();
   5975         try {
   5976             initializeHdmiStateInternal();
   5977         } finally {
   5978             StrictMode.setThreadPolicyMask(oldMask);
   5979         }
   5980     }
   5981 
   5982     void initializeHdmiStateInternal() {
   5983         boolean plugged = false;
   5984         // watch for HDMI plug messages if the hdmi switch exists
   5985         if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
   5986             mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
   5987 
   5988             final String filename = "/sys/class/switch/hdmi/state";
   5989             FileReader reader = null;
   5990             try {
   5991                 reader = new FileReader(filename);
   5992                 char[] buf = new char[15];
   5993                 int n = reader.read(buf);
   5994                 if (n > 1) {
   5995                     plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
   5996                 }
   5997             } catch (IOException ex) {
   5998                 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
   5999             } catch (NumberFormatException ex) {
   6000                 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
   6001             } finally {
   6002                 if (reader != null) {
   6003                     try {
   6004                         reader.close();
   6005                     } catch (IOException ex) {
   6006                     }
   6007                 }
   6008             }
   6009         }
   6010         // This dance forces the code in setHdmiPlugged to run.
   6011         // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
   6012         mHdmiPlugged = !plugged;
   6013         setHdmiPlugged(!mHdmiPlugged);
   6014     }
   6015 
   6016 
   6017     /** {@inheritDoc} */
   6018     @Override
   6019     public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
   6020         if (!mSystemBooted) {
   6021             // If we have not yet booted, don't let key events do anything.
   6022             return 0;
   6023         }
   6024 
   6025         final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
   6026         final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
   6027         final boolean canceled = event.isCanceled();
   6028         final int keyCode = event.getKeyCode();
   6029 
   6030         final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
   6031 
   6032         // If screen is off then we treat the case where the keyguard is open but hidden
   6033         // the same as if it were open and in front.
   6034         // This will prevent any keys other than the power button from waking the screen
   6035         // when the keyguard is hidden by another activity.
   6036         final boolean keyguardActive = (mKeyguardDelegate == null ? false :
   6037                                             (interactive ?
   6038                                                 isKeyguardShowingAndNotOccluded() :
   6039                                                 mKeyguardDelegate.isShowing()));
   6040 
   6041         if (DEBUG_INPUT) {
   6042             Log.d(TAG, "interceptKeyTq keycode=" + keyCode
   6043                     + " interactive=" + interactive + " keyguardActive=" + keyguardActive
   6044                     + " policyFlags=" + Integer.toHexString(policyFlags));
   6045         }
   6046 
   6047         // Basic policy based on interactive state.
   6048         int result;
   6049         boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
   6050                 || event.isWakeKey();
   6051         if (interactive || (isInjected && !isWakeKey)) {
   6052             // When the device is interactive or the key is injected pass the
   6053             // key to the application.
   6054             result = ACTION_PASS_TO_USER;
   6055             isWakeKey = false;
   6056 
   6057             if (interactive) {
   6058                 // If the screen is awake, but the button pressed was the one that woke the device
   6059                 // then don't pass it to the application
   6060                 if (keyCode == mPendingWakeKey && !down) {
   6061                     result = 0;
   6062                 }
   6063                 // Reset the pending key
   6064                 mPendingWakeKey = PENDING_KEY_NULL;
   6065             }
   6066         } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
   6067             // If we're currently dozing with the screen on and the keyguard showing, pass the key
   6068             // to the application but preserve its wake key status to make sure we still move
   6069             // from dozing to fully interactive if we would normally go from off to fully
   6070             // interactive.
   6071             result = ACTION_PASS_TO_USER;
   6072             // Since we're dispatching the input, reset the pending key
   6073             mPendingWakeKey = PENDING_KEY_NULL;
   6074         } else {
   6075             // When the screen is off and the key is not injected, determine whether
   6076             // to wake the device but don't pass the key to the application.
   6077             result = 0;
   6078             if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
   6079                 isWakeKey = false;
   6080             }
   6081             // Cache the wake key on down event so we can also avoid sending the up event to the app
   6082             if (isWakeKey && down) {
   6083                 mPendingWakeKey = keyCode;
   6084             }
   6085         }
   6086 
   6087         // If the key would be handled globally, just return the result, don't worry about special
   6088         // key processing.
   6089         if (isValidGlobalKey(keyCode)
   6090                 && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
   6091             if (isWakeKey) {
   6092                 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
   6093             }
   6094             return result;
   6095         }
   6096 
   6097         // Enable haptics if down and virtual key without multiple repetitions. If this is a hard
   6098         // virtual key such as a navigation bar button, only vibrate if flag is enabled.
   6099         final boolean isNavBarVirtKey = ((event.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) != 0);
   6100         boolean useHapticFeedback = down
   6101                 && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
   6102                 && (!isNavBarVirtKey || mNavBarVirtualKeyHapticFeedbackEnabled)
   6103                 && event.getRepeatCount() == 0;
   6104 
   6105         // Handle special keys.
   6106         switch (keyCode) {
   6107             case KeyEvent.KEYCODE_BACK: {
   6108                 if (down) {
   6109                     interceptBackKeyDown();
   6110                 } else {
   6111                     boolean handled = interceptBackKeyUp(event);
   6112 
   6113                     // Don't pass back press to app if we've already handled it via long press
   6114                     if (handled) {
   6115                         result &= ~ACTION_PASS_TO_USER;
   6116                     }
   6117                 }
   6118                 break;
   6119             }
   6120 
   6121             case KeyEvent.KEYCODE_VOLUME_DOWN:
   6122             case KeyEvent.KEYCODE_VOLUME_UP:
   6123             case KeyEvent.KEYCODE_VOLUME_MUTE: {
   6124                 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
   6125                     if (down) {
   6126                         // Any activity on the vol down button stops the ringer toggle shortcut
   6127                         cancelPendingRingerToggleChordAction();
   6128 
   6129                         if (interactive && !mScreenshotChordVolumeDownKeyTriggered
   6130                                 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
   6131                             mScreenshotChordVolumeDownKeyTriggered = true;
   6132                             mScreenshotChordVolumeDownKeyTime = event.getDownTime();
   6133                             mScreenshotChordVolumeDownKeyConsumed = false;
   6134                             cancelPendingPowerKeyAction();
   6135                             interceptScreenshotChord();
   6136                             interceptAccessibilityShortcutChord();
   6137                         }
   6138                     } else {
   6139                         mScreenshotChordVolumeDownKeyTriggered = false;
   6140                         cancelPendingScreenshotChordAction();
   6141                         cancelPendingAccessibilityShortcutAction();
   6142                     }
   6143                 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
   6144                     if (down) {
   6145                         if (interactive && !mA11yShortcutChordVolumeUpKeyTriggered
   6146                                 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
   6147                             mA11yShortcutChordVolumeUpKeyTriggered = true;
   6148                             mA11yShortcutChordVolumeUpKeyTime = event.getDownTime();
   6149                             mA11yShortcutChordVolumeUpKeyConsumed = false;
   6150                             cancelPendingPowerKeyAction();
   6151                             cancelPendingScreenshotChordAction();
   6152                             cancelPendingRingerToggleChordAction();
   6153 
   6154                             interceptAccessibilityShortcutChord();
   6155                             interceptRingerToggleChord();
   6156                         }
   6157                     } else {
   6158                         mA11yShortcutChordVolumeUpKeyTriggered = false;
   6159                         cancelPendingScreenshotChordAction();
   6160                         cancelPendingAccessibilityShortcutAction();
   6161                         cancelPendingRingerToggleChordAction();
   6162                     }
   6163                 }
   6164                 if (down) {
   6165                     sendSystemKeyToStatusBarAsync(event.getKeyCode());
   6166 
   6167                     TelecomManager telecomManager = getTelecommService();
   6168                     if (telecomManager != null && !mHandleVolumeKeysInWM) {
   6169                         // When {@link #mHandleVolumeKeysInWM} is set, volume key events
   6170                         // should be dispatched to WM.
   6171                         if (telecomManager.isRinging()) {
   6172                             // If an incoming call is ringing, either VOLUME key means
   6173                             // "silence ringer".  We handle these keys here, rather than
   6174                             // in the InCallScreen, to make sure we'll respond to them
   6175                             // even if the InCallScreen hasn't come to the foreground yet.
   6176                             // Look for the DOWN event here, to agree with the "fallback"
   6177                             // behavior in the InCallScreen.
   6178                             Log.i(TAG, "interceptKeyBeforeQueueing:"
   6179                                   + " VOLUME key-down while ringing: Silence ringer!");
   6180 
   6181                             // Silence the ringer.  (It's safe to call this
   6182                             // even if the ringer has already been silenced.)
   6183                             telecomManager.silenceRinger();
   6184 
   6185                             // And *don't* pass this key thru to the current activity
   6186                             // (which is probably the InCallScreen.)
   6187                             result &= ~ACTION_PASS_TO_USER;
   6188                             break;
   6189                         }
   6190                     }
   6191                     int audioMode = AudioManager.MODE_NORMAL;
   6192                     try {
   6193                         audioMode = getAudioService().getMode();
   6194                     } catch (Exception e) {
   6195                         Log.e(TAG, "Error getting AudioService in interceptKeyBeforeQueueing.", e);
   6196                     }
   6197                     boolean isInCall = (telecomManager != null && telecomManager.isInCall()) ||
   6198                             audioMode == AudioManager.MODE_IN_COMMUNICATION;
   6199                     if (isInCall && (result & ACTION_PASS_TO_USER) == 0) {
   6200                         // If we are in call but we decided not to pass the key to
   6201                         // the application, just pass it to the session service.
   6202                         MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
   6203                                 event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
   6204                         break;
   6205                     }
   6206                 }
   6207                 if (mUseTvRouting || mHandleVolumeKeysInWM) {
   6208                     // Defer special key handlings to
   6209                     // {@link interceptKeyBeforeDispatching()}.
   6210                     result |= ACTION_PASS_TO_USER;
   6211                 } else if ((result & ACTION_PASS_TO_USER) == 0) {
   6212                     // If we aren't passing to the user and no one else
   6213                     // handled it send it to the session manager to
   6214                     // figure out.
   6215                     MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
   6216                             event, AudioManager.USE_DEFAULT_STREAM_TYPE, true);
   6217                 }
   6218                 break;
   6219             }
   6220 
   6221             case KeyEvent.KEYCODE_ENDCALL: {
   6222                 result &= ~ACTION_PASS_TO_USER;
   6223                 if (down) {
   6224                     TelecomManager telecomManager = getTelecommService();
   6225                     boolean hungUp = false;
   6226                     if (telecomManager != null) {
   6227                         hungUp = telecomManager.endCall();
   6228                     }
   6229                     if (interactive && !hungUp) {
   6230                         mEndCallKeyHandled = false;
   6231                         mHandler.postDelayed(mEndCallLongPress,
   6232                                 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
   6233                     } else {
   6234                         mEndCallKeyHandled = true;
   6235                     }
   6236                 } else {
   6237                     if (!mEndCallKeyHandled) {
   6238                         mHandler.removeCallbacks(mEndCallLongPress);
   6239                         if (!canceled) {
   6240                             if ((mEndcallBehavior
   6241                                     & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
   6242                                 if (goHome()) {
   6243                                     break;
   6244                                 }
   6245                             }
   6246                             if ((mEndcallBehavior
   6247                                     & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
   6248                                 goToSleep(event.getEventTime(),
   6249                                         PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
   6250                                 isWakeKey = false;
   6251                             }
   6252                         }
   6253                     }
   6254                 }
   6255                 break;
   6256             }
   6257 
   6258             case KeyEvent.KEYCODE_POWER: {
   6259                 // Any activity on the power button stops the accessibility shortcut
   6260                 cancelPendingAccessibilityShortcutAction();
   6261                 result &= ~ACTION_PASS_TO_USER;
   6262                 isWakeKey = false; // wake-up will be handled separately
   6263                 if (down) {
   6264                     interceptPowerKeyDown(event, interactive);
   6265                 } else {
   6266                     interceptPowerKeyUp(event, interactive, canceled);
   6267                 }
   6268                 break;
   6269             }
   6270 
   6271             case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
   6272                 // fall through
   6273             case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
   6274                 // fall through
   6275             case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
   6276                 // fall through
   6277             case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
   6278                 result &= ~ACTION_PASS_TO_USER;
   6279                 interceptSystemNavigationKey(event);
   6280                 break;
   6281             }
   6282 
   6283             case KeyEvent.KEYCODE_SLEEP: {
   6284                 result &= ~ACTION_PASS_TO_USER;
   6285                 isWakeKey = false;
   6286                 if (!mPowerManager.isInteractive()) {
   6287                     useHapticFeedback = false; // suppress feedback if already non-interactive
   6288                 }
   6289                 if (down) {
   6290                     sleepPress();
   6291                 } else {
   6292                     sleepRelease(event.getEventTime());
   6293                 }
   6294                 break;
   6295             }
   6296 
   6297             case KeyEvent.KEYCODE_SOFT_SLEEP: {
   6298                 result &= ~ACTION_PASS_TO_USER;
   6299                 isWakeKey = false;
   6300                 if (!down) {
   6301                     mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
   6302                 }
   6303                 break;
   6304             }
   6305 
   6306             case KeyEvent.KEYCODE_WAKEUP: {
   6307                 result &= ~ACTION_PASS_TO_USER;
   6308                 isWakeKey = true;
   6309                 break;
   6310             }
   6311 
   6312             case KeyEvent.KEYCODE_MEDIA_PLAY:
   6313             case KeyEvent.KEYCODE_MEDIA_PAUSE:
   6314             case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
   6315             case KeyEvent.KEYCODE_HEADSETHOOK:
   6316             case KeyEvent.KEYCODE_MUTE:
   6317             case KeyEvent.KEYCODE_MEDIA_STOP:
   6318             case KeyEvent.KEYCODE_MEDIA_NEXT:
   6319             case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
   6320             case KeyEvent.KEYCODE_MEDIA_REWIND:
   6321             case KeyEvent.KEYCODE_MEDIA_RECORD:
   6322             case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
   6323             case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
   6324                 if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
   6325                     // If the global session is active pass all media keys to it
   6326                     // instead of the active window.
   6327                     result &= ~ACTION_PASS_TO_USER;
   6328                 }
   6329                 if ((result & ACTION_PASS_TO_USER) == 0) {
   6330                     // Only do this if we would otherwise not pass it to the user. In that
   6331                     // case, the PhoneWindow class will do the same thing, except it will
   6332                     // only do it if the showing app doesn't process the key on its own.
   6333                     // Note that we need to make a copy of the key event here because the
   6334                     // original key event will be recycled when we return.
   6335                     mBroadcastWakeLock.acquire();
   6336                     Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
   6337                             new KeyEvent(event));
   6338                     msg.setAsynchronous(true);
   6339                     msg.sendToTarget();
   6340                 }
   6341                 break;
   6342             }
   6343 
   6344             case KeyEvent.KEYCODE_CALL: {
   6345                 if (down) {
   6346                     TelecomManager telecomManager = getTelecommService();
   6347                     if (telecomManager != null) {
   6348                         if (telecomManager.isRinging()) {
   6349                             Log.i(TAG, "interceptKeyBeforeQueueing:"
   6350                                   + " CALL key-down while ringing: Answer the call!");
   6351                             telecomManager.acceptRingingCall();
   6352 
   6353                             // And *don't* pass this key thru to the current activity
   6354                             // (which is presumably the InCallScreen.)
   6355                             result &= ~ACTION_PASS_TO_USER;
   6356                         }
   6357                     }
   6358                 }
   6359                 break;
   6360             }
   6361             case KeyEvent.KEYCODE_ASSIST: {
   6362                 final boolean longPressed = event.getRepeatCount() > 0;
   6363                 if (down && longPressed) {
   6364                     Message msg = mHandler.obtainMessage(MSG_LAUNCH_ASSIST_LONG_PRESS);
   6365                     msg.setAsynchronous(true);
   6366                     msg.sendToTarget();
   6367                 }
   6368                 if (!down && !longPressed) {
   6369                     Message msg = mHandler.obtainMessage(MSG_LAUNCH_ASSIST, event.getDeviceId(),
   6370                             0 /* unused */, null /* hint */);
   6371                     msg.setAsynchronous(true);
   6372                     msg.sendToTarget();
   6373                 }
   6374                 result &= ~ACTION_PASS_TO_USER;
   6375                 break;
   6376             }
   6377             case KeyEvent.KEYCODE_VOICE_ASSIST: {
   6378                 if (!down) {
   6379                     mBroadcastWakeLock.acquire();
   6380                     Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK);
   6381                     msg.setAsynchronous(true);
   6382                     msg.sendToTarget();
   6383                 }
   6384                 result &= ~ACTION_PASS_TO_USER;
   6385                 break;
   6386             }
   6387             case KeyEvent.KEYCODE_WINDOW: {
   6388                 if (mShortPressOnWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
   6389                     if (mPictureInPictureVisible) {
   6390                         // Consumes the key only if picture-in-picture is visible to show
   6391                         // picture-in-picture control menu. This gives a chance to the foreground
   6392                         // activity to customize PIP key behavior.
   6393                         if (!down) {
   6394                             showPictureInPictureMenu(event);
   6395                         }
   6396                         result &= ~ACTION_PASS_TO_USER;
   6397                     }
   6398                 }
   6399                 break;
   6400             }
   6401         }
   6402 
   6403         if (useHapticFeedback) {
   6404             performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
   6405         }
   6406 
   6407         if (isWakeKey) {
   6408             wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
   6409         }
   6410 
   6411         return result;
   6412     }
   6413 
   6414     /**
   6415      * Handle statusbar expansion events.
   6416      * @param event
   6417      */
   6418     private void interceptSystemNavigationKey(KeyEvent event) {
   6419         if (event.getAction() == KeyEvent.ACTION_UP) {
   6420             if (!mAccessibilityManager.isEnabled()
   6421                     || !mAccessibilityManager.sendFingerprintGesture(event.getKeyCode())) {
   6422                 if (mSystemNavigationKeysEnabled) {
   6423                     sendSystemKeyToStatusBarAsync(event.getKeyCode());
   6424                 }
   6425             }
   6426         }
   6427     }
   6428 
   6429     /**
   6430      * Notify the StatusBar that a system key was pressed.
   6431      */
   6432     private void sendSystemKeyToStatusBar(int keyCode) {
   6433         IStatusBarService statusBar = getStatusBarService();
   6434         if (statusBar != null) {
   6435             try {
   6436                 statusBar.handleSystemKey(keyCode);
   6437             } catch (RemoteException e) {
   6438                 // Oh well.
   6439             }
   6440         }
   6441     }
   6442 
   6443     /**
   6444      * Notify the StatusBar that a system key was pressed without blocking the current thread.
   6445      */
   6446     private void sendSystemKeyToStatusBarAsync(int keyCode) {
   6447         Message message = mHandler.obtainMessage(MSG_SYSTEM_KEY_PRESS, keyCode, 0);
   6448         message.setAsynchronous(true);
   6449         mHandler.sendMessage(message);
   6450     }
   6451 
   6452     /**
   6453      * Notify the StatusBar that system rotation suggestion has changed.
   6454      */
   6455     private void sendProposedRotationChangeToStatusBarInternal(int rotation, boolean isValid) {
   6456         StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
   6457         if (statusBar != null) {
   6458             statusBar.onProposedRotationChanged(rotation, isValid);
   6459         }
   6460     }
   6461 
   6462     /**
   6463      * Returns true if the key can have global actions attached to it.
   6464      * We reserve all power management keys for the system since they require
   6465      * very careful handling.
   6466      */
   6467     private static boolean isValidGlobalKey(int keyCode) {
   6468         switch (keyCode) {
   6469             case KeyEvent.KEYCODE_POWER:
   6470             case KeyEvent.KEYCODE_WAKEUP:
   6471             case KeyEvent.KEYCODE_SLEEP:
   6472                 return false;
   6473             default:
   6474                 return true;
   6475         }
   6476     }
   6477 
   6478     /**
   6479      * When the screen is off we ignore some keys that might otherwise typically
   6480      * be considered wake keys.  We filter them out here.
   6481      *
   6482      * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
   6483      * is always considered a wake key.
   6484      */
   6485     private boolean isWakeKeyWhenScreenOff(int keyCode) {
   6486         switch (keyCode) {
   6487             // ignore volume keys unless docked
   6488             case KeyEvent.KEYCODE_VOLUME_UP:
   6489             case KeyEvent.KEYCODE_VOLUME_DOWN:
   6490             case KeyEvent.KEYCODE_VOLUME_MUTE:
   6491                 return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
   6492 
   6493             // ignore media and camera keys
   6494             case KeyEvent.KEYCODE_MUTE:
   6495             case KeyEvent.KEYCODE_HEADSETHOOK:
   6496             case KeyEvent.KEYCODE_MEDIA_PLAY:
   6497             case KeyEvent.KEYCODE_MEDIA_PAUSE:
   6498             case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
   6499             case KeyEvent.KEYCODE_MEDIA_STOP:
   6500             case KeyEvent.KEYCODE_MEDIA_NEXT:
   6501             case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
   6502             case KeyEvent.KEYCODE_MEDIA_REWIND:
   6503             case KeyEvent.KEYCODE_MEDIA_RECORD:
   6504             case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
   6505             case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
   6506             case KeyEvent.KEYCODE_CAMERA:
   6507                 return false;
   6508         }
   6509         return true;
   6510     }
   6511 
   6512 
   6513     /** {@inheritDoc} */
   6514     @Override
   6515     public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
   6516         if ((policyFlags & FLAG_WAKE) != 0) {
   6517             if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
   6518                     "android.policy:MOTION")) {
   6519                 return 0;
   6520             }
   6521         }
   6522 
   6523         if (shouldDispatchInputWhenNonInteractive(null)) {
   6524             return ACTION_PASS_TO_USER;
   6525         }
   6526 
   6527         // If we have not passed the action up and we are in theater mode without dreaming,
   6528         // there will be no dream to intercept the touch and wake into ambient.  The device should
   6529         // wake up in this case.
   6530         if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
   6531             wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
   6532                     "android.policy:MOTION");
   6533         }
   6534 
   6535         return 0;
   6536     }
   6537 
   6538     private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
   6539         final boolean displayOff = (mDisplay == null || mDisplay.getState() == STATE_OFF);
   6540 
   6541         if (displayOff && !mHasFeatureWatch) {
   6542             return false;
   6543         }
   6544 
   6545         // Send events to keyguard while the screen is on and it's showing.
   6546         if (isKeyguardShowingAndNotOccluded() && !displayOff) {
   6547             return true;
   6548         }
   6549 
   6550         // Watches handle BACK specially
   6551         if (mHasFeatureWatch
   6552                 && event != null
   6553                 && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
   6554                         || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
   6555             return false;
   6556         }
   6557 
   6558         // Send events to a dozing dream even if the screen is off since the dream
   6559         // is in control of the state of the screen.
   6560         IDreamManager dreamManager = getDreamManager();
   6561 
   6562         try {
   6563             if (dreamManager != null && dreamManager.isDreaming()) {
   6564                 return true;
   6565             }
   6566         } catch (RemoteException e) {
   6567             Slog.e(TAG, "RemoteException when checking if dreaming", e);
   6568         }
   6569 
   6570         // Otherwise, consume events since the user can't see what is being
   6571         // interacted with.
   6572         return false;
   6573     }
   6574 
   6575     private void dispatchDirectAudioEvent(KeyEvent event) {
   6576         if (event.getAction() != KeyEvent.ACTION_DOWN) {
   6577             return;
   6578         }
   6579         int keyCode = event.getKeyCode();
   6580         int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
   6581                 | AudioManager.FLAG_FROM_KEY;
   6582         String pkgName = mContext.getOpPackageName();
   6583         switch (keyCode) {
   6584             case KeyEvent.KEYCODE_VOLUME_UP:
   6585                 try {
   6586                     getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
   6587                             AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
   6588                 } catch (Exception e) {
   6589                     Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
   6590                 }
   6591                 break;
   6592             case KeyEvent.KEYCODE_VOLUME_DOWN:
   6593                 try {
   6594                     getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
   6595                             AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
   6596                 } catch (Exception e) {
   6597                     Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
   6598                 }
   6599                 break;
   6600             case KeyEvent.KEYCODE_VOLUME_MUTE:
   6601                 try {
   6602                     if (event.getRepeatCount() == 0) {
   6603                         getAudioService().adjustSuggestedStreamVolume(
   6604                                 AudioManager.ADJUST_TOGGLE_MUTE,
   6605                                 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
   6606                     }
   6607                 } catch (Exception e) {
   6608                     Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
   6609                 }
   6610                 break;
   6611         }
   6612     }
   6613 
   6614     void dispatchMediaKeyWithWakeLock(KeyEvent event) {
   6615         if (DEBUG_INPUT) {
   6616             Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
   6617         }
   6618 
   6619         if (mHavePendingMediaKeyRepeatWithWakeLock) {
   6620             if (DEBUG_INPUT) {
   6621                 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
   6622             }
   6623 
   6624             mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
   6625             mHavePendingMediaKeyRepeatWithWakeLock = false;
   6626             mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
   6627         }
   6628 
   6629         dispatchMediaKeyWithWakeLockToAudioService(event);
   6630 
   6631         if (event.getAction() == KeyEvent.ACTION_DOWN
   6632                 && event.getRepeatCount() == 0) {
   6633             mHavePendingMediaKeyRepeatWithWakeLock = true;
   6634 
   6635             Message msg = mHandler.obtainMessage(
   6636                     MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
   6637             msg.setAsynchronous(true);
   6638             mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
   6639         } else {
   6640             mBroadcastWakeLock.release();
   6641         }
   6642     }
   6643 
   6644     void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
   6645         mHavePendingMediaKeyRepeatWithWakeLock = false;
   6646 
   6647         KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
   6648                 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
   6649         if (DEBUG_INPUT) {
   6650             Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
   6651         }
   6652 
   6653         dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
   6654         mBroadcastWakeLock.release();
   6655     }
   6656 
   6657     void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
   6658         if (mActivityManagerInternal.isSystemReady()) {
   6659             MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
   6660         }
   6661     }
   6662 
   6663     void launchVoiceAssistWithWakeLock() {
   6664         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
   6665 
   6666         final Intent voiceIntent;
   6667         if (!keyguardOn()) {
   6668             voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
   6669         } else {
   6670             IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
   6671                     ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
   6672             if (dic != null) {
   6673                 try {
   6674                     dic.exitIdle("voice-search");
   6675                 } catch (RemoteException e) {
   6676                 }
   6677             }
   6678             voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
   6679             voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
   6680         }
   6681         startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
   6682         mBroadcastWakeLock.release();
   6683     }
   6684 
   6685     BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
   6686         @Override
   6687         public void onReceive(Context context, Intent intent) {
   6688             if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
   6689                 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
   6690                         Intent.EXTRA_DOCK_STATE_UNDOCKED);
   6691             } else {
   6692                 try {
   6693                     IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
   6694                             ServiceManager.getService(Context.UI_MODE_SERVICE));
   6695                     mUiMode = uiModeService.getCurrentModeType();
   6696                 } catch (RemoteException e) {
   6697                 }
   6698             }
   6699             updateRotation(true);
   6700             synchronized (mLock) {
   6701                 updateOrientationListenerLp();
   6702             }
   6703         }
   6704     };
   6705 
   6706     BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
   6707         @Override
   6708         public void onReceive(Context context, Intent intent) {
   6709             if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
   6710                 if (mKeyguardDelegate != null) {
   6711                     mKeyguardDelegate.onDreamingStarted();
   6712                 }
   6713             } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
   6714                 if (mKeyguardDelegate != null) {
   6715                     mKeyguardDelegate.onDreamingStopped();
   6716                 }
   6717             }
   6718         }
   6719     };
   6720 
   6721     BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
   6722         @Override
   6723         public void onReceive(Context context, Intent intent) {
   6724             if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
   6725                 // tickle the settings observer: this first ensures that we're
   6726                 // observing the relevant settings for the newly-active user,
   6727                 // and then updates our own bookkeeping based on the now-
   6728                 // current user.
   6729                 mSettingsObserver.onChange(false);
   6730 
   6731                 // force a re-application of focused window sysui visibility.
   6732                 // the window may never have been shown for this user
   6733                 // e.g. the keyguard when going through the new-user setup flow
   6734                 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
   6735                     mLastSystemUiFlags = 0;
   6736                     updateSystemUiVisibilityLw();
   6737                 }
   6738             }
   6739         }
   6740     };
   6741 
   6742     private final Runnable mHiddenNavPanic = new Runnable() {
   6743         @Override
   6744         public void run() {
   6745             synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
   6746                 if (!isUserSetupComplete()) {
   6747                     // Swipe-up for navigation bar is disabled during setup
   6748                     return;
   6749                 }
   6750                 mPendingPanicGestureUptime = SystemClock.uptimeMillis();
   6751                 if (!isNavBarEmpty(mLastSystemUiFlags)) {
   6752                     mNavigationBarController.showTransient();
   6753                 }
   6754             }
   6755         }
   6756     };
   6757 
   6758     private void requestTransientBars(WindowState swipeTarget) {
   6759         synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
   6760             if (!isUserSetupComplete()) {
   6761                 // Swipe-up for navigation bar is disabled during setup
   6762                 return;
   6763             }
   6764             boolean sb = mStatusBarController.checkShowTransientBarLw();
   6765             boolean nb = mNavigationBarController.checkShowTransientBarLw()
   6766                     && !isNavBarEmpty(mLastSystemUiFlags);
   6767             if (sb || nb) {
   6768                 // Don't show status bar when swiping on already visible navigation bar
   6769                 if (!nb && swipeTarget == mNavigationBar) {
   6770                     if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
   6771                     return;
   6772                 }
   6773                 if (sb) mStatusBarController.showTransient();
   6774                 if (nb) mNavigationBarController.showTransient();
   6775                 mImmersiveModeConfirmation.confirmCurrentPrompt();
   6776                 updateSystemUiVisibilityLw();
   6777             }
   6778         }
   6779     }
   6780 
   6781     // Called on the PowerManager's Notifier thread.
   6782     @Override
   6783     public void startedGoingToSleep(int why) {
   6784         if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
   6785 
   6786         mGoingToSleep = true;
   6787         mRequestedOrGoingToSleep = true;
   6788 
   6789         if (mKeyguardDelegate != null) {
   6790             mKeyguardDelegate.onStartedGoingToSleep(why);
   6791         }
   6792     }
   6793 
   6794     // Called on the PowerManager's Notifier thread.
   6795     @Override
   6796     public void finishedGoingToSleep(int why) {
   6797         EventLog.writeEvent(70000, 0);
   6798         if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
   6799         MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
   6800 
   6801         mGoingToSleep = false;
   6802         mRequestedOrGoingToSleep = false;
   6803 
   6804         // We must get this work done here because the power manager will drop
   6805         // the wake lock and let the system suspend once this function returns.
   6806         synchronized (mLock) {
   6807             mAwake = false;
   6808             updateWakeGestureListenerLp();
   6809             updateOrientationListenerLp();
   6810             updateLockScreenTimeout();
   6811         }
   6812         if (mKeyguardDelegate != null) {
   6813             mKeyguardDelegate.onFinishedGoingToSleep(why,
   6814                     mCameraGestureTriggeredDuringGoingToSleep);
   6815         }
   6816         mCameraGestureTriggeredDuringGoingToSleep = false;
   6817     }
   6818 
   6819     // Called on the PowerManager's Notifier thread.
   6820     @Override
   6821     public void startedWakingUp() {
   6822         EventLog.writeEvent(70000, 1);
   6823         if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
   6824 
   6825         // Since goToSleep performs these functions synchronously, we must
   6826         // do the same here.  We cannot post this work to a handler because
   6827         // that might cause it to become reordered with respect to what
   6828         // may happen in a future call to goToSleep.
   6829         synchronized (mLock) {
   6830             mAwake = true;
   6831 
   6832             updateWakeGestureListenerLp();
   6833             updateOrientationListenerLp();
   6834             updateLockScreenTimeout();
   6835         }
   6836 
   6837         if (mKeyguardDelegate != null) {
   6838             mKeyguardDelegate.onStartedWakingUp();
   6839         }
   6840     }
   6841 
   6842     // Called on the PowerManager's Notifier thread.
   6843     @Override
   6844     public void finishedWakingUp() {
   6845         if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
   6846 
   6847         if (mKeyguardDelegate != null) {
   6848             mKeyguardDelegate.onFinishedWakingUp();
   6849         }
   6850     }
   6851 
   6852     private void wakeUpFromPowerKey(long eventTime) {
   6853         wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
   6854     }
   6855 
   6856     private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
   6857         final boolean theaterModeEnabled = isTheaterModeEnabled();
   6858         if (!wakeInTheaterMode && theaterModeEnabled) {
   6859             return false;
   6860         }
   6861 
   6862         if (theaterModeEnabled) {
   6863             Settings.Global.putInt(mContext.getContentResolver(),
   6864                     Settings.Global.THEATER_MODE_ON, 0);
   6865         }
   6866 
   6867         mPowerManager.wakeUp(wakeTime, reason);
   6868         return true;
   6869     }
   6870 
   6871     private void finishKeyguardDrawn() {
   6872         synchronized (mLock) {
   6873             if (!mScreenOnEarly || mKeyguardDrawComplete) {
   6874                 return; // We are not awake yet or we have already informed of this event.
   6875             }
   6876 
   6877             mKeyguardDrawComplete = true;
   6878             if (mKeyguardDelegate != null) {
   6879                 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
   6880             }
   6881             mWindowManagerDrawComplete = false;
   6882         }
   6883 
   6884         // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
   6885         // as well as enabling the orientation change logic/sensor.
   6886         mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
   6887                 WAITING_FOR_DRAWN_TIMEOUT);
   6888     }
   6889 
   6890     // Called on the DisplayManager's DisplayPowerController thread.
   6891     @Override
   6892     public void screenTurnedOff() {
   6893         if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
   6894 
   6895         updateScreenOffSleepToken(true);
   6896         synchronized (mLock) {
   6897             mScreenOnEarly = false;
   6898             mScreenOnFully = false;
   6899             mKeyguardDrawComplete = false;
   6900             mWindowManagerDrawComplete = false;
   6901             mScreenOnListener = null;
   6902             updateOrientationListenerLp();
   6903 
   6904             if (mKeyguardDelegate != null) {
   6905                 mKeyguardDelegate.onScreenTurnedOff();
   6906             }
   6907         }
   6908         reportScreenStateToVrManager(false);
   6909     }
   6910 
   6911     private long getKeyguardDrawnTimeout() {
   6912         final boolean bootCompleted =
   6913                 LocalServices.getService(SystemServiceManager.class).isBootCompleted();
   6914         // Set longer timeout if it has not booted yet to prevent showing empty window.
   6915         return bootCompleted ? 1000 : 5000;
   6916     }
   6917 
   6918     // Called on the DisplayManager's DisplayPowerController thread.
   6919     @Override
   6920     public void screenTurningOn(final ScreenOnListener screenOnListener) {
   6921         if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
   6922 
   6923         updateScreenOffSleepToken(false);
   6924         synchronized (mLock) {
   6925             mScreenOnEarly = true;
   6926             mScreenOnFully = false;
   6927             mKeyguardDrawComplete = false;
   6928             mWindowManagerDrawComplete = false;
   6929             mScreenOnListener = screenOnListener;
   6930 
   6931             if (mKeyguardDelegate != null && mKeyguardDelegate.hasKeyguard()) {
   6932                 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
   6933                 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT,
   6934                         getKeyguardDrawnTimeout());
   6935                 mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
   6936             } else {
   6937                 if (DEBUG_WAKEUP) Slog.d(TAG,
   6938                         "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
   6939                 finishKeyguardDrawn();
   6940             }
   6941         }
   6942     }
   6943 
   6944     // Called on the DisplayManager's DisplayPowerController thread.
   6945     @Override
   6946     public void screenTurnedOn() {
   6947         synchronized (mLock) {
   6948             if (mKeyguardDelegate != null) {
   6949                 mKeyguardDelegate.onScreenTurnedOn();
   6950             }
   6951         }
   6952         reportScreenStateToVrManager(true);
   6953     }
   6954 
   6955     @Override
   6956     public void screenTurningOff(ScreenOffListener screenOffListener) {
   6957         mWindowManagerFuncs.screenTurningOff(screenOffListener);
   6958         synchronized (mLock) {
   6959             if (mKeyguardDelegate != null) {
   6960                 mKeyguardDelegate.onScreenTurningOff();
   6961             }
   6962         }
   6963     }
   6964 
   6965     private void reportScreenStateToVrManager(boolean isScreenOn) {
   6966         if (mVrManagerInternal == null) {
   6967             return;
   6968         }
   6969         mVrManagerInternal.onScreenStateChanged(isScreenOn);
   6970     }
   6971 
   6972     private void finishWindowsDrawn() {
   6973         synchronized (mLock) {
   6974             if (!mScreenOnEarly || mWindowManagerDrawComplete) {
   6975                 return; // Screen is not turned on or we did already handle this case earlier.
   6976             }
   6977 
   6978             mWindowManagerDrawComplete = true;
   6979         }
   6980 
   6981         finishScreenTurningOn();
   6982     }
   6983 
   6984     private void finishScreenTurningOn() {
   6985         synchronized (mLock) {
   6986             // We have just finished drawing screen content. Since the orientation listener
   6987             // gets only installed when all windows are drawn, we try to install it again.
   6988             updateOrientationListenerLp();
   6989         }
   6990         final ScreenOnListener listener;
   6991         final boolean enableScreen;
   6992         synchronized (mLock) {
   6993             if (DEBUG_WAKEUP) Slog.d(TAG,
   6994                     "finishScreenTurningOn: mAwake=" + mAwake
   6995                             + ", mScreenOnEarly=" + mScreenOnEarly
   6996                             + ", mScreenOnFully=" + mScreenOnFully
   6997                             + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
   6998                             + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
   6999 
   7000             if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
   7001                     || (mAwake && !mKeyguardDrawComplete)) {
   7002                 return; // spurious or not ready yet
   7003             }
   7004 
   7005             if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
   7006             listener = mScreenOnListener;
   7007             mScreenOnListener = null;
   7008             mScreenOnFully = true;
   7009 
   7010             // Remember the first time we draw the keyguard so we know when we're done with
   7011             // the main part of booting and can enable the screen and hide boot messages.
   7012             if (!mKeyguardDrawnOnce && mAwake) {
   7013                 mKeyguardDrawnOnce = true;
   7014                 enableScreen = true;
   7015                 if (mBootMessageNeedsHiding) {
   7016                     mBootMessageNeedsHiding = false;
   7017                     hideBootMessages();
   7018                 }
   7019             } else {
   7020                 enableScreen = false;
   7021             }
   7022         }
   7023 
   7024         if (listener != null) {
   7025             listener.onScreenOn();
   7026         }
   7027 
   7028         if (enableScreen) {
   7029             try {
   7030                 mWindowManager.enableScreenIfNeeded();
   7031             } catch (RemoteException unhandled) {
   7032             }
   7033         }
   7034     }
   7035 
   7036     private void handleHideBootMessage() {
   7037         synchronized (mLock) {
   7038             if (!mKeyguardDrawnOnce) {
   7039                 mBootMessageNeedsHiding = true;
   7040                 return; // keyguard hasn't drawn the first time yet, not done booting
   7041             }
   7042         }
   7043 
   7044         if (mBootMsgDialog != null) {
   7045             if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
   7046             mBootMsgDialog.dismiss();
   7047             mBootMsgDialog = null;
   7048         }
   7049     }
   7050 
   7051     @Override
   7052     public boolean isScreenOn() {
   7053         synchronized (mLock) {
   7054             return mScreenOnEarly;
   7055         }
   7056     }
   7057 
   7058     @Override
   7059     public boolean okToAnimate() {
   7060         return mAwake && !mGoingToSleep;
   7061     }
   7062 
   7063     /** {@inheritDoc} */
   7064     @Override
   7065     public void enableKeyguard(boolean enabled) {
   7066         if (mKeyguardDelegate != null) {
   7067             mKeyguardDelegate.setKeyguardEnabled(enabled);
   7068         }
   7069     }
   7070 
   7071     /** {@inheritDoc} */
   7072     @Override
   7073     public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
   7074         if (mKeyguardDelegate != null) {
   7075             mKeyguardDelegate.verifyUnlock(callback);
   7076         }
   7077     }
   7078 
   7079     @Override
   7080     public boolean isKeyguardShowingAndNotOccluded() {
   7081         if (mKeyguardDelegate == null) return false;
   7082         return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
   7083     }
   7084 
   7085     @Override
   7086     public boolean isKeyguardTrustedLw() {
   7087         if (mKeyguardDelegate == null) return false;
   7088         return mKeyguardDelegate.isTrusted();
   7089     }
   7090 
   7091     /** {@inheritDoc} */
   7092     @Override
   7093     public boolean isKeyguardLocked() {
   7094         return keyguardOn();
   7095     }
   7096 
   7097     /** {@inheritDoc} */
   7098     @Override
   7099     public boolean isKeyguardSecure(int userId) {
   7100         if (mKeyguardDelegate == null) return false;
   7101         return mKeyguardDelegate.isSecure(userId);
   7102     }
   7103 
   7104     /** {@inheritDoc} */
   7105     @Override
   7106     public boolean isKeyguardOccluded() {
   7107         if (mKeyguardDelegate == null) return false;
   7108         return mKeyguardOccluded;
   7109     }
   7110 
   7111     /** {@inheritDoc} */
   7112     @Override
   7113     public boolean inKeyguardRestrictedKeyInputMode() {
   7114         if (mKeyguardDelegate == null) return false;
   7115         return mKeyguardDelegate.isInputRestricted();
   7116     }
   7117 
   7118     @Override
   7119     public void dismissKeyguardLw(IKeyguardDismissCallback callback, CharSequence message) {
   7120         if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
   7121             if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
   7122 
   7123             // ask the keyguard to prompt the user to authenticate if necessary
   7124             mKeyguardDelegate.dismiss(callback, message);
   7125         } else if (callback != null) {
   7126             try {
   7127                 callback.onDismissError();
   7128             } catch (RemoteException e) {
   7129                 Slog.w(TAG, "Failed to call callback", e);
   7130             }
   7131         }
   7132     }
   7133 
   7134     @Override
   7135     public boolean isKeyguardDrawnLw() {
   7136         synchronized (mLock) {
   7137             return mKeyguardDrawnOnce;
   7138         }
   7139     }
   7140 
   7141     @Override
   7142     public boolean isShowingDreamLw() {
   7143         return mShowingDream;
   7144     }
   7145 
   7146     @Override
   7147     public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
   7148         if (mKeyguardDelegate != null) {
   7149             if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
   7150             mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
   7151         }
   7152     }
   7153 
   7154     @Override
   7155     public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
   7156             DisplayCutout displayCutout, Rect outInsets) {
   7157         outInsets.setEmpty();
   7158 
   7159         // Navigation bar and status bar.
   7160         getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, displayCutout, outInsets);
   7161         outInsets.top = Math.max(outInsets.top, mStatusBarHeightForRotation[displayRotation]);
   7162     }
   7163 
   7164     @Override
   7165     public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
   7166             DisplayCutout displayCutout, Rect outInsets) {
   7167         outInsets.setEmpty();
   7168 
   7169         // Only navigation bar
   7170         if (mHasNavigationBar) {
   7171             int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
   7172             if (position == NAV_BAR_BOTTOM) {
   7173                 outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
   7174             } else if (position == NAV_BAR_RIGHT) {
   7175                 outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
   7176             } else if (position == NAV_BAR_LEFT) {
   7177                 outInsets.left = getNavigationBarWidth(displayRotation, mUiMode);
   7178             }
   7179         }
   7180 
   7181         if (displayCutout != null) {
   7182             outInsets.left += displayCutout.getSafeInsetLeft();
   7183             outInsets.top += displayCutout.getSafeInsetTop();
   7184             outInsets.right += displayCutout.getSafeInsetRight();
   7185             outInsets.bottom += displayCutout.getSafeInsetBottom();
   7186         }
   7187     }
   7188 
   7189     @Override
   7190     public boolean isNavBarForcedShownLw(WindowState windowState) {
   7191         return mForceShowSystemBars;
   7192     }
   7193 
   7194     @Override
   7195     public int getNavBarPosition() {
   7196         // TODO(multi-display): Support system decor on secondary displays.
   7197         return mNavigationBarPosition;
   7198     }
   7199 
   7200     @Override
   7201     public boolean isDockSideAllowed(int dockSide, int originalDockSide, int displayWidth,
   7202             int displayHeight, int displayRotation) {
   7203         final int barPosition = navigationBarPosition(displayWidth, displayHeight, displayRotation);
   7204         return isDockSideAllowed(dockSide, originalDockSide, barPosition, mNavigationBarCanMove);
   7205     }
   7206 
   7207     @VisibleForTesting
   7208     static boolean isDockSideAllowed(int dockSide, int originalDockSide,
   7209             int navBarPosition, boolean navigationBarCanMove) {
   7210         if (dockSide == DOCKED_TOP) {
   7211             return true;
   7212         }
   7213 
   7214         if (navigationBarCanMove) {
   7215             // Only allow the dockside opposite to the nav bar position in landscape
   7216             return dockSide == DOCKED_LEFT && navBarPosition == NAV_BAR_RIGHT
   7217                     || dockSide == DOCKED_RIGHT && navBarPosition == NAV_BAR_LEFT;
   7218         }
   7219 
   7220         // Side is the same as original side
   7221         if (dockSide == originalDockSide) {
   7222             return true;
   7223         }
   7224 
   7225         // Only if original docked side was top in portrait will allow left for landscape
   7226         if (dockSide == DOCKED_LEFT && originalDockSide == DOCKED_TOP) {
   7227             return true;
   7228         }
   7229         return false;
   7230     }
   7231 
   7232     void sendCloseSystemWindows() {
   7233         PhoneWindow.sendCloseSystemWindows(mContext, null);
   7234     }
   7235 
   7236     void sendCloseSystemWindows(String reason) {
   7237         PhoneWindow.sendCloseSystemWindows(mContext, reason);
   7238     }
   7239 
   7240     @Override
   7241     public int rotationForOrientationLw(int orientation, int lastRotation, boolean defaultDisplay) {
   7242         if (false) {
   7243             Slog.v(TAG, "rotationForOrientationLw(orient="
   7244                         + orientation + ", last=" + lastRotation
   7245                         + "); user=" + mUserRotation + " "
   7246                         + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
   7247                             ? "USER_ROTATION_LOCKED" : "")
   7248                         );
   7249         }
   7250 
   7251         if (mForceDefaultOrientation) {
   7252             return Surface.ROTATION_0;
   7253         }
   7254 
   7255         synchronized (mLock) {
   7256             int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
   7257             if (sensorRotation < 0) {
   7258                 sensorRotation = lastRotation;
   7259             }
   7260 
   7261             final int preferredRotation;
   7262             if (!defaultDisplay) {
   7263                 // For secondary displays we ignore things like displays sensors, docking mode and
   7264                 // rotation lock, and always prefer a default rotation.
   7265                 preferredRotation = Surface.ROTATION_0;
   7266             } else if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
   7267                 // Ignore sensor when lid switch is open and rotation is forced.
   7268                 preferredRotation = mLidOpenRotation;
   7269             } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
   7270                     && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
   7271                 // Ignore sensor when in car dock unless explicitly enabled.
   7272                 // This case can override the behavior of NOSENSOR, and can also
   7273                 // enable 180 degree rotation while docked.
   7274                 preferredRotation = mCarDockEnablesAccelerometer
   7275                         ? sensorRotation : mCarDockRotation;
   7276             } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
   7277                     || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
   7278                     || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
   7279                     && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
   7280                 // Ignore sensor when in desk dock unless explicitly enabled.
   7281                 // This case can override the behavior of NOSENSOR, and can also
   7282                 // enable 180 degree rotation while docked.
   7283                 preferredRotation = mDeskDockEnablesAccelerometer
   7284                         ? sensorRotation : mDeskDockRotation;
   7285             } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
   7286                 // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
   7287                 // Note that the dock orientation overrides the HDMI orientation.
   7288                 preferredRotation = mDemoHdmiRotation;
   7289             } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
   7290                     && mUndockedHdmiRotation >= 0) {
   7291                 // Ignore sensor when plugged into HDMI and an undocked orientation has
   7292                 // been specified in the configuration (only for legacy devices without
   7293                 // full multi-display support).
   7294                 // Note that the dock orientation overrides the HDMI orientation.
   7295                 preferredRotation = mUndockedHdmiRotation;
   7296             } else if (mDemoRotationLock) {
   7297                 // Ignore sensor when demo rotation lock is enabled.
   7298                 // Note that the dock orientation and HDMI rotation lock override this.
   7299                 preferredRotation = mDemoRotation;
   7300             } else if (mPersistentVrModeEnabled) {
   7301                 // While in VR, apps always prefer a portrait rotation. This does not change
   7302                 // any apps that explicitly set landscape, but does cause sensors be ignored,
   7303                 // and ignored any orientation lock that the user has set (this conditional
   7304                 // should remain above the ORIENTATION_LOCKED conditional below).
   7305                 preferredRotation = mPortraitRotation;
   7306             } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
   7307                 // Application just wants to remain locked in the last rotation.
   7308                 preferredRotation = lastRotation;
   7309             } else if (!mSupportAutoRotation) {
   7310                 // If we don't support auto-rotation then bail out here and ignore
   7311                 // the sensor and any rotation lock settings.
   7312                 preferredRotation = -1;
   7313             } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
   7314                             && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
   7315                                     || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
   7316                                     || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
   7317                                     || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
   7318                                     || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
   7319                     || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
   7320                     || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
   7321                     || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
   7322                     || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
   7323                 // Otherwise, use sensor only if requested by the application or enabled
   7324                 // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
   7325                 if (mAllowAllRotations < 0) {
   7326                     // Can't read this during init() because the context doesn't
   7327                     // have display metrics at that time so we cannot determine
   7328                     // tablet vs. phone then.
   7329                     mAllowAllRotations = mContext.getResources().getBoolean(
   7330                             com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
   7331                 }
   7332                 if (sensorRotation != Surface.ROTATION_180
   7333                         || mAllowAllRotations == 1
   7334                         || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
   7335                         || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
   7336                     preferredRotation = sensorRotation;
   7337                 } else {
   7338                     preferredRotation = lastRotation;
   7339                 }
   7340             } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
   7341                     && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
   7342                 // Apply rotation lock.  Does not apply to NOSENSOR.
   7343                 // The idea is that the user rotation expresses a weak preference for the direction
   7344                 // of gravity and as NOSENSOR is never affected by gravity, then neither should
   7345                 // NOSENSOR be affected by rotation lock (although it will be affected by docks).
   7346                 preferredRotation = mUserRotation;
   7347             } else {
   7348                 // No overriding preference.
   7349                 // We will do exactly what the application asked us to do.
   7350                 preferredRotation = -1;
   7351             }
   7352 
   7353             switch (orientation) {
   7354                 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
   7355                     // Return portrait unless overridden.
   7356                     if (isAnyPortrait(preferredRotation)) {
   7357                         return preferredRotation;
   7358                     }
   7359                     return mPortraitRotation;
   7360 
   7361                 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
   7362                     // Return landscape unless overridden.
   7363                     if (isLandscapeOrSeascape(preferredRotation)) {
   7364                         return preferredRotation;
   7365                     }
   7366                     return mLandscapeRotation;
   7367 
   7368                 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
   7369                     // Return reverse portrait unless overridden.
   7370                     if (isAnyPortrait(preferredRotation)) {
   7371                         return preferredRotation;
   7372                     }
   7373                     return mUpsideDownRotation;
   7374 
   7375                 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
   7376                     // Return seascape unless overridden.
   7377                     if (isLandscapeOrSeascape(preferredRotation)) {
   7378                         return preferredRotation;
   7379                     }
   7380                     return mSeascapeRotation;
   7381 
   7382                 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
   7383                 case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
   7384                     // Return either landscape rotation.
   7385                     if (isLandscapeOrSeascape(preferredRotation)) {
   7386                         return preferredRotation;
   7387                     }
   7388                     if (isLandscapeOrSeascape(lastRotation)) {
   7389                         return lastRotation;
   7390                     }
   7391                     return mLandscapeRotation;
   7392 
   7393                 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
   7394                 case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
   7395                     // Return either portrait rotation.
   7396                     if (isAnyPortrait(preferredRotation)) {
   7397                         return preferredRotation;
   7398                     }
   7399                     if (isAnyPortrait(lastRotation)) {
   7400                         return lastRotation;
   7401                     }
   7402                     return mPortraitRotation;
   7403 
   7404                 default:
   7405                     // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
   7406                     // just return the preferred orientation we already calculated.
   7407                     if (preferredRotation >= 0) {
   7408                         return preferredRotation;
   7409                     }
   7410                     return Surface.ROTATION_0;
   7411             }
   7412         }
   7413     }
   7414 
   7415     @Override
   7416     public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
   7417         switch (orientation) {
   7418             case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
   7419             case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
   7420             case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
   7421                 return isAnyPortrait(rotation);
   7422 
   7423             case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
   7424             case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
   7425             case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
   7426                 return isLandscapeOrSeascape(rotation);
   7427 
   7428             default:
   7429                 return true;
   7430         }
   7431     }
   7432 
   7433     @Override
   7434     public void setRotationLw(int rotation) {
   7435         mOrientationListener.setCurrentRotation(rotation);
   7436     }
   7437 
   7438     public boolean isRotationChoicePossible(int orientation) {
   7439         // Rotation choice is only shown when the user is in locked mode.
   7440         if (mUserRotationMode != WindowManagerPolicy.USER_ROTATION_LOCKED) return false;
   7441 
   7442         // We should only enable rotation choice if the rotation isn't forced by the lid, dock,
   7443         // demo, hdmi, vr, etc mode
   7444 
   7445         // Determine if the rotation is currently forced
   7446         if (mForceDefaultOrientation) {
   7447             return false; // Rotation is forced to default orientation
   7448 
   7449         } else if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
   7450             return false; // Rotation is forced mLidOpenRotation
   7451 
   7452         } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && !mCarDockEnablesAccelerometer) {
   7453             return false; // Rotation forced to mCarDockRotation
   7454 
   7455         } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
   7456                 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
   7457                 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
   7458                 && !mDeskDockEnablesAccelerometer) {
   7459             return false; // Rotation forced to mDeskDockRotation
   7460 
   7461         } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
   7462             return false; // Rotation forced to mDemoHdmiRotation
   7463 
   7464         } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
   7465                 && mUndockedHdmiRotation >= 0) {
   7466             return false; // Rotation forced to mUndockedHdmiRotation
   7467 
   7468         } else if (mDemoRotationLock) {
   7469             return false; // Rotation forced to mDemoRotation
   7470 
   7471         } else if (mPersistentVrModeEnabled) {
   7472             return false; // Rotation forced to mPortraitRotation
   7473 
   7474         } else if (!mSupportAutoRotation) {
   7475             return false;
   7476         }
   7477 
   7478         // Ensure that some rotation choice is possible for the given orientation
   7479         switch (orientation) {
   7480             case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
   7481             case ActivityInfo.SCREEN_ORIENTATION_USER:
   7482             case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
   7483             case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
   7484             case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
   7485                 // NOSENSOR description is ambiguous, in reality WM ignores user choice
   7486                 return true;
   7487         }
   7488 
   7489         // Rotation is forced, should be controlled by system
   7490         return false;
   7491     }
   7492 
   7493     public boolean isValidRotationChoice(int orientation, final int preferredRotation) {
   7494         // Determine if the given app orientation is compatible with the provided rotation choice
   7495         switch (orientation) {
   7496             case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
   7497                 // Works with any of the 4 rotations
   7498                 return preferredRotation >= 0;
   7499 
   7500             case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
   7501                 // It's possible for the user pref to be set at 180 because of FULL_USER. This would
   7502                 // make switching to USER_PORTRAIT appear at 180. Provide choice to back to portrait
   7503                 // but never to go to 180.
   7504                 return preferredRotation == mPortraitRotation;
   7505 
   7506             case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
   7507                 // Works landscape or seascape
   7508                 return isLandscapeOrSeascape(preferredRotation);
   7509 
   7510             case ActivityInfo.SCREEN_ORIENTATION_USER:
   7511             case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
   7512                 // Works with any rotation except upside down
   7513                 return (preferredRotation >= 0) && (preferredRotation != mUpsideDownRotation);
   7514         }
   7515 
   7516         return false;
   7517     }
   7518 
   7519     private boolean isLandscapeOrSeascape(int rotation) {
   7520         return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
   7521     }
   7522 
   7523     private boolean isAnyPortrait(int rotation) {
   7524         return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
   7525     }
   7526 
   7527     @Override
   7528     public int getUserRotationMode() {
   7529         return Settings.System.getIntForUser(mContext.getContentResolver(),
   7530                 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
   7531                         WindowManagerPolicy.USER_ROTATION_FREE :
   7532                                 WindowManagerPolicy.USER_ROTATION_LOCKED;
   7533     }
   7534 
   7535     // User rotation: to be used when all else fails in assigning an orientation to the device
   7536     @Override
   7537     public void setUserRotationMode(int mode, int rot) {
   7538         ContentResolver res = mContext.getContentResolver();
   7539 
   7540         // mUserRotationMode and mUserRotation will be assigned by the content observer
   7541         if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
   7542             Settings.System.putIntForUser(res,
   7543                     Settings.System.USER_ROTATION,
   7544                     rot,
   7545                     UserHandle.USER_CURRENT);
   7546             Settings.System.putIntForUser(res,
   7547                     Settings.System.ACCELEROMETER_ROTATION,
   7548                     0,
   7549                     UserHandle.USER_CURRENT);
   7550         } else {
   7551             Settings.System.putIntForUser(res,
   7552                     Settings.System.ACCELEROMETER_ROTATION,
   7553                     1,
   7554                     UserHandle.USER_CURRENT);
   7555         }
   7556     }
   7557 
   7558     @Override
   7559     public void setSafeMode(boolean safeMode) {
   7560         mSafeMode = safeMode;
   7561         if (safeMode) {
   7562             performHapticFeedbackLw(null, HapticFeedbackConstants.SAFE_MODE_ENABLED, true);
   7563         }
   7564     }
   7565 
   7566     static long[] getLongIntArray(Resources r, int resid) {
   7567         return ArrayUtils.convertToLongArray(r.getIntArray(resid));
   7568     }
   7569 
   7570     private void bindKeyguard() {
   7571         synchronized (mLock) {
   7572             if (mKeyguardBound) {
   7573                 return;
   7574             }
   7575             mKeyguardBound = true;
   7576         }
   7577         mKeyguardDelegate.bindService(mContext);
   7578     }
   7579 
   7580     @Override
   7581     public void onSystemUiStarted() {
   7582         bindKeyguard();
   7583     }
   7584 
   7585     /** {@inheritDoc} */
   7586     @Override
   7587     public void systemReady() {
   7588         // In normal flow, systemReady is called before other system services are ready.
   7589         // So it is better not to bind keyguard here.
   7590         mKeyguardDelegate.onSystemReady();
   7591 
   7592         mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
   7593         if (mVrManagerInternal != null) {
   7594             mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
   7595         }
   7596 
   7597         readCameraLensCoverState();
   7598         updateUiMode();
   7599         synchronized (mLock) {
   7600             updateOrientationListenerLp();
   7601             mSystemReady = true;
   7602             mHandler.post(new Runnable() {
   7603                 @Override
   7604                 public void run() {
   7605                     updateSettings();
   7606                 }
   7607             });
   7608             // If this happens, for whatever reason, systemReady came later than systemBooted.
   7609             // And keyguard should be already bound from systemBooted
   7610             if (mSystemBooted) {
   7611                 mKeyguardDelegate.onBootCompleted();
   7612             }
   7613         }
   7614 
   7615         mSystemGestures.systemReady();
   7616         mImmersiveModeConfirmation.systemReady();
   7617 
   7618         mAutofillManagerInternal = LocalServices.getService(AutofillManagerInternal.class);
   7619     }
   7620 
   7621     /** {@inheritDoc} */
   7622     @Override
   7623     public void systemBooted() {
   7624         bindKeyguard();
   7625         synchronized (mLock) {
   7626             mSystemBooted = true;
   7627             if (mSystemReady) {
   7628                 mKeyguardDelegate.onBootCompleted();
   7629             }
   7630         }
   7631         startedWakingUp();
   7632         screenTurningOn(null);
   7633         screenTurnedOn();
   7634     }
   7635 
   7636     @Override
   7637     public boolean canDismissBootAnimation() {
   7638         synchronized (mLock) {
   7639             return mKeyguardDrawComplete;
   7640         }
   7641     }
   7642 
   7643     ProgressDialog mBootMsgDialog = null;
   7644 
   7645     /** {@inheritDoc} */
   7646     @Override
   7647     public void showBootMessage(final CharSequence msg, final boolean always) {
   7648         mHandler.post(new Runnable() {
   7649             @Override public void run() {
   7650                 if (mBootMsgDialog == null) {
   7651                     int theme;
   7652                     if (mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK)) {
   7653                         theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
   7654                     } else {
   7655                         theme = 0;
   7656                     }
   7657 
   7658                     mBootMsgDialog = new ProgressDialog(mContext, theme) {
   7659                         // This dialog will consume all events coming in to
   7660                         // it, to avoid it trying to do things too early in boot.
   7661                         @Override public boolean dispatchKeyEvent(KeyEvent event) {
   7662                             return true;
   7663                         }
   7664                         @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
   7665                             return true;
   7666                         }
   7667                         @Override public boolean dispatchTouchEvent(MotionEvent ev) {
   7668                             return true;
   7669                         }
   7670                         @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
   7671                             return true;
   7672                         }
   7673                         @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
   7674                             return true;
   7675                         }
   7676                         @Override public boolean dispatchPopulateAccessibilityEvent(
   7677                                 AccessibilityEvent event) {
   7678                             return true;
   7679                         }
   7680                     };
   7681                     if (mContext.getPackageManager().isUpgrade()) {
   7682                         mBootMsgDialog.setTitle(R.string.android_upgrading_title);
   7683                     } else {
   7684                         mBootMsgDialog.setTitle(R.string.android_start_title);
   7685                     }
   7686                     mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
   7687                     mBootMsgDialog.setIndeterminate(true);
   7688                     mBootMsgDialog.getWindow().setType(
   7689                             WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
   7690                     mBootMsgDialog.getWindow().addFlags(
   7691                             WindowManager.LayoutParams.FLAG_DIM_BEHIND
   7692                             | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
   7693                     mBootMsgDialog.getWindow().setDimAmount(1);
   7694                     WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
   7695                     lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
   7696                     mBootMsgDialog.getWindow().setAttributes(lp);
   7697                     mBootMsgDialog.setCancelable(false);
   7698                     mBootMsgDialog.show();
   7699                 }
   7700                 mBootMsgDialog.setMessage(msg);
   7701             }
   7702         });
   7703     }
   7704 
   7705     /** {@inheritDoc} */
   7706     @Override
   7707     public void hideBootMessages() {
   7708         mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
   7709     }
   7710 
   7711     @Override
   7712     public void requestUserActivityNotification() {
   7713         if (!mNotifyUserActivity && !mHandler.hasMessages(MSG_NOTIFY_USER_ACTIVITY)) {
   7714             mNotifyUserActivity = true;
   7715         }
   7716     }
   7717 
   7718     /** {@inheritDoc} */
   7719     @Override
   7720     public void userActivity() {
   7721         // ***************************************
   7722         // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
   7723         // ***************************************
   7724         // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
   7725         // WITH ITS LOCKS HELD.
   7726         //
   7727         // This code must be VERY careful about the locks
   7728         // it acquires.
   7729         // In fact, the current code acquires way too many,
   7730         // and probably has lurking deadlocks.
   7731 
   7732         synchronized (mScreenLockTimeout) {
   7733             if (mLockScreenTimerActive) {
   7734                 // reset the timer
   7735                 mHandler.removeCallbacks(mScreenLockTimeout);
   7736                 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
   7737             }
   7738         }
   7739 
   7740         if (mAwake && mNotifyUserActivity) {
   7741             mHandler.sendEmptyMessageDelayed(MSG_NOTIFY_USER_ACTIVITY,
   7742                     USER_ACTIVITY_NOTIFICATION_DELAY);
   7743             mNotifyUserActivity = false;
   7744         }
   7745     }
   7746 
   7747     class ScreenLockTimeout implements Runnable {
   7748         Bundle options;
   7749 
   7750         @Override
   7751         public void run() {
   7752             synchronized (this) {
   7753                 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
   7754                 if (mKeyguardDelegate != null) {
   7755                     mKeyguardDelegate.doKeyguardTimeout(options);
   7756                 }
   7757                 mLockScreenTimerActive = false;
   7758                 options = null;
   7759             }
   7760         }
   7761 
   7762         public void setLockOptions(Bundle options) {
   7763             this.options = options;
   7764         }
   7765     }
   7766 
   7767     ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
   7768 
   7769     @Override
   7770     public void lockNow(Bundle options) {
   7771         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
   7772         mHandler.removeCallbacks(mScreenLockTimeout);
   7773         if (options != null) {
   7774             // In case multiple calls are made to lockNow, we don't wipe out the options
   7775             // until the runnable actually executes.
   7776             mScreenLockTimeout.setLockOptions(options);
   7777         }
   7778         mHandler.post(mScreenLockTimeout);
   7779     }
   7780 
   7781     private void updateLockScreenTimeout() {
   7782         synchronized (mScreenLockTimeout) {
   7783             boolean enable = (mAllowLockscreenWhenOn && mAwake &&
   7784                     mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
   7785             if (mLockScreenTimerActive != enable) {
   7786                 if (enable) {
   7787                     if (localLOGV) Log.v(TAG, "setting lockscreen timer");
   7788                     mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
   7789                     mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
   7790                 } else {
   7791                     if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
   7792                     mHandler.removeCallbacks(mScreenLockTimeout);
   7793                 }
   7794                 mLockScreenTimerActive = enable;
   7795             }
   7796         }
   7797     }
   7798 
   7799     // TODO (multidisplay): Support multiple displays in WindowManagerPolicy.
   7800     private void updateDreamingSleepToken(boolean acquire) {
   7801         if (acquire) {
   7802             if (mDreamingSleepToken == null) {
   7803                 mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken(
   7804                         "Dream", DEFAULT_DISPLAY);
   7805             }
   7806         } else {
   7807             if (mDreamingSleepToken != null) {
   7808                 mDreamingSleepToken.release();
   7809                 mDreamingSleepToken = null;
   7810             }
   7811         }
   7812     }
   7813 
   7814     // TODO (multidisplay): Support multiple displays in WindowManagerPolicy.
   7815     private void updateScreenOffSleepToken(boolean acquire) {
   7816         if (acquire) {
   7817             if (mScreenOffSleepToken == null) {
   7818                 mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken(
   7819                         "ScreenOff", DEFAULT_DISPLAY);
   7820             }
   7821         } else {
   7822             if (mScreenOffSleepToken != null) {
   7823                 mScreenOffSleepToken.release();
   7824                 mScreenOffSleepToken = null;
   7825             }
   7826         }
   7827     }
   7828 
   7829     /** {@inheritDoc} */
   7830     @Override
   7831     public void enableScreenAfterBoot() {
   7832         readLidState();
   7833         applyLidSwitchState();
   7834         updateRotation(true);
   7835     }
   7836 
   7837     private void applyLidSwitchState() {
   7838         if (mLidState == LID_CLOSED && mLidControlsSleep) {
   7839             goToSleep(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
   7840                     PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
   7841         } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
   7842             mWindowManagerFuncs.lockDeviceNow();
   7843         }
   7844 
   7845         synchronized (mLock) {
   7846             updateWakeGestureListenerLp();
   7847         }
   7848     }
   7849 
   7850     void updateUiMode() {
   7851         if (mUiModeManager == null) {
   7852             mUiModeManager = IUiModeManager.Stub.asInterface(
   7853                     ServiceManager.getService(Context.UI_MODE_SERVICE));
   7854         }
   7855         try {
   7856             mUiMode = mUiModeManager.getCurrentModeType();
   7857         } catch (RemoteException e) {
   7858         }
   7859     }
   7860 
   7861     void updateRotation(boolean alwaysSendConfiguration) {
   7862         try {
   7863             //set orientation on WindowManager
   7864             mWindowManager.updateRotation(alwaysSendConfiguration, false);
   7865         } catch (RemoteException e) {
   7866             // Ignore
   7867         }
   7868     }
   7869 
   7870     void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
   7871         try {
   7872             //set orientation on WindowManager
   7873             mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
   7874         } catch (RemoteException e) {
   7875             // Ignore
   7876         }
   7877     }
   7878 
   7879     /**
   7880      * Return an Intent to launch the currently active dock app as home.  Returns
   7881      * null if the standard home should be launched, which is the case if any of the following is
   7882      * true:
   7883      * <ul>
   7884      *  <li>The device is not in either car mode or desk mode
   7885      *  <li>The device is in car mode but mEnableCarDockHomeCapture is false
   7886      *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
   7887      *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
   7888      *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
   7889      * </ul>
   7890      * @return A dock intent.
   7891      */
   7892     Intent createHomeDockIntent() {
   7893         Intent intent = null;
   7894 
   7895         // What home does is based on the mode, not the dock state.  That
   7896         // is, when in car mode you should be taken to car home regardless
   7897         // of whether we are actually in a car dock.
   7898         if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
   7899             if (mEnableCarDockHomeCapture) {
   7900                 intent = mCarDockIntent;
   7901             }
   7902         } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
   7903             if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
   7904                 intent = mDeskDockIntent;
   7905             }
   7906         } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
   7907                 && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
   7908                         || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
   7909                         || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
   7910             // Always launch dock home from home when watch is docked, if it exists.
   7911             intent = mDeskDockIntent;
   7912         } else if (mUiMode == Configuration.UI_MODE_TYPE_VR_HEADSET) {
   7913             if (ENABLE_VR_HEADSET_HOME_CAPTURE) {
   7914                 intent = mVrHeadsetHomeIntent;
   7915             }
   7916         }
   7917 
   7918         if (intent == null) {
   7919             return null;
   7920         }
   7921 
   7922         ActivityInfo ai = null;
   7923         ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
   7924                 intent,
   7925                 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
   7926                 mCurrentUserId);
   7927         if (info != null) {
   7928             ai = info.activityInfo;
   7929         }
   7930         if (ai != null
   7931                 && ai.metaData != null
   7932                 && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
   7933             intent = new Intent(intent);
   7934             intent.setClassName(ai.packageName, ai.name);
   7935             return intent;
   7936         }
   7937 
   7938         return null;
   7939     }
   7940 
   7941     void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
   7942         try {
   7943             ActivityManager.getService().stopAppSwitches();
   7944         } catch (RemoteException e) {}
   7945         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
   7946 
   7947         if (awakenFromDreams) {
   7948             awakenDreams();
   7949         }
   7950 
   7951         Intent dock = createHomeDockIntent();
   7952         if (dock != null) {
   7953             try {
   7954                 if (fromHomeKey) {
   7955                     dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
   7956                 }
   7957                 startActivityAsUser(dock, UserHandle.CURRENT);
   7958                 return;
   7959             } catch (ActivityNotFoundException e) {
   7960             }
   7961         }
   7962 
   7963         Intent intent;
   7964 
   7965         if (fromHomeKey) {
   7966             intent = new Intent(mHomeIntent);
   7967             intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
   7968         } else {
   7969             intent = mHomeIntent;
   7970         }
   7971 
   7972         startActivityAsUser(intent, UserHandle.CURRENT);
   7973     }
   7974 
   7975     /**
   7976      * goes to the home screen
   7977      * @return whether it did anything
   7978      */
   7979     boolean goHome() {
   7980         if (!isUserSetupComplete()) {
   7981             Slog.i(TAG, "Not going home because user setup is in progress.");
   7982             return false;
   7983         }
   7984         if (false) {
   7985             // This code always brings home to the front.
   7986             startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
   7987         } else {
   7988             // This code brings home to the front or, if it is already
   7989             // at the front, puts the device to sleep.
   7990             try {
   7991                 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
   7992                     /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
   7993                     Log.d(TAG, "UTS-TEST-MODE");
   7994                 } else {
   7995                     ActivityManager.getService().stopAppSwitches();
   7996                     sendCloseSystemWindows();
   7997                     Intent dock = createHomeDockIntent();
   7998                     if (dock != null) {
   7999                         int result = ActivityManager.getService()
   8000                                 .startActivityAsUser(null, null, dock,
   8001                                         dock.resolveTypeIfNeeded(mContext.getContentResolver()),
   8002                                         null, null, 0,
   8003                                         ActivityManager.START_FLAG_ONLY_IF_NEEDED,
   8004                                         null, null, UserHandle.USER_CURRENT);
   8005                         if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
   8006                             return false;
   8007                         }
   8008                     }
   8009                 }
   8010                 int result = ActivityManager.getService()
   8011                         .startActivityAsUser(null, null, mHomeIntent,
   8012                                 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
   8013                                 null, null, 0,
   8014                                 ActivityManager.START_FLAG_ONLY_IF_NEEDED,
   8015                                 null, null, UserHandle.USER_CURRENT);
   8016                 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
   8017                     return false;
   8018                 }
   8019             } catch (RemoteException ex) {
   8020                 // bummer, the activity manager, which is in this process, is dead
   8021             }
   8022         }
   8023         return true;
   8024     }
   8025 
   8026     @Override
   8027     public void setCurrentOrientationLw(int newOrientation) {
   8028         synchronized (mLock) {
   8029             if (newOrientation != mCurrentAppOrientation) {
   8030                 mCurrentAppOrientation = newOrientation;
   8031                 updateOrientationListenerLp();
   8032             }
   8033         }
   8034     }
   8035 
   8036     private boolean isTheaterModeEnabled() {
   8037         return Settings.Global.getInt(mContext.getContentResolver(),
   8038                 Settings.Global.THEATER_MODE_ON, 0) == 1;
   8039     }
   8040 
   8041     @Override
   8042     public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
   8043         if (!mVibrator.hasVibrator()) {
   8044             return false;
   8045         }
   8046         final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
   8047                 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
   8048         if (hapticsDisabled && !always) {
   8049             return false;
   8050         }
   8051 
   8052         VibrationEffect effect = getVibrationEffect(effectId);
   8053         if (effect == null) {
   8054             return false;
   8055         }
   8056 
   8057         int owningUid;
   8058         String owningPackage;
   8059         if (win != null) {
   8060             owningUid = win.getOwningUid();
   8061             owningPackage = win.getOwningPackage();
   8062         } else {
   8063             owningUid = android.os.Process.myUid();
   8064             owningPackage = mContext.getOpPackageName();
   8065         }
   8066         mVibrator.vibrate(owningUid, owningPackage, effect, VIBRATION_ATTRIBUTES);
   8067         return true;
   8068     }
   8069 
   8070     private VibrationEffect getVibrationEffect(int effectId) {
   8071         long[] pattern;
   8072         switch (effectId) {
   8073             case HapticFeedbackConstants.CLOCK_TICK:
   8074             case HapticFeedbackConstants.CONTEXT_CLICK:
   8075                 return VibrationEffect.get(VibrationEffect.EFFECT_TICK);
   8076             case HapticFeedbackConstants.KEYBOARD_RELEASE:
   8077             case HapticFeedbackConstants.TEXT_HANDLE_MOVE:
   8078             case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE:
   8079             case HapticFeedbackConstants.ENTRY_BUMP:
   8080             case HapticFeedbackConstants.DRAG_CROSSING:
   8081             case HapticFeedbackConstants.GESTURE_END:
   8082                 return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false);
   8083             case HapticFeedbackConstants.KEYBOARD_TAP: // == KEYBOARD_PRESS
   8084             case HapticFeedbackConstants.VIRTUAL_KEY:
   8085             case HapticFeedbackConstants.EDGE_RELEASE:
   8086             case HapticFeedbackConstants.CONFIRM:
   8087             case HapticFeedbackConstants.GESTURE_START:
   8088                 return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
   8089             case HapticFeedbackConstants.LONG_PRESS:
   8090             case HapticFeedbackConstants.EDGE_SQUEEZE:
   8091                 return VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK);
   8092             case HapticFeedbackConstants.REJECT:
   8093                 return VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
   8094 
   8095             case HapticFeedbackConstants.CALENDAR_DATE:
   8096                 pattern = mCalendarDateVibePattern;
   8097                 break;
   8098             case HapticFeedbackConstants.SAFE_MODE_ENABLED:
   8099                 pattern = mSafeModeEnabledVibePattern;
   8100                 break;
   8101 
   8102             default:
   8103                 return null;
   8104         }
   8105         if (pattern.length == 0) {
   8106             // No vibration
   8107             return null;
   8108         } else if (pattern.length == 1) {
   8109             // One-shot vibration
   8110             return VibrationEffect.createOneShot(pattern[0], VibrationEffect.DEFAULT_AMPLITUDE);
   8111         } else {
   8112             // Pattern vibration
   8113             return VibrationEffect.createWaveform(pattern, -1);
   8114         }
   8115     }
   8116 
   8117     @Override
   8118     public void keepScreenOnStartedLw() {
   8119     }
   8120 
   8121     @Override
   8122     public void keepScreenOnStoppedLw() {
   8123         if (isKeyguardShowingAndNotOccluded()) {
   8124             mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
   8125         }
   8126     }
   8127 
   8128     private int updateSystemUiVisibilityLw() {
   8129         // If there is no window focused, there will be nobody to handle the events
   8130         // anyway, so just hang on in whatever state we're in until things settle down.
   8131         WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
   8132                 : mTopFullscreenOpaqueWindowState;
   8133         if (winCandidate == null) {
   8134             return 0;
   8135         }
   8136         if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
   8137             // The immersive mode confirmation should never affect the system bar visibility,
   8138             // otherwise it will unhide the navigation bar and hide itself.
   8139             winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState;
   8140             if (winCandidate == null) {
   8141                 return 0;
   8142             }
   8143         }
   8144         final WindowState win = winCandidate;
   8145         if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mKeyguardOccluded) {
   8146             // We are updating at a point where the keyguard has gotten
   8147             // focus, but we were last in a state where the top window is
   8148             // hiding it.  This is probably because the keyguard as been
   8149             // shown while the top window was displayed, so we want to ignore
   8150             // it here because this is just a very transient change and it
   8151             // will quickly lose focus once it correctly gets hidden.
   8152             return 0;
   8153         }
   8154 
   8155         int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
   8156                 & ~mResettingSystemUiFlags
   8157                 & ~mForceClearedSystemUiFlags;
   8158         if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
   8159             tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
   8160         }
   8161 
   8162         final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
   8163                 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
   8164         final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
   8165                 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
   8166         mWindowManagerFuncs.getStackBounds(
   8167                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, mNonDockedStackBounds);
   8168         mWindowManagerFuncs.getStackBounds(
   8169                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, mDockedStackBounds);
   8170         final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
   8171         final int diff = visibility ^ mLastSystemUiFlags;
   8172         final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
   8173         final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
   8174         final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
   8175         if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
   8176                 && mFocusedApp == win.getAppToken()
   8177                 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
   8178                 && mLastDockedStackBounds.equals(mDockedStackBounds)) {
   8179             return 0;
   8180         }
   8181         mLastSystemUiFlags = visibility;
   8182         mLastFullscreenStackSysUiFlags = fullscreenVisibility;
   8183         mLastDockedStackSysUiFlags = dockedVisibility;
   8184         mLastFocusNeedsMenu = needsMenu;
   8185         mFocusedApp = win.getAppToken();
   8186         final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
   8187         final Rect dockedStackBounds = new Rect(mDockedStackBounds);
   8188         mHandler.post(new Runnable() {
   8189                 @Override
   8190                 public void run() {
   8191                     StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
   8192                     if (statusbar != null) {
   8193                         statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
   8194                                 dockedVisibility, 0xffffffff, fullscreenStackBounds,
   8195                                 dockedStackBounds, win.toString());
   8196                         statusbar.topAppWindowChanged(needsMenu);
   8197                     }
   8198                 }
   8199             });
   8200         return diff;
   8201     }
   8202 
   8203     private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
   8204         final boolean onKeyguard = isStatusBarKeyguard() && !mKeyguardOccluded;
   8205         final WindowState statusColorWin = onKeyguard ? mStatusBar : opaqueOrDimming;
   8206         if (statusColorWin != null && (statusColorWin == opaque || onKeyguard)) {
   8207             // If the top fullscreen-or-dimming window is also the top fullscreen, respect
   8208             // its light flag.
   8209             vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
   8210             vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
   8211                     & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
   8212         } else if (statusColorWin != null && statusColorWin.isDimming()) {
   8213             // Otherwise if it's dimming, clear the light flag.
   8214             vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
   8215         }
   8216         return vis;
   8217     }
   8218 
   8219     @VisibleForTesting
   8220     @Nullable
   8221     static WindowState chooseNavigationColorWindowLw(WindowState opaque,
   8222             WindowState opaqueOrDimming, WindowState imeWindow,
   8223             @NavigationBarPosition int navBarPosition) {
   8224         // If the IME window is visible and FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS is set, then IME
   8225         // window can be navigation color window.
   8226         final boolean imeWindowCanNavColorWindow = imeWindow != null
   8227                 && imeWindow.isVisibleLw()
   8228                 && navBarPosition == NAV_BAR_BOTTOM
   8229                 && (PolicyControl.getWindowFlags(imeWindow, null)
   8230                 & WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
   8231 
   8232         if (opaque != null && opaqueOrDimming == opaque) {
   8233             // If the top fullscreen-or-dimming window is also the top fullscreen, respect it
   8234             // unless IME window is also eligible, since currently the IME window is always show
   8235             // above the opaque fullscreen app window, regardless of the IME target window.
   8236             // TODO(b/31559891): Maybe we need to revisit this condition once b/31559891 is fixed.
   8237             return imeWindowCanNavColorWindow ? imeWindow : opaque;
   8238         }
   8239 
   8240         if (opaqueOrDimming == null || !opaqueOrDimming.isDimming()) {
   8241             // No dimming window is involved. Determine the result only with the IME window.
   8242             return imeWindowCanNavColorWindow ? imeWindow : null;
   8243         }
   8244 
   8245         if (!imeWindowCanNavColorWindow) {
   8246             // No IME window is involved. Determine the result only with opaqueOrDimming.
   8247             return opaqueOrDimming;
   8248         }
   8249 
   8250         // The IME window and the dimming window are competing.  Check if the dimming window can be
   8251         // IME target or not.
   8252         if (LayoutParams.mayUseInputMethod(PolicyControl.getWindowFlags(opaqueOrDimming, null))) {
   8253             // The IME window is above the dimming window.
   8254             return imeWindow;
   8255         } else {
   8256             // The dimming window is above the IME window.
   8257             return opaqueOrDimming;
   8258         }
   8259     }
   8260 
   8261     @VisibleForTesting
   8262     static int updateLightNavigationBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming,
   8263             WindowState imeWindow, WindowState navColorWin) {
   8264 
   8265         if (navColorWin != null) {
   8266             if (navColorWin == imeWindow || navColorWin == opaque) {
   8267                 // Respect the light flag.
   8268                 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
   8269                 vis |= PolicyControl.getSystemUiVisibility(navColorWin, null)
   8270                         & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
   8271             } else if (navColorWin == opaqueOrDimming && navColorWin.isDimming()) {
   8272                 // Clear the light flag for dimming window.
   8273                 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
   8274             }
   8275         }
   8276         return vis;
   8277     }
   8278 
   8279     private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
   8280         final boolean dockedStackVisible =
   8281                 mWindowManagerInternal.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
   8282         final boolean freeformStackVisible =
   8283                 mWindowManagerInternal.isStackVisible(WINDOWING_MODE_FREEFORM);
   8284         final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
   8285 
   8286         // We need to force system bars when the docked stack is visible, when the freeform stack
   8287         // is visible but also when we are resizing for the transitions when docked stack
   8288         // visibility changes.
   8289         mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
   8290         final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
   8291 
   8292         // apply translucent bar vis flags
   8293         WindowState fullscreenTransWin = isStatusBarKeyguard() && !mKeyguardOccluded
   8294                 ? mStatusBar
   8295                 : mTopFullscreenOpaqueWindowState;
   8296         vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
   8297         vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
   8298         final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
   8299                 mTopDockedOpaqueWindowState, 0, 0);
   8300 
   8301         final boolean fullscreenDrawsStatusBarBackground =
   8302                 drawsStatusBarBackground(vis, mTopFullscreenOpaqueWindowState);
   8303         final boolean dockedDrawsStatusBarBackground =
   8304                 drawsStatusBarBackground(dockedVis, mTopDockedOpaqueWindowState);
   8305 
   8306         // prevent status bar interaction from clearing certain flags
   8307         int type = win.getAttrs().type;
   8308         boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
   8309         if (statusBarHasFocus && !isStatusBarKeyguard()) {
   8310             int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
   8311                     | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
   8312                     | View.SYSTEM_UI_FLAG_IMMERSIVE
   8313                     | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
   8314                     | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
   8315             if (mKeyguardOccluded) {
   8316                 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
   8317             }
   8318             vis = (vis & ~flags) | (oldVis & flags);
   8319         }
   8320 
   8321         if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
   8322             vis |= View.STATUS_BAR_TRANSPARENT;
   8323             vis &= ~View.STATUS_BAR_TRANSLUCENT;
   8324         } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
   8325                 || forceOpaqueStatusBar) {
   8326             vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
   8327         }
   8328 
   8329         vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
   8330 
   8331         // update status bar
   8332         boolean immersiveSticky =
   8333                 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
   8334         final boolean hideStatusBarWM =
   8335                 mTopFullscreenOpaqueWindowState != null
   8336                 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
   8337                         & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
   8338         final boolean hideStatusBarSysui =
   8339                 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
   8340         final boolean hideNavBarSysui =
   8341                 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
   8342 
   8343         final boolean transientStatusBarAllowed = mStatusBar != null
   8344                 && (statusBarHasFocus || (!mForceShowSystemBars
   8345                         && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
   8346 
   8347         final boolean transientNavBarAllowed = mNavigationBar != null
   8348                 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
   8349 
   8350         final long now = SystemClock.uptimeMillis();
   8351         final boolean pendingPanic = mPendingPanicGestureUptime != 0
   8352                 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
   8353         if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
   8354             // The user performed the panic gesture recently, we're about to hide the bars,
   8355             // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
   8356             mPendingPanicGestureUptime = 0;
   8357             mStatusBarController.showTransient();
   8358             if (!isNavBarEmpty(vis)) {
   8359                 mNavigationBarController.showTransient();
   8360             }
   8361         }
   8362 
   8363         final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
   8364                 && !transientStatusBarAllowed && hideStatusBarSysui;
   8365         final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
   8366                 && !transientNavBarAllowed;
   8367         if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
   8368             // clear the clearable flags instead
   8369             clearClearableFlagsLw();
   8370             vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
   8371         }
   8372 
   8373         final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
   8374         immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
   8375         final boolean navAllowedHidden = immersive || immersiveSticky;
   8376 
   8377         if (hideNavBarSysui && !navAllowedHidden
   8378                 && getWindowLayerLw(win) > getWindowLayerFromTypeLw(TYPE_INPUT_CONSUMER)) {
   8379             // We can't hide the navbar from this window otherwise the input consumer would not get
   8380             // the input events.
   8381             vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
   8382         }
   8383 
   8384         vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
   8385 
   8386         // update navigation bar
   8387         boolean oldImmersiveMode = isImmersiveMode(oldVis);
   8388         boolean newImmersiveMode = isImmersiveMode(vis);
   8389         if (win != null && oldImmersiveMode != newImmersiveMode) {
   8390             final String pkg = win.getOwningPackage();
   8391             mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
   8392                     isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility()));
   8393         }
   8394 
   8395         vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
   8396 
   8397         final WindowState navColorWin = chooseNavigationColorWindowLw(
   8398                 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState,
   8399                 mWindowManagerFuncs.getInputMethodWindowLw(), mNavigationBarPosition);
   8400         vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState,
   8401                 mTopFullscreenOpaqueOrDimmingWindowState,
   8402                 mWindowManagerFuncs.getInputMethodWindowLw(), navColorWin);
   8403 
   8404         return vis;
   8405     }
   8406 
   8407     private boolean drawsStatusBarBackground(int vis, WindowState win) {
   8408         if (!mStatusBarController.isTransparentAllowed(win)) {
   8409             return false;
   8410         }
   8411         if (win == null) {
   8412             return true;
   8413         }
   8414 
   8415         final boolean drawsSystemBars =
   8416                 (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
   8417         final boolean forceDrawsSystemBars =
   8418                 (win.getAttrs().privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
   8419 
   8420         return forceDrawsSystemBars || drawsSystemBars && (vis & View.STATUS_BAR_TRANSLUCENT) == 0;
   8421     }
   8422 
   8423     /**
   8424      * @return the current visibility flags with the nav-bar opacity related flags toggled based
   8425      *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
   8426      */
   8427     private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
   8428             boolean freeformStackVisible, boolean isDockedDividerResizing) {
   8429         if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
   8430             if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
   8431                 visibility = setNavBarOpaqueFlag(visibility);
   8432             }
   8433         } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
   8434             if (isDockedDividerResizing) {
   8435                 visibility = setNavBarOpaqueFlag(visibility);
   8436             } else if (freeformStackVisible) {
   8437                 visibility = setNavBarTranslucentFlag(visibility);
   8438             } else {
   8439                 visibility = setNavBarOpaqueFlag(visibility);
   8440             }
   8441         }
   8442 
   8443         if (!areTranslucentBarsAllowed()) {
   8444             visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
   8445         }
   8446         return visibility;
   8447     }
   8448 
   8449     private int setNavBarOpaqueFlag(int visibility) {
   8450         return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
   8451     }
   8452 
   8453     private int setNavBarTranslucentFlag(int visibility) {
   8454         visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
   8455         return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
   8456     }
   8457 
   8458     private void clearClearableFlagsLw() {
   8459         int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
   8460         if (newVal != mResettingSystemUiFlags) {
   8461             mResettingSystemUiFlags = newVal;
   8462             mWindowManagerFuncs.reevaluateStatusBarVisibility();
   8463         }
   8464     }
   8465 
   8466     private boolean isImmersiveMode(int vis) {
   8467         final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
   8468         return mNavigationBar != null
   8469                 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
   8470                 && (vis & flags) != 0
   8471                 && canHideNavigationBar();
   8472     }
   8473 
   8474     private static boolean isNavBarEmpty(int systemUiFlags) {
   8475         final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
   8476                 | View.STATUS_BAR_DISABLE_BACK
   8477                 | View.STATUS_BAR_DISABLE_RECENT);
   8478 
   8479         return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
   8480     }
   8481 
   8482     /**
   8483      * @return whether the navigation or status bar can be made translucent
   8484      *
   8485      * This should return true unless touch exploration is not enabled or
   8486      * R.boolean.config_enableTranslucentDecor is false.
   8487      */
   8488     private boolean areTranslucentBarsAllowed() {
   8489         return mTranslucentDecorEnabled;
   8490     }
   8491 
   8492     // Use this instead of checking config_showNavigationBar so that it can be consistently
   8493     // overridden by qemu.hw.mainkeys in the emulator.
   8494     @Override
   8495     public boolean hasNavigationBar() {
   8496         return mHasNavigationBar;
   8497     }
   8498 
   8499     @Override
   8500     public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
   8501         mLastInputMethodWindow = ime;
   8502         mLastInputMethodTargetWindow = target;
   8503     }
   8504 
   8505     @Override
   8506     public void setDismissImeOnBackKeyPressed(boolean newValue) {
   8507         mDismissImeOnBackKeyPressed = newValue;
   8508     }
   8509 
   8510     @Override
   8511     public void setCurrentUserLw(int newUserId) {
   8512         mCurrentUserId = newUserId;
   8513         if (mKeyguardDelegate != null) {
   8514             mKeyguardDelegate.setCurrentUser(newUserId);
   8515         }
   8516         if (mAccessibilityShortcutController != null) {
   8517             mAccessibilityShortcutController.setCurrentUser(newUserId);
   8518         }
   8519         StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
   8520         if (statusBar != null) {
   8521             statusBar.setCurrentUser(newUserId);
   8522         }
   8523         setLastInputMethodWindowLw(null, null);
   8524     }
   8525 
   8526     @Override
   8527     public void setSwitchingUser(boolean switching) {
   8528         mKeyguardDelegate.setSwitchingUser(switching);
   8529     }
   8530 
   8531     @Override
   8532     public boolean isTopLevelWindow(int windowType) {
   8533         if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
   8534                 && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
   8535             return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
   8536         }
   8537         return true;
   8538     }
   8539 
   8540     @Override
   8541     public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
   8542         // For the upside down rotation we don't rotate seamlessly as the navigation
   8543         // bar moves position.
   8544         // Note most apps (using orientation:sensor or user as opposed to fullSensor)
   8545         // will not enter the reverse portrait orientation, so actually the
   8546         // orientation won't change at all.
   8547         if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
   8548             return false;
   8549         }
   8550         // If the navigation bar can't change sides, then it will
   8551         // jump when we change orientations and we don't rotate
   8552         // seamlessly.
   8553         if (!mNavigationBarCanMove) {
   8554             return false;
   8555         }
   8556         int delta = newRotation - oldRotation;
   8557         if (delta < 0) delta += 4;
   8558         // Likewise we don't rotate seamlessly for 180 degree rotations
   8559         // in this case the surfaces never resize, and our logic to
   8560         // revert the transformations on size change will fail. We could
   8561         // fix this in the future with the "tagged" frames idea.
   8562         if (delta == Surface.ROTATION_180) {
   8563             return false;
   8564         }
   8565 
   8566         final WindowState w = mTopFullscreenOpaqueWindowState;
   8567         if (w != mFocusedWindow) {
   8568             return false;
   8569         }
   8570 
   8571         // We only enable seamless rotation if the top window has requested
   8572         // it and is in the fullscreen opaque state. Seamless rotation
   8573         // requires freezing various Surface states and won't work well
   8574         // with animations, so we disable it in the animation case for now.
   8575         if (w != null && !w.isAnimatingLw() &&
   8576                 ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) ||
   8577                         (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) {
   8578             return true;
   8579         }
   8580         return false;
   8581     }
   8582 
   8583     @Override
   8584     public void writeToProto(ProtoOutputStream proto, long fieldId) {
   8585         final long token = proto.start(fieldId);
   8586         proto.write(LAST_SYSTEM_UI_FLAGS, mLastSystemUiFlags);
   8587         proto.write(ROTATION_MODE, mUserRotationMode);
   8588         proto.write(ROTATION, mUserRotation);
   8589         proto.write(ORIENTATION, mCurrentAppOrientation);
   8590         proto.write(SCREEN_ON_FULLY, mScreenOnFully);
   8591         proto.write(KEYGUARD_DRAW_COMPLETE, mKeyguardDrawComplete);
   8592         proto.write(WINDOW_MANAGER_DRAW_COMPLETE, mWindowManagerDrawComplete);
   8593         if (mFocusedApp != null) {
   8594             proto.write(FOCUSED_APP_TOKEN, mFocusedApp.toString());
   8595         }
   8596         if (mFocusedWindow != null) {
   8597             mFocusedWindow.writeIdentifierToProto(proto, FOCUSED_WINDOW);
   8598         }
   8599         if (mTopFullscreenOpaqueWindowState != null) {
   8600             mTopFullscreenOpaqueWindowState.writeIdentifierToProto(
   8601                     proto, TOP_FULLSCREEN_OPAQUE_WINDOW);
   8602         }
   8603         if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
   8604             mTopFullscreenOpaqueOrDimmingWindowState.writeIdentifierToProto(
   8605                     proto, TOP_FULLSCREEN_OPAQUE_OR_DIMMING_WINDOW);
   8606         }
   8607         proto.write(KEYGUARD_OCCLUDED, mKeyguardOccluded);
   8608         proto.write(KEYGUARD_OCCLUDED_CHANGED, mKeyguardOccludedChanged);
   8609         proto.write(KEYGUARD_OCCLUDED_PENDING, mPendingKeyguardOccluded);
   8610         proto.write(FORCE_STATUS_BAR, mForceStatusBar);
   8611         proto.write(FORCE_STATUS_BAR_FROM_KEYGUARD, mForceStatusBarFromKeyguard);
   8612         mStatusBarController.writeToProto(proto, STATUS_BAR);
   8613         mNavigationBarController.writeToProto(proto, NAVIGATION_BAR);
   8614         if (mOrientationListener != null) {
   8615             mOrientationListener.writeToProto(proto, ORIENTATION_LISTENER);
   8616         }
   8617         if (mKeyguardDelegate != null) {
   8618             mKeyguardDelegate.writeToProto(proto, KEYGUARD_DELEGATE);
   8619         }
   8620         proto.end(token);
   8621     }
   8622 
   8623     @Override
   8624     public void dump(String prefix, PrintWriter pw, String[] args) {
   8625         pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
   8626                 pw.print(" mSystemReady="); pw.print(mSystemReady);
   8627                 pw.print(" mSystemBooted="); pw.println(mSystemBooted);
   8628         pw.print(prefix); pw.print("mLidState=");
   8629                 pw.print(WindowManagerFuncs.lidStateToString(mLidState));
   8630                 pw.print(" mLidOpenRotation=");
   8631                 pw.println(Surface.rotationToString(mLidOpenRotation));
   8632         pw.print(prefix); pw.print("mCameraLensCoverState=");
   8633                 pw.print(WindowManagerFuncs.cameraLensStateToString(mCameraLensCoverState));
   8634                 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
   8635         if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
   8636                 || mForceClearedSystemUiFlags != 0) {
   8637             pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
   8638                     pw.print(Integer.toHexString(mLastSystemUiFlags));
   8639                     pw.print(" mResettingSystemUiFlags=0x");
   8640                     pw.print(Integer.toHexString(mResettingSystemUiFlags));
   8641                     pw.print(" mForceClearedSystemUiFlags=0x");
   8642                     pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
   8643         }
   8644         if (mLastFocusNeedsMenu) {
   8645             pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
   8646                     pw.println(mLastFocusNeedsMenu);
   8647         }
   8648         pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
   8649                 pw.println(mWakeGestureEnabledSetting);
   8650 
   8651         pw.print(prefix);
   8652                 pw.print("mSupportAutoRotation="); pw.print(mSupportAutoRotation);
   8653                 pw.print(" mOrientationSensorEnabled="); pw.println(mOrientationSensorEnabled);
   8654         pw.print(prefix); pw.print("mUiMode="); pw.print(Configuration.uiModeToString(mUiMode));
   8655                 pw.print(" mDockMode="); pw.println(Intent.dockStateToString(mDockMode));
   8656         pw.print(prefix); pw.print("mEnableCarDockHomeCapture=");
   8657                 pw.print(mEnableCarDockHomeCapture);
   8658                 pw.print(" mCarDockRotation=");
   8659                 pw.print(Surface.rotationToString(mCarDockRotation));
   8660                 pw.print(" mDeskDockRotation=");
   8661                 pw.println(Surface.rotationToString(mDeskDockRotation));
   8662         pw.print(prefix); pw.print("mUserRotationMode=");
   8663                 pw.print(WindowManagerPolicy.userRotationModeToString(mUserRotationMode));
   8664                 pw.print(" mUserRotation="); pw.print(Surface.rotationToString(mUserRotation));
   8665                 pw.print(" mAllowAllRotations=");
   8666                 pw.println(allowAllRotationsToString(mAllowAllRotations));
   8667         pw.print(prefix); pw.print("mCurrentAppOrientation=");
   8668                 pw.println(ActivityInfo.screenOrientationToString(mCurrentAppOrientation));
   8669         pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
   8670                 pw.print(mCarDockEnablesAccelerometer);
   8671                 pw.print(" mDeskDockEnablesAccelerometer=");
   8672                 pw.println(mDeskDockEnablesAccelerometer);
   8673         pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
   8674                 pw.print(mLidKeyboardAccessibility);
   8675                 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
   8676                 pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
   8677         pw.print(prefix); pw.print("mLidControlsSleep="); pw.println(mLidControlsSleep);
   8678         pw.print(prefix);
   8679                 pw.print("mLongPressOnBackBehavior=");
   8680                 pw.println(longPressOnBackBehaviorToString(mLongPressOnBackBehavior));
   8681         pw.print(prefix);
   8682                 pw.print("mLongPressOnHomeBehavior=");
   8683                 pw.println(longPressOnHomeBehaviorToString(mLongPressOnHomeBehavior));
   8684         pw.print(prefix);
   8685                 pw.print("mDoubleTapOnHomeBehavior=");
   8686                 pw.println(doubleTapOnHomeBehaviorToString(mDoubleTapOnHomeBehavior));
   8687         pw.print(prefix);
   8688                 pw.print("mShortPressOnPowerBehavior=");
   8689                 pw.println(shortPressOnPowerBehaviorToString(mShortPressOnPowerBehavior));
   8690         pw.print(prefix);
   8691                 pw.print("mLongPressOnPowerBehavior=");
   8692                 pw.println(longPressOnPowerBehaviorToString(mLongPressOnPowerBehavior));
   8693         pw.print(prefix);
   8694                 pw.print("mVeryLongPressOnPowerBehavior=");
   8695                 pw.println(veryLongPressOnPowerBehaviorToString(mVeryLongPressOnPowerBehavior));
   8696         pw.print(prefix);
   8697                 pw.print("mDoublePressOnPowerBehavior=");
   8698                 pw.println(multiPressOnPowerBehaviorToString(mDoublePressOnPowerBehavior));
   8699         pw.print(prefix);
   8700                 pw.print("mTriplePressOnPowerBehavior=");
   8701                 pw.println(multiPressOnPowerBehaviorToString(mTriplePressOnPowerBehavior));
   8702         pw.print(prefix);
   8703                 pw.print("mShortPressOnSleepBehavior=");
   8704                 pw.println(shortPressOnSleepBehaviorToString(mShortPressOnSleepBehavior));
   8705         pw.print(prefix);
   8706                 pw.print("mShortPressOnWindowBehavior=");
   8707                 pw.println(shortPressOnWindowBehaviorToString(mShortPressOnWindowBehavior));
   8708         pw.print(prefix);
   8709                 pw.print("mAllowStartActivityForLongPressOnPowerDuringSetup=");
   8710                 pw.println(mAllowStartActivityForLongPressOnPowerDuringSetup);
   8711         pw.print(prefix);
   8712                 pw.print("mHasSoftInput="); pw.print(mHasSoftInput);
   8713                 pw.print(" mDismissImeOnBackKeyPressed="); pw.println(mDismissImeOnBackKeyPressed);
   8714         pw.print(prefix);
   8715                 pw.print("mIncallPowerBehavior=");
   8716                 pw.print(incallPowerBehaviorToString(mIncallPowerBehavior));
   8717                 pw.print(" mIncallBackBehavior=");
   8718                 pw.print(incallBackBehaviorToString(mIncallBackBehavior));
   8719                 pw.print(" mEndcallBehavior=");
   8720                 pw.println(endcallBehaviorToString(mEndcallBehavior));
   8721         pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
   8722         pw.print(prefix);
   8723                 pw.print("mAwake="); pw.print(mAwake);
   8724                 pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
   8725                 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
   8726         pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
   8727                 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
   8728         pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
   8729                 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
   8730         pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
   8731                 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
   8732                 pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
   8733         if (mLastInputMethodWindow != null) {
   8734             pw.print(prefix); pw.print("mLastInputMethodWindow=");
   8735                     pw.println(mLastInputMethodWindow);
   8736         }
   8737         if (mLastInputMethodTargetWindow != null) {
   8738             pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
   8739                     pw.println(mLastInputMethodTargetWindow);
   8740         }
   8741         if (mStatusBar != null) {
   8742             pw.print(prefix); pw.print("mStatusBar=");
   8743                     pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
   8744                     pw.println(isStatusBarKeyguard());
   8745         }
   8746         if (mNavigationBar != null) {
   8747             pw.print(prefix); pw.print("mNavigationBar=");
   8748                     pw.println(mNavigationBar);
   8749         }
   8750         if (mFocusedWindow != null) {
   8751             pw.print(prefix); pw.print("mFocusedWindow=");
   8752                     pw.println(mFocusedWindow);
   8753         }
   8754         if (mFocusedApp != null) {
   8755             pw.print(prefix); pw.print("mFocusedApp=");
   8756                     pw.println(mFocusedApp);
   8757         }
   8758         if (mTopFullscreenOpaqueWindowState != null) {
   8759             pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
   8760                     pw.println(mTopFullscreenOpaqueWindowState);
   8761         }
   8762         if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
   8763             pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
   8764                     pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
   8765         }
   8766         if (mForcingShowNavBar) {
   8767             pw.print(prefix); pw.print("mForcingShowNavBar=");
   8768                     pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
   8769                     pw.println(mForcingShowNavBarLayer);
   8770         }
   8771         pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
   8772                 pw.print(" mKeyguardOccluded="); pw.println(mKeyguardOccluded);
   8773         pw.print(prefix);
   8774                 pw.print("mKeyguardOccludedChanged="); pw.print(mKeyguardOccludedChanged);
   8775                 pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded);
   8776         pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
   8777                 pw.print(" mForceStatusBarFromKeyguard=");
   8778                 pw.println(mForceStatusBarFromKeyguard);
   8779         pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
   8780                 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
   8781                 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
   8782         pw.print(prefix); pw.print("mLandscapeRotation=");
   8783                 pw.print(Surface.rotationToString(mLandscapeRotation));
   8784                 pw.print(" mSeascapeRotation=");
   8785                 pw.println(Surface.rotationToString(mSeascapeRotation));
   8786         pw.print(prefix); pw.print("mPortraitRotation=");
   8787                 pw.print(Surface.rotationToString(mPortraitRotation));
   8788                 pw.print(" mUpsideDownRotation=");
   8789                 pw.println(Surface.rotationToString(mUpsideDownRotation));
   8790         pw.print(prefix); pw.print("mDemoHdmiRotation=");
   8791                 pw.print(Surface.rotationToString(mDemoHdmiRotation));
   8792                 pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
   8793         pw.print(prefix); pw.print("mUndockedHdmiRotation=");
   8794                 pw.println(Surface.rotationToString(mUndockedHdmiRotation));
   8795         if (mHasFeatureLeanback) {
   8796             pw.print(prefix);
   8797             pw.print("mAccessibilityTvKey1Pressed="); pw.println(mAccessibilityTvKey1Pressed);
   8798             pw.print(prefix);
   8799             pw.print("mAccessibilityTvKey2Pressed="); pw.println(mAccessibilityTvKey2Pressed);
   8800             pw.print(prefix);
   8801             pw.print("mAccessibilityTvScheduled="); pw.println(mAccessibilityTvScheduled);
   8802         }
   8803 
   8804         mGlobalKeyManager.dump(prefix, pw);
   8805         mStatusBarController.dump(pw, prefix);
   8806         mNavigationBarController.dump(pw, prefix);
   8807         PolicyControl.dump(prefix, pw);
   8808 
   8809         if (mWakeGestureListener != null) {
   8810             mWakeGestureListener.dump(pw, prefix);
   8811         }
   8812         if (mOrientationListener != null) {
   8813             mOrientationListener.dump(pw, prefix);
   8814         }
   8815         if (mBurnInProtectionHelper != null) {
   8816             mBurnInProtectionHelper.dump(prefix, pw);
   8817         }
   8818         if (mKeyguardDelegate != null) {
   8819             mKeyguardDelegate.dump(prefix, pw);
   8820         }
   8821 
   8822         pw.print(prefix); pw.println("Looper state:");
   8823         mHandler.getLooper().dump(new PrintWriterPrinter(pw), prefix + "  ");
   8824     }
   8825 
   8826     private static String allowAllRotationsToString(int allowAll) {
   8827         switch (allowAll) {
   8828             case -1:
   8829                 return "unknown";
   8830             case 0:
   8831                 return "false";
   8832             case 1:
   8833                 return "true";
   8834             default:
   8835                 return Integer.toString(allowAll);
   8836         }
   8837     }
   8838 
   8839     private static String endcallBehaviorToString(int behavior) {
   8840         StringBuilder sb = new StringBuilder();
   8841         if ((behavior & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0 ) {
   8842             sb.append("home|");
   8843         }
   8844         if ((behavior & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
   8845             sb.append("sleep|");
   8846         }
   8847 
   8848         final int N = sb.length();
   8849         if (N == 0) {
   8850             return "<nothing>";
   8851         } else {
   8852             // Chop off the trailing '|'
   8853             return sb.substring(0, N - 1);
   8854         }
   8855     }
   8856 
   8857     private static String incallPowerBehaviorToString(int behavior) {
   8858         if ((behavior & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0) {
   8859             return "hangup";
   8860         } else {
   8861             return "sleep";
   8862         }
   8863     }
   8864 
   8865     private static String incallBackBehaviorToString(int behavior) {
   8866         if ((behavior & Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_HANGUP) != 0) {
   8867             return "hangup";
   8868         } else {
   8869             return "<nothing>";
   8870         }
   8871     }
   8872 
   8873     private static String longPressOnBackBehaviorToString(int behavior) {
   8874         switch (behavior) {
   8875             case LONG_PRESS_BACK_NOTHING:
   8876                 return "LONG_PRESS_BACK_NOTHING";
   8877             case LONG_PRESS_BACK_GO_TO_VOICE_ASSIST:
   8878                 return "LONG_PRESS_BACK_GO_TO_VOICE_ASSIST";
   8879             default:
   8880                 return Integer.toString(behavior);
   8881         }
   8882     }
   8883 
   8884     private static String longPressOnHomeBehaviorToString(int behavior) {
   8885         switch (behavior) {
   8886             case LONG_PRESS_HOME_NOTHING:
   8887                 return "LONG_PRESS_HOME_NOTHING";
   8888             case LONG_PRESS_HOME_ALL_APPS:
   8889                 return "LONG_PRESS_HOME_ALL_APPS";
   8890             case LONG_PRESS_HOME_ASSIST:
   8891                 return "LONG_PRESS_HOME_ASSIST";
   8892             default:
   8893                 return Integer.toString(behavior);
   8894         }
   8895     }
   8896 
   8897     private static String doubleTapOnHomeBehaviorToString(int behavior) {
   8898         switch (behavior) {
   8899             case DOUBLE_TAP_HOME_NOTHING:
   8900                 return "DOUBLE_TAP_HOME_NOTHING";
   8901             case DOUBLE_TAP_HOME_RECENT_SYSTEM_UI:
   8902                 return "DOUBLE_TAP_HOME_RECENT_SYSTEM_UI";
   8903             default:
   8904                 return Integer.toString(behavior);
   8905         }
   8906     }
   8907 
   8908     private static String shortPressOnPowerBehaviorToString(int behavior) {
   8909         switch (behavior) {
   8910             case SHORT_PRESS_POWER_NOTHING:
   8911                 return "SHORT_PRESS_POWER_NOTHING";
   8912             case SHORT_PRESS_POWER_GO_TO_SLEEP:
   8913                 return "SHORT_PRESS_POWER_GO_TO_SLEEP";
   8914             case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
   8915                 return "SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP";
   8916             case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
   8917                 return "SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME";
   8918             case SHORT_PRESS_POWER_GO_HOME:
   8919                 return "SHORT_PRESS_POWER_GO_HOME";
   8920             case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME:
   8921                 return "SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME";
   8922             default:
   8923                 return Integer.toString(behavior);
   8924         }
   8925     }
   8926 
   8927     private static String longPressOnPowerBehaviorToString(int behavior) {
   8928         switch (behavior) {
   8929             case LONG_PRESS_POWER_NOTHING:
   8930                 return "LONG_PRESS_POWER_NOTHING";
   8931             case LONG_PRESS_POWER_GLOBAL_ACTIONS:
   8932                 return "LONG_PRESS_POWER_GLOBAL_ACTIONS";
   8933             case LONG_PRESS_POWER_SHUT_OFF:
   8934                 return "LONG_PRESS_POWER_SHUT_OFF";
   8935             case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
   8936                 return "LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM";
   8937             default:
   8938                 return Integer.toString(behavior);
   8939         }
   8940     }
   8941 
   8942     private static String veryLongPressOnPowerBehaviorToString(int behavior) {
   8943         switch (behavior) {
   8944             case VERY_LONG_PRESS_POWER_NOTHING:
   8945                 return "VERY_LONG_PRESS_POWER_NOTHING";
   8946             case VERY_LONG_PRESS_POWER_GLOBAL_ACTIONS:
   8947                 return "VERY_LONG_PRESS_POWER_GLOBAL_ACTIONS";
   8948             default:
   8949                 return Integer.toString(behavior);
   8950         }
   8951     }
   8952 
   8953     private static String multiPressOnPowerBehaviorToString(int behavior) {
   8954         switch (behavior) {
   8955             case MULTI_PRESS_POWER_NOTHING:
   8956                 return "MULTI_PRESS_POWER_NOTHING";
   8957             case MULTI_PRESS_POWER_THEATER_MODE:
   8958                 return "MULTI_PRESS_POWER_THEATER_MODE";
   8959             case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
   8960                 return "MULTI_PRESS_POWER_BRIGHTNESS_BOOST";
   8961             default:
   8962                 return Integer.toString(behavior);
   8963         }
   8964     }
   8965 
   8966     private static String shortPressOnSleepBehaviorToString(int behavior) {
   8967         switch (behavior) {
   8968             case SHORT_PRESS_SLEEP_GO_TO_SLEEP:
   8969                 return "SHORT_PRESS_SLEEP_GO_TO_SLEEP";
   8970             case SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME:
   8971                 return "SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME";
   8972             default:
   8973                 return Integer.toString(behavior);
   8974         }
   8975     }
   8976 
   8977     private static String shortPressOnWindowBehaviorToString(int behavior) {
   8978         switch (behavior) {
   8979             case SHORT_PRESS_WINDOW_NOTHING:
   8980                 return "SHORT_PRESS_WINDOW_NOTHING";
   8981             case SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE:
   8982                 return "SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE";
   8983             default:
   8984                 return Integer.toString(behavior);
   8985         }
   8986     }
   8987 
   8988     @Override
   8989     public void onLockTaskStateChangedLw(int lockTaskState) {
   8990         mImmersiveModeConfirmation.onLockTaskModeChangedLw(lockTaskState);
   8991     }
   8992 
   8993     @Override
   8994     public boolean setAodShowing(boolean aodShowing) {
   8995         if (mAodShowing != aodShowing) {
   8996             mAodShowing = aodShowing;
   8997             return true;
   8998         }
   8999         return false;
   9000     }
   9001 }
   9002