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