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