Home | History | Annotate | Download | only in impl
      1 /*
      2  *
      3  * Licensed under the Apache License, Version 2.0 (the "License");
      4  * you may not use this file except in compliance with the License.
      5  * You may obtain a copy of the License at
      6  *
      7  *      http://www.apache.org/licenses/LICENSE-2.0
      8  *
      9  * Unless required by applicable law or agreed to in writing, software
     10  * distributed under the License is distributed on an "AS IS" BASIS,
     11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12  * See the License for the specific language governing permissions and
     13  * limitations under the License.
     14  */
     15 
     16 package com.android.internal.policy.impl;
     17 
     18 import android.app.ActivityManager;
     19 import android.app.ActivityManagerNative;
     20 import android.app.AppOpsManager;
     21 import android.app.IUiModeManager;
     22 import android.app.ProgressDialog;
     23 import android.app.SearchManager;
     24 import android.app.StatusBarManager;
     25 import android.app.UiModeManager;
     26 import android.content.ActivityNotFoundException;
     27 import android.content.BroadcastReceiver;
     28 import android.content.ComponentName;
     29 import android.content.ContentResolver;
     30 import android.content.Context;
     31 import android.content.Intent;
     32 import android.content.IntentFilter;
     33 import android.content.ServiceConnection;
     34 import android.content.pm.ActivityInfo;
     35 import android.content.pm.PackageManager;
     36 import android.content.pm.ResolveInfo;
     37 import android.content.res.CompatibilityInfo;
     38 import android.content.res.Configuration;
     39 import android.content.res.Resources;
     40 import android.content.res.TypedArray;
     41 import android.database.ContentObserver;
     42 import android.graphics.PixelFormat;
     43 import android.graphics.Rect;
     44 import android.media.AudioAttributes;
     45 import android.media.AudioManager;
     46 import android.media.IAudioService;
     47 import android.media.Ringtone;
     48 import android.media.RingtoneManager;
     49 import android.media.session.MediaSessionLegacyHelper;
     50 import android.os.Bundle;
     51 import android.os.Debug;
     52 import android.os.FactoryTest;
     53 import android.os.Handler;
     54 import android.os.IBinder;
     55 import android.os.Looper;
     56 import android.os.Message;
     57 import android.os.Messenger;
     58 import android.os.PowerManager;
     59 import android.os.RemoteException;
     60 import android.os.ServiceManager;
     61 import android.os.SystemClock;
     62 import android.os.SystemProperties;
     63 import android.os.UEventObserver;
     64 import android.os.UserHandle;
     65 import android.os.Vibrator;
     66 import android.provider.MediaStore;
     67 import android.provider.Settings;
     68 import android.service.dreams.DreamManagerInternal;
     69 import android.service.dreams.DreamService;
     70 import android.service.dreams.IDreamManager;
     71 import android.speech.RecognizerIntent;
     72 import android.telecom.TelecomManager;
     73 import android.util.DisplayMetrics;
     74 import android.util.EventLog;
     75 import android.util.Log;
     76 import android.util.Slog;
     77 import android.util.SparseArray;
     78 import android.view.Display;
     79 import android.view.Gravity;
     80 import android.view.HapticFeedbackConstants;
     81 import android.view.IApplicationToken;
     82 import android.view.IWindowManager;
     83 import android.view.InputChannel;
     84 import android.view.InputDevice;
     85 import android.view.InputEvent;
     86 import android.view.InputEventReceiver;
     87 import android.view.KeyCharacterMap;
     88 import android.view.KeyCharacterMap.FallbackAction;
     89 import android.view.KeyEvent;
     90 import android.view.MotionEvent;
     91 import android.view.Surface;
     92 import android.view.View;
     93 import android.view.ViewConfiguration;
     94 import android.view.Window;
     95 import android.view.WindowManager;
     96 import android.view.WindowManagerGlobal;
     97 import android.view.WindowManagerInternal;
     98 import android.view.WindowManagerPolicy;
     99 import android.view.accessibility.AccessibilityEvent;
    100 import android.view.accessibility.AccessibilityManager;
    101 import android.view.animation.Animation;
    102 import android.view.animation.AnimationSet;
    103 import android.view.animation.AnimationUtils;
    104 
    105 import com.android.internal.R;
    106 import com.android.internal.policy.PolicyManager;
    107 import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate;
    108 import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate.ShowListener;
    109 import com.android.internal.statusbar.IStatusBarService;
    110 import com.android.internal.widget.PointerLocationView;
    111 import com.android.server.LocalServices;
    112 
    113 import java.io.File;
    114 import java.io.FileReader;
    115 import java.io.IOException;
    116 import java.io.PrintWriter;
    117 import java.util.HashSet;
    118 import java.util.List;
    119 
    120 import static android.view.WindowManager.LayoutParams.*;
    121 import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
    122 import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
    123 import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
    124 import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
    125 import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
    126 import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
    127 
    128 /**
    129  * WindowManagerPolicy implementation for the Android phone UI.  This
    130  * introduces a new method suffix, Lp, for an internal lock of the
    131  * PhoneWindowManager.  This is used to protect some internal state, and
    132  * can be acquired with either the Lw and Li lock held, so has the restrictions
    133  * of both of those when held.
    134  */
    135 public class PhoneWindowManager implements WindowManagerPolicy {
    136     static final String TAG = "WindowManager";
    137     static final boolean DEBUG = false;
    138     static final boolean localLOGV = false;
    139     static final boolean DEBUG_INPUT = false;
    140     static final boolean DEBUG_KEYGUARD = false;
    141     static final boolean DEBUG_LAYOUT = false;
    142     static final boolean DEBUG_STARTING_WINDOW = false;
    143     static final boolean DEBUG_WAKEUP = false;
    144     static final boolean SHOW_STARTING_ANIMATIONS = true;
    145     static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
    146 
    147     // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
    148     // No longer recommended for desk docks; still useful in car docks.
    149     static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true;
    150     static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
    151 
    152     static final int SHORT_PRESS_POWER_NOTHING = 0;
    153     static final int SHORT_PRESS_POWER_GO_TO_SLEEP = 1;
    154     static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2;
    155     static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3;
    156 
    157     static final int LONG_PRESS_POWER_NOTHING = 0;
    158     static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
    159     static final int LONG_PRESS_POWER_SHUT_OFF = 2;
    160     static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
    161 
    162     static final int MULTI_PRESS_POWER_NOTHING = 0;
    163     static final int MULTI_PRESS_POWER_THEATER_MODE = 1;
    164     static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2;
    165 
    166     // These need to match the documentation/constant in
    167     // core/res/res/values/config.xml
    168     static final int LONG_PRESS_HOME_NOTHING = 0;
    169     static final int LONG_PRESS_HOME_RECENT_SYSTEM_UI = 1;
    170     static final int LONG_PRESS_HOME_ASSIST = 2;
    171 
    172     static final int DOUBLE_TAP_HOME_NOTHING = 0;
    173     static final int DOUBLE_TAP_HOME_RECENT_SYSTEM_UI = 1;
    174 
    175     static final int APPLICATION_MEDIA_SUBLAYER = -2;
    176     static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
    177     static final int APPLICATION_PANEL_SUBLAYER = 1;
    178     static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
    179 
    180     static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
    181     static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
    182     static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
    183     static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
    184     static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";
    185 
    186     /**
    187      * These are the system UI flags that, when changing, can cause the layout
    188      * of the screen to change.
    189      */
    190     static final int SYSTEM_UI_CHANGING_LAYOUT =
    191               View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
    192             | View.SYSTEM_UI_FLAG_FULLSCREEN
    193             | View.STATUS_BAR_TRANSLUCENT
    194             | View.NAVIGATION_BAR_TRANSLUCENT
    195             | View.SYSTEM_UI_TRANSPARENT;
    196 
    197     private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
    198             .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
    199             .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
    200             .build();
    201 
    202     /**
    203      * Keyguard stuff
    204      */
    205     private WindowState mKeyguardScrim;
    206     private boolean mKeyguardHidden;
    207     private boolean mKeyguardDrawnOnce;
    208 
    209     /* Table of Application Launch keys.  Maps from key codes to intent categories.
    210      *
    211      * These are special keys that are used to launch particular kinds of applications,
    212      * such as a web browser.  HID defines nearly a hundred of them in the Consumer (0x0C)
    213      * usage page.  We don't support quite that many yet...
    214      */
    215     static SparseArray<String> sApplicationLaunchKeyCategories;
    216     static {
    217         sApplicationLaunchKeyCategories = new SparseArray<String>();
    218         sApplicationLaunchKeyCategories.append(
    219                 KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER);
    220         sApplicationLaunchKeyCategories.append(
    221                 KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL);
    222         sApplicationLaunchKeyCategories.append(
    223                 KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS);
    224         sApplicationLaunchKeyCategories.append(
    225                 KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR);
    226         sApplicationLaunchKeyCategories.append(
    227                 KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC);
    228         sApplicationLaunchKeyCategories.append(
    229                 KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
    230     }
    231 
    232     /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
    233     static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;
    234 
    235     /**
    236      * Lock protecting internal state.  Must not call out into window
    237      * manager with lock held.  (This lock will be acquired in places
    238      * where the window manager is calling in with its own lock held.)
    239      */
    240     private final Object mLock = new Object();
    241 
    242     Context mContext;
    243     IWindowManager mWindowManager;
    244     WindowManagerFuncs mWindowManagerFuncs;
    245     WindowManagerInternal mWindowManagerInternal;
    246     PowerManager mPowerManager;
    247     DreamManagerInternal mDreamManagerInternal;
    248     IStatusBarService mStatusBarService;
    249     boolean mPreloadedRecentApps;
    250     final Object mServiceAquireLock = new Object();
    251     Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
    252     SearchManager mSearchManager;
    253     AccessibilityManager mAccessibilityManager;
    254 
    255     // Vibrator pattern for haptic feedback of a long press.
    256     long[] mLongPressVibePattern;
    257 
    258     // Vibrator pattern for haptic feedback of virtual key press.
    259     long[] mVirtualKeyVibePattern;
    260 
    261     // Vibrator pattern for a short vibration.
    262     long[] mKeyboardTapVibePattern;
    263 
    264     // Vibrator pattern for a short vibration when tapping on an hour/minute tick of a Clock.
    265     long[] mClockTickVibePattern;
    266 
    267     // Vibrator pattern for a short vibration when tapping on a day/month/year date of a Calendar.
    268     long[] mCalendarDateVibePattern;
    269 
    270     // Vibrator pattern for haptic feedback during boot when safe mode is disabled.
    271     long[] mSafeModeDisabledVibePattern;
    272 
    273     // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
    274     long[] mSafeModeEnabledVibePattern;
    275 
    276     /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
    277     boolean mEnableShiftMenuBugReports = false;
    278 
    279     boolean mSafeMode;
    280     WindowState mStatusBar = null;
    281     int mStatusBarHeight;
    282     WindowState mNavigationBar = null;
    283     boolean mHasNavigationBar = false;
    284     boolean mCanHideNavigationBar = false;
    285     boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?
    286     boolean mNavigationBarOnBottom = true; // is the navigation bar on the bottom *right now*?
    287     int[] mNavigationBarHeightForRotation = new int[4];
    288     int[] mNavigationBarWidthForRotation = new int[4];
    289 
    290     boolean mBootMessageNeedsHiding;
    291     KeyguardServiceDelegate mKeyguardDelegate;
    292     final Runnable mWindowManagerDrawCallback = new Runnable() {
    293         @Override
    294         public void run() {
    295             if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!");
    296             mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);
    297         }
    298     };
    299     final ShowListener mKeyguardDelegateCallback = new ShowListener() {
    300         @Override
    301         public void onShown(IBinder windowToken) {
    302             if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onShown.");
    303             mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
    304         }
    305     };
    306 
    307     GlobalActions mGlobalActions;
    308     Handler mHandler;
    309     WindowState mLastInputMethodWindow = null;
    310     WindowState mLastInputMethodTargetWindow = null;
    311 
    312     // FIXME This state is shared between the input reader and handler thread.
    313     // Technically it's broken and buggy but it has been like this for many years
    314     // and we have not yet seen any problems.  Someday we'll rewrite this logic
    315     // so that only one thread is involved in handling input policy.  Unfortunately
    316     // it's on a critical path for power management so we can't just post the work to the
    317     // handler thread.  We'll need to resolve this someday by teaching the input dispatcher
    318     // to hold wakelocks during dispatch and eliminating the critical path.
    319     volatile boolean mPowerKeyHandled;
    320     volatile boolean mBeganFromNonInteractive;
    321     volatile int mPowerKeyPressCounter;
    322     volatile boolean mEndCallKeyHandled;
    323 
    324     boolean mRecentsVisible;
    325     int mRecentAppsHeldModifiers;
    326     boolean mLanguageSwitchKeyPressed;
    327 
    328     int mLidState = LID_ABSENT;
    329     int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT;
    330     boolean mHaveBuiltInKeyboard;
    331 
    332     boolean mSystemReady;
    333     boolean mSystemBooted;
    334     boolean mHdmiPlugged;
    335     IUiModeManager mUiModeManager;
    336     int mUiMode;
    337     int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
    338     int mLidOpenRotation;
    339     int mCarDockRotation;
    340     int mDeskDockRotation;
    341     int mUndockedHdmiRotation;
    342     int mDemoHdmiRotation;
    343     boolean mDemoHdmiRotationLock;
    344     int mDemoRotation;
    345     boolean mDemoRotationLock;
    346 
    347     boolean mWakeGestureEnabledSetting;
    348     MyWakeGestureListener mWakeGestureListener;
    349 
    350     // Default display does not rotate, apps that require non-default orientation will have to
    351     // have the orientation emulated.
    352     private boolean mForceDefaultOrientation = false;
    353 
    354     int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
    355     int mUserRotation = Surface.ROTATION_0;
    356     boolean mAccelerometerDefault;
    357 
    358     boolean mSupportAutoRotation;
    359     int mAllowAllRotations = -1;
    360     boolean mCarDockEnablesAccelerometer;
    361     boolean mDeskDockEnablesAccelerometer;
    362     int mLidKeyboardAccessibility;
    363     int mLidNavigationAccessibility;
    364     boolean mLidControlsSleep;
    365     int mShortPressOnPowerBehavior;
    366     int mLongPressOnPowerBehavior;
    367     int mDoublePressOnPowerBehavior;
    368     int mTriplePressOnPowerBehavior;
    369     boolean mAwake;
    370     boolean mScreenOnEarly;
    371     boolean mScreenOnFully;
    372     ScreenOnListener mScreenOnListener;
    373     boolean mKeyguardDrawComplete;
    374     boolean mWindowManagerDrawComplete;
    375     boolean mOrientationSensorEnabled = false;
    376     int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
    377     boolean mHasSoftInput = false;
    378     boolean mTranslucentDecorEnabled = true;
    379 
    380     int mPointerLocationMode = 0; // guarded by mLock
    381 
    382     // The last window we were told about in focusChanged.
    383     WindowState mFocusedWindow;
    384     IApplicationToken mFocusedApp;
    385 
    386     PointerLocationView mPointerLocationView;
    387 
    388     // The current size of the screen; really; extends into the overscan area of
    389     // the screen and doesn't account for any system elements like the status bar.
    390     int mOverscanScreenLeft, mOverscanScreenTop;
    391     int mOverscanScreenWidth, mOverscanScreenHeight;
    392     // The current visible size of the screen; really; (ir)regardless of whether the status
    393     // bar can be hidden but not extending into the overscan area.
    394     int mUnrestrictedScreenLeft, mUnrestrictedScreenTop;
    395     int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight;
    396     // Like mOverscanScreen*, but allowed to move into the overscan region where appropriate.
    397     int mRestrictedOverscanScreenLeft, mRestrictedOverscanScreenTop;
    398     int mRestrictedOverscanScreenWidth, mRestrictedOverscanScreenHeight;
    399     // The current size of the screen; these may be different than (0,0)-(dw,dh)
    400     // if the status bar can't be hidden; in that case it effectively carves out
    401     // that area of the display from all other windows.
    402     int mRestrictedScreenLeft, mRestrictedScreenTop;
    403     int mRestrictedScreenWidth, mRestrictedScreenHeight;
    404     // During layout, the current screen borders accounting for any currently
    405     // visible system UI elements.
    406     int mSystemLeft, mSystemTop, mSystemRight, mSystemBottom;
    407     // For applications requesting stable content insets, these are them.
    408     int mStableLeft, mStableTop, mStableRight, mStableBottom;
    409     // For applications requesting stable content insets but have also set the
    410     // fullscreen window flag, these are the stable dimensions without the status bar.
    411     int mStableFullscreenLeft, mStableFullscreenTop;
    412     int mStableFullscreenRight, mStableFullscreenBottom;
    413     // During layout, the current screen borders with all outer decoration
    414     // (status bar, input method dock) accounted for.
    415     int mCurLeft, mCurTop, mCurRight, mCurBottom;
    416     // During layout, the frame in which content should be displayed
    417     // to the user, accounting for all screen decoration except for any
    418     // space they deem as available for other content.  This is usually
    419     // the same as mCur*, but may be larger if the screen decor has supplied
    420     // content insets.
    421     int mContentLeft, mContentTop, mContentRight, mContentBottom;
    422     // During layout, the frame in which voice content should be displayed
    423     // to the user, accounting for all screen decoration except for any
    424     // space they deem as available for other content.
    425     int mVoiceContentLeft, mVoiceContentTop, mVoiceContentRight, mVoiceContentBottom;
    426     // During layout, the current screen borders along which input method
    427     // windows are placed.
    428     int mDockLeft, mDockTop, mDockRight, mDockBottom;
    429     // During layout, the layer at which the doc window is placed.
    430     int mDockLayer;
    431     // During layout, this is the layer of the status bar.
    432     int mStatusBarLayer;
    433     int mLastSystemUiFlags;
    434     // Bits that we are in the process of clearing, so we want to prevent
    435     // them from being set by applications until everything has been updated
    436     // to have them clear.
    437     int mResettingSystemUiFlags = 0;
    438     // Bits that we are currently always keeping cleared.
    439     int mForceClearedSystemUiFlags = 0;
    440     // What we last reported to system UI about whether the compatibility
    441     // menu needs to be displayed.
    442     boolean mLastFocusNeedsMenu = false;
    443 
    444     FakeWindow mHideNavFakeWindow = null;
    445 
    446     static final Rect mTmpParentFrame = new Rect();
    447     static final Rect mTmpDisplayFrame = new Rect();
    448     static final Rect mTmpOverscanFrame = new Rect();
    449     static final Rect mTmpContentFrame = new Rect();
    450     static final Rect mTmpVisibleFrame = new Rect();
    451     static final Rect mTmpDecorFrame = new Rect();
    452     static final Rect mTmpStableFrame = new Rect();
    453     static final Rect mTmpNavigationFrame = new Rect();
    454 
    455     WindowState mTopFullscreenOpaqueWindowState;
    456     HashSet<IApplicationToken> mAppsToBeHidden = new HashSet<IApplicationToken>();
    457     HashSet<IApplicationToken> mAppsThatDismissKeyguard = new HashSet<IApplicationToken>();
    458     boolean mTopIsFullscreen;
    459     boolean mForceStatusBar;
    460     boolean mForceStatusBarFromKeyguard;
    461     boolean mHideLockScreen;
    462     boolean mForcingShowNavBar;
    463     int mForcingShowNavBarLayer;
    464 
    465     // States of keyguard dismiss.
    466     private static final int DISMISS_KEYGUARD_NONE = 0; // Keyguard not being dismissed.
    467     private static final int DISMISS_KEYGUARD_START = 1; // Keyguard needs to be dismissed.
    468     private static final int DISMISS_KEYGUARD_CONTINUE = 2; // Keyguard has been dismissed.
    469     int mDismissKeyguard = DISMISS_KEYGUARD_NONE;
    470 
    471     /** The window that is currently dismissing the keyguard. Dismissing the keyguard must only
    472      * be done once per window. */
    473     private WindowState mWinDismissingKeyguard;
    474 
    475     /** The window that is currently showing "over" the keyguard. If there is an app window
    476      * belonging to another app on top of this the keyguard shows. If there is a fullscreen
    477      * app window under this, still dismiss the keyguard but don't show the app underneath. Show
    478      * the wallpaper. */
    479     private WindowState mWinShowWhenLocked;
    480 
    481     boolean mShowingLockscreen;
    482     boolean mShowingDream;
    483     boolean mDreamingLockscreen;
    484     boolean mKeyguardSecure;
    485     boolean mKeyguardSecureIncludingHidden;
    486     volatile boolean mKeyguardOccluded;
    487     boolean mHomePressed;
    488     boolean mHomeConsumed;
    489     boolean mHomeDoubleTapPending;
    490     Intent mHomeIntent;
    491     Intent mCarDockIntent;
    492     Intent mDeskDockIntent;
    493     boolean mSearchKeyShortcutPending;
    494     boolean mConsumeSearchKeyUp;
    495     boolean mAssistKeyLongPressed;
    496     boolean mPendingMetaAction;
    497 
    498     // support for activating the lock screen while the screen is on
    499     boolean mAllowLockscreenWhenOn;
    500     int mLockScreenTimeout;
    501     boolean mLockScreenTimerActive;
    502 
    503     // Behavior of ENDCALL Button.  (See Settings.System.END_BUTTON_BEHAVIOR.)
    504     int mEndcallBehavior;
    505 
    506     // Behavior of POWER button while in-call and screen on.
    507     // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
    508     int mIncallPowerBehavior;
    509 
    510     Display mDisplay;
    511 
    512     int mLandscapeRotation = 0;  // default landscape rotation
    513     int mSeascapeRotation = 0;   // "other" landscape rotation, 180 degrees from mLandscapeRotation
    514     int mPortraitRotation = 0;   // default portrait rotation
    515     int mUpsideDownRotation = 0; // "other" portrait rotation
    516 
    517     int mOverscanLeft = 0;
    518     int mOverscanTop = 0;
    519     int mOverscanRight = 0;
    520     int mOverscanBottom = 0;
    521 
    522     // What we do when the user long presses on home
    523     private int mLongPressOnHomeBehavior;
    524 
    525     // What we do when the user double-taps on home
    526     private int mDoubleTapOnHomeBehavior;
    527 
    528     // Allowed theater mode wake actions
    529     private boolean mAllowTheaterModeWakeFromKey;
    530     private boolean mAllowTheaterModeWakeFromPowerKey;
    531     private boolean mAllowTheaterModeWakeFromMotion;
    532     private boolean mAllowTheaterModeWakeFromMotionWhenNotDreaming;
    533     private boolean mAllowTheaterModeWakeFromCameraLens;
    534     private boolean mAllowTheaterModeWakeFromLidSwitch;
    535     private boolean mAllowTheaterModeWakeFromWakeGesture;
    536 
    537     // Whether to go to sleep entering theater mode from power button
    538     private boolean mGoToSleepOnButtonPressTheaterMode;
    539 
    540     // Screenshot trigger states
    541     // Time to volume and power must be pressed within this interval of each other.
    542     private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
    543     // Increase the chord delay when taking a screenshot from the keyguard
    544     private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f;
    545     private boolean mScreenshotChordEnabled;
    546     private boolean mScreenshotChordVolumeDownKeyTriggered;
    547     private long mScreenshotChordVolumeDownKeyTime;
    548     private boolean mScreenshotChordVolumeDownKeyConsumed;
    549     private boolean mScreenshotChordVolumeUpKeyTriggered;
    550     private boolean mScreenshotChordPowerKeyTriggered;
    551     private long mScreenshotChordPowerKeyTime;
    552 
    553     /* The number of steps between min and max brightness */
    554     private static final int BRIGHTNESS_STEPS = 10;
    555 
    556     SettingsObserver mSettingsObserver;
    557     ShortcutManager mShortcutManager;
    558     PowerManager.WakeLock mBroadcastWakeLock;
    559     PowerManager.WakeLock mPowerKeyWakeLock;
    560     boolean mHavePendingMediaKeyRepeatWithWakeLock;
    561 
    562     private int mCurrentUserId;
    563 
    564     // Maps global key codes to the components that will handle them.
    565     private GlobalKeyManager mGlobalKeyManager;
    566 
    567     // Fallback actions by key code.
    568     private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions =
    569             new SparseArray<KeyCharacterMap.FallbackAction>();
    570 
    571     private final LogDecelerateInterpolator mLogDecelerateInterpolator
    572             = new LogDecelerateInterpolator(100, 0);
    573 
    574     private static final int MSG_ENABLE_POINTER_LOCATION = 1;
    575     private static final int MSG_DISABLE_POINTER_LOCATION = 2;
    576     private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
    577     private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
    578     private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
    579     private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6;
    580     private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7;
    581     private static final int MSG_DISPATCH_SHOW_RECENTS = 9;
    582     private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10;
    583     private static final int MSG_HIDE_BOOT_MESSAGE = 11;
    584     private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12;
    585     private static final int MSG_POWER_DELAYED_PRESS = 13;
    586     private static final int MSG_POWER_LONG_PRESS = 14;
    587 
    588     private class PolicyHandler extends Handler {
    589         @Override
    590         public void handleMessage(Message msg) {
    591             switch (msg.what) {
    592                 case MSG_ENABLE_POINTER_LOCATION:
    593                     enablePointerLocation();
    594                     break;
    595                 case MSG_DISABLE_POINTER_LOCATION:
    596                     disablePointerLocation();
    597                     break;
    598                 case MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK:
    599                     dispatchMediaKeyWithWakeLock((KeyEvent)msg.obj);
    600                     break;
    601                 case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK:
    602                     dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj);
    603                     break;
    604                 case MSG_DISPATCH_SHOW_RECENTS:
    605                     showRecentApps(false);
    606                     break;
    607                 case MSG_DISPATCH_SHOW_GLOBAL_ACTIONS:
    608                     showGlobalActionsInternal();
    609                     break;
    610                 case MSG_KEYGUARD_DRAWN_COMPLETE:
    611                     if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete");
    612                     finishKeyguardDrawn();
    613                     break;
    614                 case MSG_KEYGUARD_DRAWN_TIMEOUT:
    615                     Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete");
    616                     finishKeyguardDrawn();
    617                     break;
    618                 case MSG_WINDOW_MANAGER_DRAWN_COMPLETE:
    619                     if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete");
    620                     finishWindowsDrawn();
    621                     break;
    622                 case MSG_HIDE_BOOT_MESSAGE:
    623                     handleHideBootMessage();
    624                     break;
    625                 case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK:
    626                     launchVoiceAssistWithWakeLock(msg.arg1 != 0);
    627                     break;
    628                 case MSG_POWER_DELAYED_PRESS:
    629                     powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2);
    630                     finishPowerKeyPress();
    631                     break;
    632                 case MSG_POWER_LONG_PRESS:
    633                     powerLongPress();
    634                     break;
    635             }
    636         }
    637     }
    638 
    639     private UEventObserver mHDMIObserver = new UEventObserver() {
    640         @Override
    641         public void onUEvent(UEventObserver.UEvent event) {
    642             setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
    643         }
    644     };
    645 
    646     class SettingsObserver extends ContentObserver {
    647         SettingsObserver(Handler handler) {
    648             super(handler);
    649         }
    650 
    651         void observe() {
    652             // Observe all users' changes
    653             ContentResolver resolver = mContext.getContentResolver();
    654             resolver.registerContentObserver(Settings.System.getUriFor(
    655                     Settings.System.END_BUTTON_BEHAVIOR), false, this,
    656                     UserHandle.USER_ALL);
    657             resolver.registerContentObserver(Settings.Secure.getUriFor(
    658                     Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this,
    659                     UserHandle.USER_ALL);
    660             resolver.registerContentObserver(Settings.Secure.getUriFor(
    661                     Settings.Secure.WAKE_GESTURE_ENABLED), false, this,
    662                     UserHandle.USER_ALL);
    663             resolver.registerContentObserver(Settings.System.getUriFor(
    664                     Settings.System.ACCELEROMETER_ROTATION), false, this,
    665                     UserHandle.USER_ALL);
    666             resolver.registerContentObserver(Settings.System.getUriFor(
    667                     Settings.System.USER_ROTATION), false, this,
    668                     UserHandle.USER_ALL);
    669             resolver.registerContentObserver(Settings.System.getUriFor(
    670                     Settings.System.SCREEN_OFF_TIMEOUT), false, this,
    671                     UserHandle.USER_ALL);
    672             resolver.registerContentObserver(Settings.System.getUriFor(
    673                     Settings.System.POINTER_LOCATION), false, this,
    674                     UserHandle.USER_ALL);
    675             resolver.registerContentObserver(Settings.Secure.getUriFor(
    676                     Settings.Secure.DEFAULT_INPUT_METHOD), false, this,
    677                     UserHandle.USER_ALL);
    678             resolver.registerContentObserver(Settings.Secure.getUriFor(
    679                     Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this,
    680                     UserHandle.USER_ALL);
    681             resolver.registerContentObserver(Settings.Global.getUriFor(
    682                     Settings.Global.POLICY_CONTROL), false, this,
    683                     UserHandle.USER_ALL);
    684             updateSettings();
    685         }
    686 
    687         @Override public void onChange(boolean selfChange) {
    688             updateSettings();
    689             updateRotation(false);
    690         }
    691     }
    692 
    693     class MyWakeGestureListener extends WakeGestureListener {
    694         MyWakeGestureListener(Context context, Handler handler) {
    695             super(context, handler);
    696         }
    697 
    698         @Override
    699         public void onWakeUp() {
    700             synchronized (mLock) {
    701                 if (shouldEnableWakeGestureLp()) {
    702                     performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
    703                     wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture);
    704                 }
    705             }
    706         }
    707     }
    708 
    709     class MyOrientationListener extends WindowOrientationListener {
    710         MyOrientationListener(Context context, Handler handler) {
    711             super(context, handler);
    712         }
    713 
    714         @Override
    715         public void onProposedRotationChanged(int rotation) {
    716             if (localLOGV) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
    717             updateRotation(false);
    718         }
    719     }
    720     MyOrientationListener mOrientationListener;
    721 
    722     private final BarController mStatusBarController = new BarController("StatusBar",
    723             View.STATUS_BAR_TRANSIENT,
    724             View.STATUS_BAR_UNHIDE,
    725             View.STATUS_BAR_TRANSLUCENT,
    726             StatusBarManager.WINDOW_STATUS_BAR,
    727             WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    728 
    729     private final BarController mNavigationBarController = new BarController("NavigationBar",
    730             View.NAVIGATION_BAR_TRANSIENT,
    731             View.NAVIGATION_BAR_UNHIDE,
    732             View.NAVIGATION_BAR_TRANSLUCENT,
    733             StatusBarManager.WINDOW_NAVIGATION_BAR,
    734             WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
    735 
    736     private ImmersiveModeConfirmation mImmersiveModeConfirmation;
    737 
    738     private SystemGesturesPointerEventListener mSystemGestures;
    739 
    740     IStatusBarService getStatusBarService() {
    741         synchronized (mServiceAquireLock) {
    742             if (mStatusBarService == null) {
    743                 mStatusBarService = IStatusBarService.Stub.asInterface(
    744                         ServiceManager.getService("statusbar"));
    745             }
    746             return mStatusBarService;
    747         }
    748     }
    749 
    750     /*
    751      * We always let the sensor be switched on by default except when
    752      * the user has explicitly disabled sensor based rotation or when the
    753      * screen is switched off.
    754      */
    755     boolean needSensorRunningLp() {
    756         if (mSupportAutoRotation) {
    757             if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
    758                     || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
    759                     || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
    760                     || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
    761                 // If the application has explicitly requested to follow the
    762                 // orientation, then we need to turn the sensor on.
    763                 return true;
    764             }
    765         }
    766         if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
    767                 (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
    768                         || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
    769                         || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
    770             // enable accelerometer if we are docked in a dock that enables accelerometer
    771             // orientation management,
    772             return true;
    773         }
    774         if (mUserRotationMode == USER_ROTATION_LOCKED) {
    775             // If the setting for using the sensor by default is enabled, then
    776             // we will always leave it on.  Note that the user could go to
    777             // a window that forces an orientation that does not use the
    778             // sensor and in theory we could turn it off... however, when next
    779             // turning it on we won't have a good value for the current
    780             // orientation for a little bit, which can cause orientation
    781             // changes to lag, so we'd like to keep it always on.  (It will
    782             // still be turned off when the screen is off.)
    783             return false;
    784         }
    785         return mSupportAutoRotation;
    786     }
    787 
    788     /*
    789      * Various use cases for invoking this function
    790      * screen turning off, should always disable listeners if already enabled
    791      * screen turned on and current app has sensor based orientation, enable listeners
    792      * if not already enabled
    793      * screen turned on and current app does not have sensor orientation, disable listeners if
    794      * already enabled
    795      * screen turning on and current app has sensor based orientation, enable listeners if needed
    796      * screen turning on and current app has nosensor based orientation, do nothing
    797      */
    798     void updateOrientationListenerLp() {
    799         if (!mOrientationListener.canDetectOrientation()) {
    800             // If sensor is turned off or nonexistent for some reason
    801             return;
    802         }
    803         //Could have been invoked due to screen turning on or off or
    804         //change of the currently visible window's orientation
    805         if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly
    806                 + ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation
    807                 + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled);
    808         boolean disable = true;
    809         if (mScreenOnEarly && mAwake) {
    810             if (needSensorRunningLp()) {
    811                 disable = false;
    812                 //enable listener if not already enabled
    813                 if (!mOrientationSensorEnabled) {
    814                     mOrientationListener.enable();
    815                     if(localLOGV) Slog.v(TAG, "Enabling listeners");
    816                     mOrientationSensorEnabled = true;
    817                 }
    818             }
    819         }
    820         //check if sensors need to be disabled
    821         if (disable && mOrientationSensorEnabled) {
    822             mOrientationListener.disable();
    823             if(localLOGV) Slog.v(TAG, "Disabling listeners");
    824             mOrientationSensorEnabled = false;
    825         }
    826     }
    827 
    828     private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
    829         // Hold a wake lock until the power key is released.
    830         if (!mPowerKeyWakeLock.isHeld()) {
    831             mPowerKeyWakeLock.acquire();
    832         }
    833 
    834         // Cancel multi-press detection timeout.
    835         if (mPowerKeyPressCounter != 0) {
    836             mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);
    837         }
    838 
    839         // Detect user pressing the power button in panic when an application has
    840         // taken over the whole screen.
    841         boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
    842                 event.getDownTime(), isImmersiveMode(mLastSystemUiFlags));
    843         if (panic) {
    844             mHandler.post(mRequestTransientNav);
    845         }
    846 
    847         // Latch power key state to detect screenshot chord.
    848         if (interactive && !mScreenshotChordPowerKeyTriggered
    849                 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
    850             mScreenshotChordPowerKeyTriggered = true;
    851             mScreenshotChordPowerKeyTime = event.getDownTime();
    852             interceptScreenshotChord();
    853         }
    854 
    855         // Stop ringing or end call if configured to do so when power is pressed.
    856         TelecomManager telecomManager = getTelecommService();
    857         boolean hungUp = false;
    858         if (telecomManager != null) {
    859             if (telecomManager.isRinging()) {
    860                 // Pressing Power while there's a ringing incoming
    861                 // call should silence the ringer.
    862                 telecomManager.silenceRinger();
    863             } else if ((mIncallPowerBehavior
    864                     & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
    865                     && telecomManager.isInCall() && interactive) {
    866                 // Otherwise, if "Power button ends call" is enabled,
    867                 // the Power button will hang up any current active call.
    868                 hungUp = telecomManager.endCall();
    869             }
    870         }
    871 
    872         // If the power key has still not yet been handled, then detect short
    873         // press, long press, or multi press and decide what to do.
    874         mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
    875                 || mScreenshotChordVolumeUpKeyTriggered;
    876         if (!mPowerKeyHandled) {
    877             if (interactive) {
    878                 // When interactive, we're already awake.
    879                 // Wait for a long press or for the button to be released to decide what to do.
    880                 if (hasLongPressOnPowerBehavior()) {
    881                     Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
    882                     msg.setAsynchronous(true);
    883                     mHandler.sendMessageDelayed(msg,
    884                             ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
    885                 }
    886             } else {
    887                 wakeUpFromPowerKey(event.getDownTime());
    888                 final int maxCount = getMaxMultiPressPowerCount();
    889 
    890                 if (maxCount <= 1) {
    891                     mPowerKeyHandled = true;
    892                 } else {
    893                     mBeganFromNonInteractive = true;
    894                 }
    895             }
    896         }
    897     }
    898 
    899     private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
    900         final boolean handled = canceled || mPowerKeyHandled;
    901         mScreenshotChordPowerKeyTriggered = false;
    902         cancelPendingScreenshotChordAction();
    903         cancelPendingPowerKeyAction();
    904 
    905         if (!handled) {
    906             // Figure out how to handle the key now that it has been released.
    907             mPowerKeyPressCounter += 1;
    908 
    909             final int maxCount = getMaxMultiPressPowerCount();
    910             final long eventTime = event.getDownTime();
    911             if (mPowerKeyPressCounter < maxCount) {
    912                 // This could be a multi-press.  Wait a little bit longer to confirm.
    913                 // Continue holding the wake lock.
    914                 Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
    915                         interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
    916                 msg.setAsynchronous(true);
    917                 mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
    918                 return;
    919             }
    920 
    921             // No other actions.  Handle it immediately.
    922             powerPress(eventTime, interactive, mPowerKeyPressCounter);
    923         }
    924 
    925         // Done.  Reset our state.
    926         finishPowerKeyPress();
    927     }
    928 
    929     private void finishPowerKeyPress() {
    930         mBeganFromNonInteractive = false;
    931         mPowerKeyPressCounter = 0;
    932         if (mPowerKeyWakeLock.isHeld()) {
    933             mPowerKeyWakeLock.release();
    934         }
    935     }
    936 
    937     private void cancelPendingPowerKeyAction() {
    938         if (!mPowerKeyHandled) {
    939             mPowerKeyHandled = true;
    940             mHandler.removeMessages(MSG_POWER_LONG_PRESS);
    941         }
    942     }
    943 
    944     private void powerPress(long eventTime, boolean interactive, int count) {
    945         if (mScreenOnEarly && !mScreenOnFully) {
    946             Slog.i(TAG, "Suppressed redundant power key press while "
    947                     + "already in the process of turning the screen on.");
    948             return;
    949         }
    950 
    951         if (count == 2) {
    952             powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
    953         } else if (count == 3) {
    954             powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
    955         } else if (interactive && !mBeganFromNonInteractive) {
    956             switch (mShortPressOnPowerBehavior) {
    957                 case SHORT_PRESS_POWER_NOTHING:
    958                     break;
    959                 case SHORT_PRESS_POWER_GO_TO_SLEEP:
    960                     mPowerManager.goToSleep(eventTime,
    961                             PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
    962                     break;
    963                 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
    964                     mPowerManager.goToSleep(eventTime,
    965                             PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
    966                             PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
    967                     break;
    968                 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
    969                     mPowerManager.goToSleep(eventTime,
    970                             PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
    971                             PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
    972                     launchHomeFromHotKey();
    973                     break;
    974             }
    975         }
    976     }
    977 
    978     private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) {
    979         switch (behavior) {
    980             case MULTI_PRESS_POWER_NOTHING:
    981                 break;
    982             case MULTI_PRESS_POWER_THEATER_MODE:
    983                 if (isTheaterModeEnabled()) {
    984                     Slog.i(TAG, "Toggling theater mode off.");
    985                     Settings.Global.putInt(mContext.getContentResolver(),
    986                             Settings.Global.THEATER_MODE_ON, 0);
    987                     if (!interactive) {
    988                         wakeUpFromPowerKey(eventTime);
    989                     }
    990                 } else {
    991                     Slog.i(TAG, "Toggling theater mode on.");
    992                     Settings.Global.putInt(mContext.getContentResolver(),
    993                             Settings.Global.THEATER_MODE_ON, 1);
    994 
    995                     if (mGoToSleepOnButtonPressTheaterMode && interactive) {
    996                         mPowerManager.goToSleep(eventTime,
    997                                 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
    998                     }
    999                 }
   1000                 break;
   1001             case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
   1002                 Slog.i(TAG, "Starting brightness boost.");
   1003                 if (!interactive) {
   1004                     wakeUpFromPowerKey(eventTime);
   1005                 }
   1006                 mPowerManager.boostScreenBrightness(eventTime);
   1007                 break;
   1008         }
   1009     }
   1010 
   1011     private int getMaxMultiPressPowerCount() {
   1012         if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
   1013             return 3;
   1014         }
   1015         if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
   1016             return 2;
   1017         }
   1018         return 1;
   1019     }
   1020 
   1021     private void powerLongPress() {
   1022         final int behavior = getResolvedLongPressOnPowerBehavior();
   1023         switch (behavior) {
   1024         case LONG_PRESS_POWER_NOTHING:
   1025             break;
   1026         case LONG_PRESS_POWER_GLOBAL_ACTIONS:
   1027             mPowerKeyHandled = true;
   1028             if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
   1029                 performAuditoryFeedbackForAccessibilityIfNeed();
   1030             }
   1031             showGlobalActionsInternal();
   1032             break;
   1033         case LONG_PRESS_POWER_SHUT_OFF:
   1034         case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
   1035             mPowerKeyHandled = true;
   1036             performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
   1037             sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
   1038             mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
   1039             break;
   1040         }
   1041     }
   1042 
   1043     private int getResolvedLongPressOnPowerBehavior() {
   1044         if (FactoryTest.isLongPressOnPowerOffEnabled()) {
   1045             return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
   1046         }
   1047         return mLongPressOnPowerBehavior;
   1048     }
   1049 
   1050     private boolean hasLongPressOnPowerBehavior() {
   1051         return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;
   1052     }
   1053 
   1054     private void interceptScreenshotChord() {
   1055         if (mScreenshotChordEnabled
   1056                 && mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered
   1057                 && !mScreenshotChordVolumeUpKeyTriggered) {
   1058             final long now = SystemClock.uptimeMillis();
   1059             if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
   1060                     && now <= mScreenshotChordPowerKeyTime
   1061                             + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
   1062                 mScreenshotChordVolumeDownKeyConsumed = true;
   1063                 cancelPendingPowerKeyAction();
   1064 
   1065                 mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
   1066             }
   1067         }
   1068     }
   1069 
   1070     private long getScreenshotChordLongPressDelay() {
   1071         if (mKeyguardDelegate.isShowing()) {
   1072             // Double the time it takes to take a screenshot from the keyguard
   1073             return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER *
   1074                     ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
   1075         }
   1076         return ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout();
   1077     }
   1078 
   1079     private void cancelPendingScreenshotChordAction() {
   1080         mHandler.removeCallbacks(mScreenshotRunnable);
   1081     }
   1082 
   1083     private final Runnable mEndCallLongPress = new Runnable() {
   1084         @Override
   1085         public void run() {
   1086             mEndCallKeyHandled = true;
   1087             if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
   1088                 performAuditoryFeedbackForAccessibilityIfNeed();
   1089             }
   1090             showGlobalActionsInternal();
   1091         }
   1092     };
   1093 
   1094     private final Runnable mScreenshotRunnable = new Runnable() {
   1095         @Override
   1096         public void run() {
   1097             takeScreenshot();
   1098         }
   1099     };
   1100 
   1101     @Override
   1102     public void showGlobalActions() {
   1103         mHandler.removeMessages(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
   1104         mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
   1105     }
   1106 
   1107     void showGlobalActionsInternal() {
   1108         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
   1109         if (mGlobalActions == null) {
   1110             mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
   1111         }
   1112         final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();
   1113         mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
   1114         if (keyguardShowing) {
   1115             // since it took two seconds of long press to bring this up,
   1116             // poke the wake lock so they have some time to see the dialog.
   1117             mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
   1118         }
   1119     }
   1120 
   1121     boolean isDeviceProvisioned() {
   1122         return Settings.Global.getInt(
   1123                 mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
   1124     }
   1125 
   1126     boolean isUserSetupComplete() {
   1127         return Settings.Secure.getIntForUser(mContext.getContentResolver(),
   1128                 Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
   1129     }
   1130 
   1131     private void handleShortPressOnHome() {
   1132         // If there's a dream running then use home to escape the dream
   1133         // but don't actually go home.
   1134         if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) {
   1135             mDreamManagerInternal.stopDream(false /*immediate*/);
   1136             return;
   1137         }
   1138 
   1139         // Go home!
   1140         launchHomeFromHotKey();
   1141     }
   1142 
   1143     private void handleLongPressOnHome() {
   1144         if (mLongPressOnHomeBehavior != LONG_PRESS_HOME_NOTHING) {
   1145             mHomeConsumed = true;
   1146             performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
   1147 
   1148             if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
   1149                 toggleRecentApps();
   1150             } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_ASSIST) {
   1151                 launchAssistAction();
   1152             }
   1153         }
   1154     }
   1155 
   1156     private void handleDoubleTapOnHome() {
   1157         if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
   1158             mHomeConsumed = true;
   1159             toggleRecentApps();
   1160         }
   1161     }
   1162 
   1163     private final Runnable mHomeDoubleTapTimeoutRunnable = new Runnable() {
   1164         @Override
   1165         public void run() {
   1166             if (mHomeDoubleTapPending) {
   1167                 mHomeDoubleTapPending = false;
   1168                 handleShortPressOnHome();
   1169             }
   1170         }
   1171     };
   1172 
   1173     /** {@inheritDoc} */
   1174     @Override
   1175     public void init(Context context, IWindowManager windowManager,
   1176             WindowManagerFuncs windowManagerFuncs) {
   1177         mContext = context;
   1178         mWindowManager = windowManager;
   1179         mWindowManagerFuncs = windowManagerFuncs;
   1180         mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
   1181         mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
   1182 
   1183         mHandler = new PolicyHandler();
   1184         mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
   1185         mOrientationListener = new MyOrientationListener(mContext, mHandler);
   1186         try {
   1187             mOrientationListener.setCurrentRotation(windowManager.getRotation());
   1188         } catch (RemoteException ex) { }
   1189         mSettingsObserver = new SettingsObserver(mHandler);
   1190         mSettingsObserver.observe();
   1191         mShortcutManager = new ShortcutManager(context, mHandler);
   1192         mShortcutManager.observe();
   1193         mUiMode = context.getResources().getInteger(
   1194                 com.android.internal.R.integer.config_defaultUiModeType);
   1195         mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
   1196         mHomeIntent.addCategory(Intent.CATEGORY_HOME);
   1197         mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
   1198                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
   1199         mCarDockIntent =  new Intent(Intent.ACTION_MAIN, null);
   1200         mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
   1201         mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
   1202                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
   1203         mDeskDockIntent =  new Intent(Intent.ACTION_MAIN, null);
   1204         mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
   1205         mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
   1206                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
   1207 
   1208         mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
   1209         mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
   1210                 "PhoneWindowManager.mBroadcastWakeLock");
   1211         mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
   1212                 "PhoneWindowManager.mPowerKeyWakeLock");
   1213         mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
   1214         mSupportAutoRotation = mContext.getResources().getBoolean(
   1215                 com.android.internal.R.bool.config_supportAutoRotation);
   1216         mLidOpenRotation = readRotation(
   1217                 com.android.internal.R.integer.config_lidOpenRotation);
   1218         mCarDockRotation = readRotation(
   1219                 com.android.internal.R.integer.config_carDockRotation);
   1220         mDeskDockRotation = readRotation(
   1221                 com.android.internal.R.integer.config_deskDockRotation);
   1222         mUndockedHdmiRotation = readRotation(
   1223                 com.android.internal.R.integer.config_undockedHdmiRotation);
   1224         mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
   1225                 com.android.internal.R.bool.config_carDockEnablesAccelerometer);
   1226         mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
   1227                 com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
   1228         mLidKeyboardAccessibility = mContext.getResources().getInteger(
   1229                 com.android.internal.R.integer.config_lidKeyboardAccessibility);
   1230         mLidNavigationAccessibility = mContext.getResources().getInteger(
   1231                 com.android.internal.R.integer.config_lidNavigationAccessibility);
   1232         mLidControlsSleep = mContext.getResources().getBoolean(
   1233                 com.android.internal.R.bool.config_lidControlsSleep);
   1234         mTranslucentDecorEnabled = mContext.getResources().getBoolean(
   1235                 com.android.internal.R.bool.config_enableTranslucentDecor);
   1236 
   1237         mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
   1238                 com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
   1239         mAllowTheaterModeWakeFromPowerKey = mAllowTheaterModeWakeFromKey
   1240                 || mContext.getResources().getBoolean(
   1241                     com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey);
   1242         mAllowTheaterModeWakeFromMotion = mContext.getResources().getBoolean(
   1243                 com.android.internal.R.bool.config_allowTheaterModeWakeFromMotion);
   1244         mAllowTheaterModeWakeFromMotionWhenNotDreaming = mContext.getResources().getBoolean(
   1245                 com.android.internal.R.bool.config_allowTheaterModeWakeFromMotionWhenNotDreaming);
   1246         mAllowTheaterModeWakeFromCameraLens = mContext.getResources().getBoolean(
   1247                 com.android.internal.R.bool.config_allowTheaterModeWakeFromCameraLens);
   1248         mAllowTheaterModeWakeFromLidSwitch = mContext.getResources().getBoolean(
   1249                 com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch);
   1250         mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean(
   1251                 com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture);
   1252 
   1253         mGoToSleepOnButtonPressTheaterMode = mContext.getResources().getBoolean(
   1254                 com.android.internal.R.bool.config_goToSleepOnButtonPressTheaterMode);
   1255 
   1256         mShortPressOnPowerBehavior = mContext.getResources().getInteger(
   1257                 com.android.internal.R.integer.config_shortPressOnPowerBehavior);
   1258         mLongPressOnPowerBehavior = mContext.getResources().getInteger(
   1259                 com.android.internal.R.integer.config_longPressOnPowerBehavior);
   1260         mDoublePressOnPowerBehavior = mContext.getResources().getInteger(
   1261                 com.android.internal.R.integer.config_doublePressOnPowerBehavior);
   1262         mTriplePressOnPowerBehavior = mContext.getResources().getInteger(
   1263                 com.android.internal.R.integer.config_triplePressOnPowerBehavior);
   1264 
   1265         readConfigurationDependentBehaviors();
   1266 
   1267         mAccessibilityManager = (AccessibilityManager) context.getSystemService(
   1268                 Context.ACCESSIBILITY_SERVICE);
   1269 
   1270         // register for dock events
   1271         IntentFilter filter = new IntentFilter();
   1272         filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
   1273         filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
   1274         filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
   1275         filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
   1276         filter.addAction(Intent.ACTION_DOCK_EVENT);
   1277         Intent intent = context.registerReceiver(mDockReceiver, filter);
   1278         if (intent != null) {
   1279             // Retrieve current sticky dock event broadcast.
   1280             mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
   1281                     Intent.EXTRA_DOCK_STATE_UNDOCKED);
   1282         }
   1283 
   1284         // register for dream-related broadcasts
   1285         filter = new IntentFilter();
   1286         filter.addAction(Intent.ACTION_DREAMING_STARTED);
   1287         filter.addAction(Intent.ACTION_DREAMING_STOPPED);
   1288         context.registerReceiver(mDreamReceiver, filter);
   1289 
   1290         // register for multiuser-relevant broadcasts
   1291         filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
   1292         context.registerReceiver(mMultiuserReceiver, filter);
   1293 
   1294         // monitor for system gestures
   1295         mSystemGestures = new SystemGesturesPointerEventListener(context,
   1296                 new SystemGesturesPointerEventListener.Callbacks() {
   1297                     @Override
   1298                     public void onSwipeFromTop() {
   1299                         if (mStatusBar != null) {
   1300                             requestTransientBars(mStatusBar);
   1301                         }
   1302                     }
   1303                     @Override
   1304                     public void onSwipeFromBottom() {
   1305                         if (mNavigationBar != null && mNavigationBarOnBottom) {
   1306                             requestTransientBars(mNavigationBar);
   1307                         }
   1308                     }
   1309                     @Override
   1310                     public void onSwipeFromRight() {
   1311                         if (mNavigationBar != null && !mNavigationBarOnBottom) {
   1312                             requestTransientBars(mNavigationBar);
   1313                         }
   1314                     }
   1315                     @Override
   1316                     public void onDebug() {
   1317                         // no-op
   1318                     }
   1319                 });
   1320         mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext);
   1321         mWindowManagerFuncs.registerPointerEventListener(mSystemGestures);
   1322 
   1323         mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
   1324         mLongPressVibePattern = getLongIntArray(mContext.getResources(),
   1325                 com.android.internal.R.array.config_longPressVibePattern);
   1326         mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(),
   1327                 com.android.internal.R.array.config_virtualKeyVibePattern);
   1328         mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(),
   1329                 com.android.internal.R.array.config_keyboardTapVibePattern);
   1330         mClockTickVibePattern = getLongIntArray(mContext.getResources(),
   1331                 com.android.internal.R.array.config_clockTickVibePattern);
   1332         mCalendarDateVibePattern = getLongIntArray(mContext.getResources(),
   1333                 com.android.internal.R.array.config_calendarDateVibePattern);
   1334         mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
   1335                 com.android.internal.R.array.config_safeModeDisabledVibePattern);
   1336         mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
   1337                 com.android.internal.R.array.config_safeModeEnabledVibePattern);
   1338 
   1339         mScreenshotChordEnabled = mContext.getResources().getBoolean(
   1340                 com.android.internal.R.bool.config_enableScreenshotChord);
   1341 
   1342         mGlobalKeyManager = new GlobalKeyManager(mContext);
   1343 
   1344         // Controls rotation and the like.
   1345         initializeHdmiState();
   1346 
   1347         // Match current screen state.
   1348         if (!mPowerManager.isInteractive()) {
   1349             goingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
   1350         }
   1351     }
   1352 
   1353     /**
   1354      * Read values from config.xml that may be overridden depending on
   1355      * the configuration of the device.
   1356      * eg. Disable long press on home goes to recents on sw600dp.
   1357      */
   1358     private void readConfigurationDependentBehaviors() {
   1359         mLongPressOnHomeBehavior = mContext.getResources().getInteger(
   1360                 com.android.internal.R.integer.config_longPressOnHomeBehavior);
   1361         if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||
   1362                 mLongPressOnHomeBehavior > LONG_PRESS_HOME_ASSIST) {
   1363             mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
   1364         }
   1365 
   1366         mDoubleTapOnHomeBehavior = mContext.getResources().getInteger(
   1367                 com.android.internal.R.integer.config_doubleTapOnHomeBehavior);
   1368         if (mDoubleTapOnHomeBehavior < DOUBLE_TAP_HOME_NOTHING ||
   1369                 mDoubleTapOnHomeBehavior > DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
   1370             mDoubleTapOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
   1371         }
   1372     }
   1373 
   1374     @Override
   1375     public void setInitialDisplaySize(Display display, int width, int height, int density) {
   1376         // This method might be called before the policy has been fully initialized
   1377         // or for other displays we don't care about.
   1378         if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) {
   1379             return;
   1380         }
   1381         mDisplay = display;
   1382 
   1383         final Resources res = mContext.getResources();
   1384         int shortSize, longSize;
   1385         if (width > height) {
   1386             shortSize = height;
   1387             longSize = width;
   1388             mLandscapeRotation = Surface.ROTATION_0;
   1389             mSeascapeRotation = Surface.ROTATION_180;
   1390             if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
   1391                 mPortraitRotation = Surface.ROTATION_90;
   1392                 mUpsideDownRotation = Surface.ROTATION_270;
   1393             } else {
   1394                 mPortraitRotation = Surface.ROTATION_270;
   1395                 mUpsideDownRotation = Surface.ROTATION_90;
   1396             }
   1397         } else {
   1398             shortSize = width;
   1399             longSize = height;
   1400             mPortraitRotation = Surface.ROTATION_0;
   1401             mUpsideDownRotation = Surface.ROTATION_180;
   1402             if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
   1403                 mLandscapeRotation = Surface.ROTATION_270;
   1404                 mSeascapeRotation = Surface.ROTATION_90;
   1405             } else {
   1406                 mLandscapeRotation = Surface.ROTATION_90;
   1407                 mSeascapeRotation = Surface.ROTATION_270;
   1408             }
   1409         }
   1410 
   1411         mStatusBarHeight =
   1412                 res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
   1413 
   1414         // Height of the navigation bar when presented horizontally at bottom
   1415         mNavigationBarHeightForRotation[mPortraitRotation] =
   1416         mNavigationBarHeightForRotation[mUpsideDownRotation] =
   1417                 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
   1418         mNavigationBarHeightForRotation[mLandscapeRotation] =
   1419         mNavigationBarHeightForRotation[mSeascapeRotation] = res.getDimensionPixelSize(
   1420                 com.android.internal.R.dimen.navigation_bar_height_landscape);
   1421 
   1422         // Width of the navigation bar when presented vertically along one side
   1423         mNavigationBarWidthForRotation[mPortraitRotation] =
   1424         mNavigationBarWidthForRotation[mUpsideDownRotation] =
   1425         mNavigationBarWidthForRotation[mLandscapeRotation] =
   1426         mNavigationBarWidthForRotation[mSeascapeRotation] =
   1427                 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
   1428 
   1429         // SystemUI (status bar) layout policy
   1430         int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
   1431         int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
   1432 
   1433         // Allow the navigation bar to move on small devices (phones).
   1434         mNavigationBarCanMove = shortSizeDp < 600;
   1435 
   1436         mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
   1437         // Allow a system property to override this. Used by the emulator.
   1438         // See also hasNavigationBar().
   1439         String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
   1440         if ("1".equals(navBarOverride)) {
   1441             mHasNavigationBar = false;
   1442         } else if ("0".equals(navBarOverride)) {
   1443             mHasNavigationBar = true;
   1444         }
   1445 
   1446         // For demo purposes, allow the rotation of the HDMI display to be controlled.
   1447         // By default, HDMI locks rotation to landscape.
   1448         if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
   1449             mDemoHdmiRotation = mPortraitRotation;
   1450         } else {
   1451             mDemoHdmiRotation = mLandscapeRotation;
   1452         }
   1453         mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
   1454 
   1455         // For demo purposes, allow the rotation of the remote display to be controlled.
   1456         // By default, remote display locks rotation to landscape.
   1457         if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
   1458             mDemoRotation = mPortraitRotation;
   1459         } else {
   1460             mDemoRotation = mLandscapeRotation;
   1461         }
   1462         mDemoRotationLock = SystemProperties.getBoolean(
   1463                 "persist.demo.rotationlock", false);
   1464 
   1465         // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
   1466         // http://developer.android.com/guide/practices/screens_support.html#range
   1467         mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 &&
   1468                 res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
   1469                 // For debug purposes the next line turns this feature off with:
   1470                 // $ adb shell setprop config.override_forced_orient true
   1471                 // $ adb shell wm size reset
   1472                 !"true".equals(SystemProperties.get("config.override_forced_orient"));
   1473     }
   1474 
   1475     /**
   1476      * @return whether the navigation bar can be hidden, e.g. the device has a
   1477      *         navigation bar and touch exploration is not enabled
   1478      */
   1479     private boolean canHideNavigationBar() {
   1480         return mHasNavigationBar
   1481                 && !mAccessibilityManager.isTouchExplorationEnabled();
   1482     }
   1483 
   1484     @Override
   1485     public boolean isDefaultOrientationForced() {
   1486         return mForceDefaultOrientation;
   1487     }
   1488 
   1489     @Override
   1490     public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) {
   1491         if (display.getDisplayId() == Display.DEFAULT_DISPLAY) {
   1492             mOverscanLeft = left;
   1493             mOverscanTop = top;
   1494             mOverscanRight = right;
   1495             mOverscanBottom = bottom;
   1496         }
   1497     }
   1498 
   1499     public void updateSettings() {
   1500         ContentResolver resolver = mContext.getContentResolver();
   1501         boolean updateRotation = false;
   1502         synchronized (mLock) {
   1503             mEndcallBehavior = Settings.System.getIntForUser(resolver,
   1504                     Settings.System.END_BUTTON_BEHAVIOR,
   1505                     Settings.System.END_BUTTON_BEHAVIOR_DEFAULT,
   1506                     UserHandle.USER_CURRENT);
   1507             mIncallPowerBehavior = Settings.Secure.getIntForUser(resolver,
   1508                     Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
   1509                     Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT,
   1510                     UserHandle.USER_CURRENT);
   1511 
   1512             // Configure wake gesture.
   1513             boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver,
   1514                     Settings.Secure.WAKE_GESTURE_ENABLED, 0,
   1515                     UserHandle.USER_CURRENT) != 0;
   1516             if (mWakeGestureEnabledSetting != wakeGestureEnabledSetting) {
   1517                 mWakeGestureEnabledSetting = wakeGestureEnabledSetting;
   1518                 updateWakeGestureListenerLp();
   1519             }
   1520 
   1521             // Configure rotation lock.
   1522             int userRotation = Settings.System.getIntForUser(resolver,
   1523                     Settings.System.USER_ROTATION, Surface.ROTATION_0,
   1524                     UserHandle.USER_CURRENT);
   1525             if (mUserRotation != userRotation) {
   1526                 mUserRotation = userRotation;
   1527                 updateRotation = true;
   1528             }
   1529             int userRotationMode = Settings.System.getIntForUser(resolver,
   1530                     Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
   1531                             WindowManagerPolicy.USER_ROTATION_FREE :
   1532                                     WindowManagerPolicy.USER_ROTATION_LOCKED;
   1533             if (mUserRotationMode != userRotationMode) {
   1534                 mUserRotationMode = userRotationMode;
   1535                 updateRotation = true;
   1536                 updateOrientationListenerLp();
   1537             }
   1538 
   1539             if (mSystemReady) {
   1540                 int pointerLocation = Settings.System.getIntForUser(resolver,
   1541                         Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT);
   1542                 if (mPointerLocationMode != pointerLocation) {
   1543                     mPointerLocationMode = pointerLocation;
   1544                     mHandler.sendEmptyMessage(pointerLocation != 0 ?
   1545                             MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
   1546                 }
   1547             }
   1548             // use screen off timeout setting as the timeout for the lockscreen
   1549             mLockScreenTimeout = Settings.System.getIntForUser(resolver,
   1550                     Settings.System.SCREEN_OFF_TIMEOUT, 0, UserHandle.USER_CURRENT);
   1551             String imId = Settings.Secure.getStringForUser(resolver,
   1552                     Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.USER_CURRENT);
   1553             boolean hasSoftInput = imId != null && imId.length() > 0;
   1554             if (mHasSoftInput != hasSoftInput) {
   1555                 mHasSoftInput = hasSoftInput;
   1556                 updateRotation = true;
   1557             }
   1558             if (mImmersiveModeConfirmation != null) {
   1559                 mImmersiveModeConfirmation.loadSetting(mCurrentUserId);
   1560             }
   1561             PolicyControl.reloadFromSetting(mContext);
   1562         }
   1563         if (updateRotation) {
   1564             updateRotation(true);
   1565         }
   1566     }
   1567 
   1568     private void updateWakeGestureListenerLp() {
   1569         if (shouldEnableWakeGestureLp()) {
   1570             mWakeGestureListener.requestWakeUpTrigger();
   1571         } else {
   1572             mWakeGestureListener.cancelWakeUpTrigger();
   1573         }
   1574     }
   1575 
   1576     private boolean shouldEnableWakeGestureLp() {
   1577         return mWakeGestureEnabledSetting && !mAwake
   1578                 && (!mLidControlsSleep || mLidState != LID_CLOSED)
   1579                 && mWakeGestureListener.isSupported();
   1580     }
   1581 
   1582     private void enablePointerLocation() {
   1583         if (mPointerLocationView == null) {
   1584             mPointerLocationView = new PointerLocationView(mContext);
   1585             mPointerLocationView.setPrintCoords(false);
   1586             WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
   1587                     WindowManager.LayoutParams.MATCH_PARENT,
   1588                     WindowManager.LayoutParams.MATCH_PARENT);
   1589             lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
   1590             lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
   1591                     | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
   1592                     | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
   1593                     | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
   1594             if (ActivityManager.isHighEndGfx()) {
   1595                 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
   1596                 lp.privateFlags |=
   1597                         WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
   1598             }
   1599             lp.format = PixelFormat.TRANSLUCENT;
   1600             lp.setTitle("PointerLocation");
   1601             WindowManager wm = (WindowManager)
   1602                     mContext.getSystemService(Context.WINDOW_SERVICE);
   1603             lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
   1604             wm.addView(mPointerLocationView, lp);
   1605             mWindowManagerFuncs.registerPointerEventListener(mPointerLocationView);
   1606         }
   1607     }
   1608 
   1609     private void disablePointerLocation() {
   1610         if (mPointerLocationView != null) {
   1611             mWindowManagerFuncs.unregisterPointerEventListener(mPointerLocationView);
   1612             WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
   1613             wm.removeView(mPointerLocationView);
   1614             mPointerLocationView = null;
   1615         }
   1616     }
   1617 
   1618     private int readRotation(int resID) {
   1619         try {
   1620             int rotation = mContext.getResources().getInteger(resID);
   1621             switch (rotation) {
   1622                 case 0:
   1623                     return Surface.ROTATION_0;
   1624                 case 90:
   1625                     return Surface.ROTATION_90;
   1626                 case 180:
   1627                     return Surface.ROTATION_180;
   1628                 case 270:
   1629                     return Surface.ROTATION_270;
   1630             }
   1631         } catch (Resources.NotFoundException e) {
   1632             // fall through
   1633         }
   1634         return -1;
   1635     }
   1636 
   1637     /** {@inheritDoc} */
   1638     @Override
   1639     public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) {
   1640         int type = attrs.type;
   1641 
   1642         outAppOp[0] = AppOpsManager.OP_NONE;
   1643 
   1644         if (!((type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW)
   1645                 || (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW)
   1646                 || (type >= FIRST_SYSTEM_WINDOW && type <= LAST_SYSTEM_WINDOW))) {
   1647             return WindowManagerGlobal.ADD_INVALID_TYPE;
   1648         }
   1649 
   1650         if (type < FIRST_SYSTEM_WINDOW || type > LAST_SYSTEM_WINDOW) {
   1651             // Window manager will make sure these are okay.
   1652             return WindowManagerGlobal.ADD_OKAY;
   1653         }
   1654         String permission = null;
   1655         switch (type) {
   1656             case TYPE_TOAST:
   1657                 // XXX right now the app process has complete control over
   1658                 // this...  should introduce a token to let the system
   1659                 // monitor/control what they are doing.
   1660                 outAppOp[0] = AppOpsManager.OP_TOAST_WINDOW;
   1661                 break;
   1662             case TYPE_DREAM:
   1663             case TYPE_INPUT_METHOD:
   1664             case TYPE_WALLPAPER:
   1665             case TYPE_PRIVATE_PRESENTATION:
   1666             case TYPE_VOICE_INTERACTION:
   1667             case TYPE_ACCESSIBILITY_OVERLAY:
   1668                 // The window manager will check these.
   1669                 break;
   1670             case TYPE_PHONE:
   1671             case TYPE_PRIORITY_PHONE:
   1672             case TYPE_SYSTEM_ALERT:
   1673             case TYPE_SYSTEM_ERROR:
   1674             case TYPE_SYSTEM_OVERLAY:
   1675                 permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
   1676                 outAppOp[0] = AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
   1677                 break;
   1678             default:
   1679                 permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
   1680         }
   1681         if (permission != null) {
   1682             if (mContext.checkCallingOrSelfPermission(permission)
   1683                     != PackageManager.PERMISSION_GRANTED) {
   1684                 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
   1685             }
   1686         }
   1687         return WindowManagerGlobal.ADD_OKAY;
   1688     }
   1689 
   1690     @Override
   1691     public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) {
   1692 
   1693         // If this switch statement is modified, modify the comment in the declarations of
   1694         // the type in {@link WindowManager.LayoutParams} as well.
   1695         switch (attrs.type) {
   1696             default:
   1697                 // These are the windows that by default are shown only to the user that created
   1698                 // them. If this needs to be overridden, set
   1699                 // {@link WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS} in
   1700                 // {@link WindowManager.LayoutParams}. Note that permission
   1701                 // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well.
   1702                 if ((attrs.privateFlags & PRIVATE_FLAG_SHOW_FOR_ALL_USERS) == 0) {
   1703                     return true;
   1704                 }
   1705                 break;
   1706 
   1707             // These are the windows that by default are shown to all users. However, to
   1708             // protect against spoofing, check permissions below.
   1709             case TYPE_APPLICATION_STARTING:
   1710             case TYPE_BOOT_PROGRESS:
   1711             case TYPE_DISPLAY_OVERLAY:
   1712             case TYPE_HIDDEN_NAV_CONSUMER:
   1713             case TYPE_KEYGUARD_SCRIM:
   1714             case TYPE_KEYGUARD_DIALOG:
   1715             case TYPE_MAGNIFICATION_OVERLAY:
   1716             case TYPE_NAVIGATION_BAR:
   1717             case TYPE_NAVIGATION_BAR_PANEL:
   1718             case TYPE_PHONE:
   1719             case TYPE_POINTER:
   1720             case TYPE_PRIORITY_PHONE:
   1721             case TYPE_SEARCH_BAR:
   1722             case TYPE_STATUS_BAR:
   1723             case TYPE_STATUS_BAR_PANEL:
   1724             case TYPE_STATUS_BAR_SUB_PANEL:
   1725             case TYPE_SYSTEM_DIALOG:
   1726             case TYPE_UNIVERSE_BACKGROUND:
   1727             case TYPE_VOLUME_OVERLAY:
   1728             case TYPE_PRIVATE_PRESENTATION:
   1729                 break;
   1730         }
   1731 
   1732         // Check if third party app has set window to system window type.
   1733         return mContext.checkCallingOrSelfPermission(
   1734                 android.Manifest.permission.INTERNAL_SYSTEM_WINDOW)
   1735                         != PackageManager.PERMISSION_GRANTED;
   1736     }
   1737 
   1738     @Override
   1739     public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
   1740         switch (attrs.type) {
   1741             case TYPE_SYSTEM_OVERLAY:
   1742             case TYPE_SECURE_SYSTEM_OVERLAY:
   1743                 // These types of windows can't receive input events.
   1744                 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
   1745                         | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
   1746                 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
   1747                 break;
   1748             case TYPE_STATUS_BAR:
   1749 
   1750                 // If the Keyguard is in a hidden state (occluded by another window), we force to
   1751                 // remove the wallpaper and keyguard flag so that any change in-flight after setting
   1752                 // the keyguard as occluded wouldn't set these flags again.
   1753                 // See {@link #processKeyguardSetHiddenResultLw}.
   1754                 if (mKeyguardHidden) {
   1755                     attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
   1756                     attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
   1757                 }
   1758                 break;
   1759         }
   1760 
   1761         if (attrs.type != TYPE_STATUS_BAR) {
   1762             // The status bar is the only window allowed to exhibit keyguard behavior.
   1763             attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
   1764         }
   1765 
   1766         if (ActivityManager.isHighEndGfx()
   1767                 && (attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
   1768             attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
   1769                     | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
   1770         }
   1771     }
   1772 
   1773     void readLidState() {
   1774         mLidState = mWindowManagerFuncs.getLidState();
   1775     }
   1776 
   1777     private void readCameraLensCoverState() {
   1778         mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState();
   1779     }
   1780 
   1781     private boolean isHidden(int accessibilityMode) {
   1782         switch (accessibilityMode) {
   1783             case 1:
   1784                 return mLidState == LID_CLOSED;
   1785             case 2:
   1786                 return mLidState == LID_OPEN;
   1787             default:
   1788                 return false;
   1789         }
   1790     }
   1791 
   1792     /** {@inheritDoc} */
   1793     @Override
   1794     public void adjustConfigurationLw(Configuration config, int keyboardPresence,
   1795             int navigationPresence) {
   1796         mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0;
   1797 
   1798         readConfigurationDependentBehaviors();
   1799         readLidState();
   1800         applyLidSwitchState();
   1801 
   1802         if (config.keyboard == Configuration.KEYBOARD_NOKEYS
   1803                 || (keyboardPresence == PRESENCE_INTERNAL
   1804                         && isHidden(mLidKeyboardAccessibility))) {
   1805             config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
   1806             if (!mHasSoftInput) {
   1807                 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
   1808             }
   1809         }
   1810 
   1811         if (config.navigation == Configuration.NAVIGATION_NONAV
   1812                 || (navigationPresence == PRESENCE_INTERNAL
   1813                         && isHidden(mLidNavigationAccessibility))) {
   1814             config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
   1815         }
   1816     }
   1817 
   1818     /** {@inheritDoc} */
   1819     @Override
   1820     public int windowTypeToLayerLw(int type) {
   1821         if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
   1822             return 2;
   1823         }
   1824         switch (type) {
   1825         case TYPE_UNIVERSE_BACKGROUND:
   1826             return 1;
   1827         case TYPE_PRIVATE_PRESENTATION:
   1828             return 2;
   1829         case TYPE_WALLPAPER:
   1830             // wallpaper is at the bottom, though the window manager may move it.
   1831             return 2;
   1832         case TYPE_PHONE:
   1833             return 3;
   1834         case TYPE_SEARCH_BAR:
   1835             return 4;
   1836         case TYPE_VOICE_INTERACTION:
   1837             // voice interaction layer is almost immediately above apps.
   1838             return 5;
   1839         case TYPE_SYSTEM_DIALOG:
   1840             return 6;
   1841         case TYPE_TOAST:
   1842             // toasts and the plugged-in battery thing
   1843             return 7;
   1844         case TYPE_PRIORITY_PHONE:
   1845             // SIM errors and unlock.  Not sure if this really should be in a high layer.
   1846             return 8;
   1847         case TYPE_DREAM:
   1848             // used for Dreams (screensavers with TYPE_DREAM windows)
   1849             return 9;
   1850         case TYPE_SYSTEM_ALERT:
   1851             // like the ANR / app crashed dialogs
   1852             return 10;
   1853         case TYPE_INPUT_METHOD:
   1854             // on-screen keyboards and other such input method user interfaces go here.
   1855             return 11;
   1856         case TYPE_INPUT_METHOD_DIALOG:
   1857             // on-screen keyboards and other such input method user interfaces go here.
   1858             return 12;
   1859         case TYPE_KEYGUARD_SCRIM:
   1860             // the safety window that shows behind keyguard while keyguard is starting
   1861             return 13;
   1862         case TYPE_STATUS_BAR_SUB_PANEL:
   1863             return 14;
   1864         case TYPE_STATUS_BAR:
   1865             return 15;
   1866         case TYPE_STATUS_BAR_PANEL:
   1867             return 16;
   1868         case TYPE_KEYGUARD_DIALOG:
   1869             return 17;
   1870         case TYPE_VOLUME_OVERLAY:
   1871             // the on-screen volume indicator and controller shown when the user
   1872             // changes the device volume
   1873             return 18;
   1874         case TYPE_SYSTEM_OVERLAY:
   1875             // the on-screen volume indicator and controller shown when the user
   1876             // changes the device volume
   1877             return 19;
   1878         case TYPE_NAVIGATION_BAR:
   1879             // the navigation bar, if available, shows atop most things
   1880             return 20;
   1881         case TYPE_NAVIGATION_BAR_PANEL:
   1882             // some panels (e.g. search) need to show on top of the navigation bar
   1883             return 21;
   1884         case TYPE_SYSTEM_ERROR:
   1885             // system-level error dialogs
   1886             return 22;
   1887         case TYPE_MAGNIFICATION_OVERLAY:
   1888             // used to highlight the magnified portion of a display
   1889             return 23;
   1890         case TYPE_DISPLAY_OVERLAY:
   1891             // used to simulate secondary display devices
   1892             return 24;
   1893         case TYPE_DRAG:
   1894             // the drag layer: input for drag-and-drop is associated with this window,
   1895             // which sits above all other focusable windows
   1896             return 25;
   1897         case TYPE_ACCESSIBILITY_OVERLAY:
   1898             // overlay put by accessibility services to intercept user interaction
   1899             return 26;
   1900         case TYPE_SECURE_SYSTEM_OVERLAY:
   1901             return 27;
   1902         case TYPE_BOOT_PROGRESS:
   1903             return 28;
   1904         case TYPE_POINTER:
   1905             // the (mouse) pointer layer
   1906             return 29;
   1907         case TYPE_HIDDEN_NAV_CONSUMER:
   1908             return 30;
   1909         }
   1910         Log.e(TAG, "Unknown window type: " + type);
   1911         return 2;
   1912     }
   1913 
   1914     /** {@inheritDoc} */
   1915     @Override
   1916     public int subWindowTypeToLayerLw(int type) {
   1917         switch (type) {
   1918         case TYPE_APPLICATION_PANEL:
   1919         case TYPE_APPLICATION_ATTACHED_DIALOG:
   1920             return APPLICATION_PANEL_SUBLAYER;
   1921         case TYPE_APPLICATION_MEDIA:
   1922             return APPLICATION_MEDIA_SUBLAYER;
   1923         case TYPE_APPLICATION_MEDIA_OVERLAY:
   1924             return APPLICATION_MEDIA_OVERLAY_SUBLAYER;
   1925         case TYPE_APPLICATION_SUB_PANEL:
   1926             return APPLICATION_SUB_PANEL_SUBLAYER;
   1927         }
   1928         Log.e(TAG, "Unknown sub-window type: " + type);
   1929         return 0;
   1930     }
   1931 
   1932     @Override
   1933     public int getMaxWallpaperLayer() {
   1934         return windowTypeToLayerLw(TYPE_STATUS_BAR);
   1935     }
   1936 
   1937     @Override
   1938     public int getAboveUniverseLayer() {
   1939         return windowTypeToLayerLw(TYPE_SYSTEM_ERROR);
   1940     }
   1941 
   1942     @Override
   1943     public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation) {
   1944         if (mHasNavigationBar) {
   1945             // For a basic navigation bar, when we are in landscape mode we place
   1946             // the navigation bar to the side.
   1947             if (mNavigationBarCanMove && fullWidth > fullHeight) {
   1948                 return fullWidth - mNavigationBarWidthForRotation[rotation];
   1949             }
   1950         }
   1951         return fullWidth;
   1952     }
   1953 
   1954     @Override
   1955     public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation) {
   1956         if (mHasNavigationBar) {
   1957             // For a basic navigation bar, when we are in portrait mode we place
   1958             // the navigation bar to the bottom.
   1959             if (!mNavigationBarCanMove || fullWidth < fullHeight) {
   1960                 return fullHeight - mNavigationBarHeightForRotation[rotation];
   1961             }
   1962         }
   1963         return fullHeight;
   1964     }
   1965 
   1966     @Override
   1967     public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation) {
   1968         return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation);
   1969     }
   1970 
   1971     @Override
   1972     public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation) {
   1973         // There is a separate status bar at the top of the display.  We don't count that as part
   1974         // of the fixed decor, since it can hide; however, for purposes of configurations,
   1975         // we do want to exclude it since applications can't generally use that part
   1976         // of the screen.
   1977         return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation) - mStatusBarHeight;
   1978     }
   1979 
   1980     @Override
   1981     public boolean isForceHiding(WindowManager.LayoutParams attrs) {
   1982         return (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
   1983                 (isKeyguardHostWindow(attrs) &&
   1984                         (mKeyguardDelegate != null && mKeyguardDelegate.isShowing())) ||
   1985                 (attrs.type == TYPE_KEYGUARD_SCRIM);
   1986     }
   1987 
   1988     @Override
   1989     public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) {
   1990         return attrs.type == TYPE_STATUS_BAR;
   1991     }
   1992 
   1993     @Override
   1994     public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
   1995         switch (attrs.type) {
   1996             case TYPE_STATUS_BAR:
   1997             case TYPE_NAVIGATION_BAR:
   1998             case TYPE_WALLPAPER:
   1999             case TYPE_DREAM:
   2000             case TYPE_UNIVERSE_BACKGROUND:
   2001             case TYPE_KEYGUARD_SCRIM:
   2002                 return false;
   2003             default:
   2004                 return true;
   2005         }
   2006     }
   2007 
   2008     @Override
   2009     public WindowState getWinShowWhenLockedLw() {
   2010         return mWinShowWhenLocked;
   2011     }
   2012 
   2013     /** {@inheritDoc} */
   2014     @Override
   2015     public View addStartingWindow(IBinder appToken, String packageName, int theme,
   2016             CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
   2017             int icon, int logo, int windowFlags) {
   2018         if (!SHOW_STARTING_ANIMATIONS) {
   2019             return null;
   2020         }
   2021         if (packageName == null) {
   2022             return null;
   2023         }
   2024 
   2025         WindowManager wm = null;
   2026         View view = null;
   2027 
   2028         try {
   2029             Context context = mContext;
   2030             if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow " + packageName
   2031                     + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
   2032                     + Integer.toHexString(theme));
   2033             if (theme != context.getThemeResId() || labelRes != 0) {
   2034                 try {
   2035                     context = context.createPackageContext(packageName, 0);
   2036                     context.setTheme(theme);
   2037                 } catch (PackageManager.NameNotFoundException e) {
   2038                     // Ignore
   2039                 }
   2040             }
   2041 
   2042             Window win = PolicyManager.makeNewWindow(context);
   2043             final TypedArray ta = win.getWindowStyle();
   2044             if (ta.getBoolean(
   2045                         com.android.internal.R.styleable.Window_windowDisablePreview, false)
   2046                 || ta.getBoolean(
   2047                         com.android.internal.R.styleable.Window_windowShowWallpaper,false)) {
   2048                 return null;
   2049             }
   2050 
   2051             Resources r = context.getResources();
   2052             win.setTitle(r.getText(labelRes, nonLocalizedLabel));
   2053 
   2054             win.setType(
   2055                 WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
   2056             // Force the window flags: this is a fake window, so it is not really
   2057             // touchable or focusable by the user.  We also add in the ALT_FOCUSABLE_IM
   2058             // flag because we do know that the next window will take input
   2059             // focus, so we want to get the IME window up on top of us right away.
   2060             win.setFlags(
   2061                 windowFlags|
   2062                 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
   2063                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
   2064                 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
   2065                 windowFlags|
   2066                 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
   2067                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
   2068                 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
   2069 
   2070             win.setDefaultIcon(icon);
   2071             win.setDefaultLogo(logo);
   2072 
   2073             win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
   2074                     WindowManager.LayoutParams.MATCH_PARENT);
   2075 
   2076             final WindowManager.LayoutParams params = win.getAttributes();
   2077             params.token = appToken;
   2078             params.packageName = packageName;
   2079             params.windowAnimations = win.getWindowStyle().getResourceId(
   2080                     com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
   2081             params.privateFlags |=
   2082                     WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
   2083             params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
   2084 
   2085             if (!compatInfo.supportsScreen()) {
   2086                 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
   2087             }
   2088 
   2089             params.setTitle("Starting " + packageName);
   2090 
   2091             wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
   2092             view = win.getDecorView();
   2093 
   2094             if (win.isFloating()) {
   2095                 // Whoops, there is no way to display an animation/preview
   2096                 // of such a thing!  After all that work...  let's skip it.
   2097                 // (Note that we must do this here because it is in
   2098                 // getDecorView() where the theme is evaluated...  maybe
   2099                 // we should peek the floating attribute from the theme
   2100                 // earlier.)
   2101                 return null;
   2102             }
   2103 
   2104             if (DEBUG_STARTING_WINDOW) Slog.d(
   2105                 TAG, "Adding starting window for " + packageName
   2106                 + " / " + appToken + ": "
   2107                 + (view.getParent() != null ? view : null));
   2108 
   2109             wm.addView(view, params);
   2110 
   2111             // Only return the view if it was successfully added to the
   2112             // window manager... which we can tell by it having a parent.
   2113             return view.getParent() != null ? view : null;
   2114         } catch (WindowManager.BadTokenException e) {
   2115             // ignore
   2116             Log.w(TAG, appToken + " already running, starting window not displayed. " +
   2117                     e.getMessage());
   2118         } catch (RuntimeException e) {
   2119             // don't crash if something else bad happens, for example a
   2120             // failure loading resources because we are loading from an app
   2121             // on external storage that has been unmounted.
   2122             Log.w(TAG, appToken + " failed creating starting window", e);
   2123         } finally {
   2124             if (view != null && view.getParent() == null) {
   2125                 Log.w(TAG, "view not successfully added to wm, removing view");
   2126                 wm.removeViewImmediate(view);
   2127             }
   2128         }
   2129 
   2130         return null;
   2131     }
   2132 
   2133     /** {@inheritDoc} */
   2134     @Override
   2135     public void removeStartingWindow(IBinder appToken, View window) {
   2136         if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Removing starting window for " + appToken + ": "
   2137                 + window + " Callers=" + Debug.getCallers(4));
   2138 
   2139         if (window != null) {
   2140             WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
   2141             wm.removeView(window);
   2142         }
   2143     }
   2144 
   2145     /**
   2146      * Preflight adding a window to the system.
   2147      *
   2148      * Currently enforces that three window types are singletons:
   2149      * <ul>
   2150      * <li>STATUS_BAR_TYPE</li>
   2151      * <li>KEYGUARD_TYPE</li>
   2152      * </ul>
   2153      *
   2154      * @param win The window to be added
   2155      * @param attrs Information about the window to be added
   2156      *
   2157      * @return If ok, WindowManagerImpl.ADD_OKAY.  If too many singletons,
   2158      * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
   2159      */
   2160     @Override
   2161     public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
   2162         switch (attrs.type) {
   2163             case TYPE_STATUS_BAR:
   2164                 mContext.enforceCallingOrSelfPermission(
   2165                         android.Manifest.permission.STATUS_BAR_SERVICE,
   2166                         "PhoneWindowManager");
   2167                 if (mStatusBar != null) {
   2168                     if (mStatusBar.isAlive()) {
   2169                         return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
   2170                     }
   2171                 }
   2172                 mStatusBar = win;
   2173                 mStatusBarController.setWindow(win);
   2174                 break;
   2175             case TYPE_NAVIGATION_BAR:
   2176                 mContext.enforceCallingOrSelfPermission(
   2177                         android.Manifest.permission.STATUS_BAR_SERVICE,
   2178                         "PhoneWindowManager");
   2179                 if (mNavigationBar != null) {
   2180                     if (mNavigationBar.isAlive()) {
   2181                         return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
   2182                     }
   2183                 }
   2184                 mNavigationBar = win;
   2185                 mNavigationBarController.setWindow(win);
   2186                 if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
   2187                 break;
   2188             case TYPE_NAVIGATION_BAR_PANEL:
   2189                 mContext.enforceCallingOrSelfPermission(
   2190                         android.Manifest.permission.STATUS_BAR_SERVICE,
   2191                         "PhoneWindowManager");
   2192                 break;
   2193             case TYPE_STATUS_BAR_PANEL:
   2194                 mContext.enforceCallingOrSelfPermission(
   2195                         android.Manifest.permission.STATUS_BAR_SERVICE,
   2196                         "PhoneWindowManager");
   2197                 break;
   2198             case TYPE_STATUS_BAR_SUB_PANEL:
   2199                 mContext.enforceCallingOrSelfPermission(
   2200                         android.Manifest.permission.STATUS_BAR_SERVICE,
   2201                         "PhoneWindowManager");
   2202                 break;
   2203             case TYPE_KEYGUARD_SCRIM:
   2204                 if (mKeyguardScrim != null) {
   2205                     return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
   2206                 }
   2207                 mKeyguardScrim = win;
   2208                 break;
   2209         }
   2210         return WindowManagerGlobal.ADD_OKAY;
   2211     }
   2212 
   2213     /** {@inheritDoc} */
   2214     @Override
   2215     public void removeWindowLw(WindowState win) {
   2216         if (mStatusBar == win) {
   2217             mStatusBar = null;
   2218             mStatusBarController.setWindow(null);
   2219             mKeyguardDelegate.showScrim();
   2220         } else if (mKeyguardScrim == win) {
   2221             Log.v(TAG, "Removing keyguard scrim");
   2222             mKeyguardScrim = null;
   2223         } if (mNavigationBar == win) {
   2224             mNavigationBar = null;
   2225             mNavigationBarController.setWindow(null);
   2226         }
   2227     }
   2228 
   2229     static final boolean PRINT_ANIM = false;
   2230 
   2231     /** {@inheritDoc} */
   2232     @Override
   2233     public int selectAnimationLw(WindowState win, int transit) {
   2234         if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
   2235               + ": transit=" + transit);
   2236         if (win == mStatusBar) {
   2237             boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
   2238             if (transit == TRANSIT_EXIT
   2239                     || transit == TRANSIT_HIDE) {
   2240                 return isKeyguard ? -1 : R.anim.dock_top_exit;
   2241             } else if (transit == TRANSIT_ENTER
   2242                     || transit == TRANSIT_SHOW) {
   2243                 return isKeyguard ? -1 : R.anim.dock_top_enter;
   2244             }
   2245         } else if (win == mNavigationBar) {
   2246             // This can be on either the bottom or the right.
   2247             if (mNavigationBarOnBottom) {
   2248                 if (transit == TRANSIT_EXIT
   2249                         || transit == TRANSIT_HIDE) {
   2250                     return R.anim.dock_bottom_exit;
   2251                 } else if (transit == TRANSIT_ENTER
   2252                         || transit == TRANSIT_SHOW) {
   2253                     return R.anim.dock_bottom_enter;
   2254                 }
   2255             } else {
   2256                 if (transit == TRANSIT_EXIT
   2257                         || transit == TRANSIT_HIDE) {
   2258                     return R.anim.dock_right_exit;
   2259                 } else if (transit == TRANSIT_ENTER
   2260                         || transit == TRANSIT_SHOW) {
   2261                     return R.anim.dock_right_enter;
   2262                 }
   2263             }
   2264         }
   2265 
   2266         if (transit == TRANSIT_PREVIEW_DONE) {
   2267             if (win.hasAppShownWindows()) {
   2268                 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
   2269                 return com.android.internal.R.anim.app_starting_exit;
   2270             }
   2271         } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
   2272                 && transit == TRANSIT_ENTER) {
   2273             // Special case: we are animating in a dream, while the keyguard
   2274             // is shown.  We don't want an animation on the dream, because
   2275             // we need it shown immediately with the keyguard animating away
   2276             // to reveal it.
   2277             return -1;
   2278         }
   2279 
   2280         return 0;
   2281     }
   2282 
   2283     @Override
   2284     public void selectRotationAnimationLw(int anim[]) {
   2285         if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
   2286                 + mTopFullscreenOpaqueWindowState + " rotationAnimation="
   2287                 + (mTopFullscreenOpaqueWindowState == null ?
   2288                         "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation));
   2289         if (mTopFullscreenOpaqueWindowState != null && mTopIsFullscreen) {
   2290             switch (mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation) {
   2291                 case ROTATION_ANIMATION_CROSSFADE:
   2292                     anim[0] = R.anim.rotation_animation_xfade_exit;
   2293                     anim[1] = R.anim.rotation_animation_enter;
   2294                     break;
   2295                 case ROTATION_ANIMATION_JUMPCUT:
   2296                     anim[0] = R.anim.rotation_animation_jump_exit;
   2297                     anim[1] = R.anim.rotation_animation_enter;
   2298                     break;
   2299                 case ROTATION_ANIMATION_ROTATE:
   2300                 default:
   2301                     anim[0] = anim[1] = 0;
   2302                     break;
   2303             }
   2304         } else {
   2305             anim[0] = anim[1] = 0;
   2306         }
   2307     }
   2308 
   2309     @Override
   2310     public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId,
   2311             boolean forceDefault) {
   2312         switch (exitAnimId) {
   2313             case R.anim.rotation_animation_xfade_exit:
   2314             case R.anim.rotation_animation_jump_exit:
   2315                 // These are the only cases that matter.
   2316                 if (forceDefault) {
   2317                     return false;
   2318                 }
   2319                 int anim[] = new int[2];
   2320                 selectRotationAnimationLw(anim);
   2321                 return (exitAnimId == anim[0] && enterAnimId == anim[1]);
   2322             default:
   2323                 return true;
   2324         }
   2325     }
   2326 
   2327     @Override
   2328     public Animation createForceHideEnterAnimation(boolean onWallpaper,
   2329             boolean goingToNotificationShade) {
   2330         if (goingToNotificationShade) {
   2331             return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
   2332         }
   2333 
   2334         AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ?
   2335                     R.anim.lock_screen_behind_enter_wallpaper :
   2336                     R.anim.lock_screen_behind_enter);
   2337 
   2338         // TODO: Use XML interpolators when we have log interpolators available in XML.
   2339         final List<Animation> animations = set.getAnimations();
   2340         for (int i = animations.size() - 1; i >= 0; --i) {
   2341             animations.get(i).setInterpolator(mLogDecelerateInterpolator);
   2342         }
   2343 
   2344         return set;
   2345     }
   2346 
   2347 
   2348     @Override
   2349     public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade) {
   2350         if (goingToNotificationShade) {
   2351             return null;
   2352         } else {
   2353             return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
   2354         }
   2355     }
   2356 
   2357     private static void awakenDreams() {
   2358         IDreamManager dreamManager = getDreamManager();
   2359         if (dreamManager != null) {
   2360             try {
   2361                 dreamManager.awaken();
   2362             } catch (RemoteException e) {
   2363                 // fine, stay asleep then
   2364             }
   2365         }
   2366     }
   2367 
   2368     static IDreamManager getDreamManager() {
   2369         return IDreamManager.Stub.asInterface(
   2370                 ServiceManager.checkService(DreamService.DREAM_SERVICE));
   2371     }
   2372 
   2373     TelecomManager getTelecommService() {
   2374         return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
   2375     }
   2376 
   2377     static IAudioService getAudioService() {
   2378         IAudioService audioService = IAudioService.Stub.asInterface(
   2379                 ServiceManager.checkService(Context.AUDIO_SERVICE));
   2380         if (audioService == null) {
   2381             Log.w(TAG, "Unable to find IAudioService interface.");
   2382         }
   2383         return audioService;
   2384     }
   2385 
   2386     boolean keyguardOn() {
   2387         return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode();
   2388     }
   2389 
   2390     private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
   2391             WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
   2392             WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
   2393         };
   2394 
   2395     /** {@inheritDoc} */
   2396     @Override
   2397     public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
   2398         final boolean keyguardOn = keyguardOn();
   2399         final int keyCode = event.getKeyCode();
   2400         final int repeatCount = event.getRepeatCount();
   2401         final int metaState = event.getMetaState();
   2402         final int flags = event.getFlags();
   2403         final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
   2404         final boolean canceled = event.isCanceled();
   2405 
   2406         if (DEBUG_INPUT) {
   2407             Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
   2408                     + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
   2409                     + " canceled=" + canceled);
   2410         }
   2411 
   2412         // If we think we might have a volume down & power key chord on the way
   2413         // but we're not sure, then tell the dispatcher to wait a little while and
   2414         // try again later before dispatching.
   2415         if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
   2416             if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
   2417                 final long now = SystemClock.uptimeMillis();
   2418                 final long timeoutTime = mScreenshotChordVolumeDownKeyTime
   2419                         + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
   2420                 if (now < timeoutTime) {
   2421                     return timeoutTime - now;
   2422                 }
   2423             }
   2424             if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
   2425                     && mScreenshotChordVolumeDownKeyConsumed) {
   2426                 if (!down) {
   2427                     mScreenshotChordVolumeDownKeyConsumed = false;
   2428                 }
   2429                 return -1;
   2430             }
   2431         }
   2432 
   2433         // Cancel any pending meta actions if we see any other keys being pressed between the down
   2434         // of the meta key and its corresponding up.
   2435         if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
   2436             mPendingMetaAction = false;
   2437         }
   2438 
   2439         // First we always handle the home key here, so applications
   2440         // can never break it, although if keyguard is on, we do let
   2441         // it handle it, because that gives us the correct 5 second
   2442         // timeout.
   2443         if (keyCode == KeyEvent.KEYCODE_HOME) {
   2444 
   2445             // If we have released the home key, and didn't do anything else
   2446             // while it was pressed, then it is time to go home!
   2447             if (!down) {
   2448                 cancelPreloadRecentApps();
   2449 
   2450                 mHomePressed = false;
   2451                 if (mHomeConsumed) {
   2452                     mHomeConsumed = false;
   2453                     return -1;
   2454                 }
   2455 
   2456                 if (canceled) {
   2457                     Log.i(TAG, "Ignoring HOME; event canceled.");
   2458                     return -1;
   2459                 }
   2460 
   2461                 // If an incoming call is ringing, HOME is totally disabled.
   2462                 // (The user is already on the InCallUI at this point,
   2463                 // and his ONLY options are to answer or reject the call.)
   2464                 TelecomManager telecomManager = getTelecommService();
   2465                 if (telecomManager != null && telecomManager.isRinging()) {
   2466                     Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
   2467                     return -1;
   2468                 }
   2469 
   2470                 // Delay handling home if a double-tap is possible.
   2471                 if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
   2472                     mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
   2473                     mHomeDoubleTapPending = true;
   2474                     mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
   2475                             ViewConfiguration.getDoubleTapTimeout());
   2476                     return -1;
   2477                 }
   2478 
   2479                 handleShortPressOnHome();
   2480                 return -1;
   2481             }
   2482 
   2483             // If a system window has focus, then it doesn't make sense
   2484             // right now to interact with applications.
   2485             WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
   2486             if (attrs != null) {
   2487                 final int type = attrs.type;
   2488                 if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM
   2489                         || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
   2490                         || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
   2491                     // the "app" is keyguard, so give it the key
   2492                     return 0;
   2493                 }
   2494                 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
   2495                 for (int i=0; i<typeCount; i++) {
   2496                     if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
   2497                         // don't do anything, but also don't pass it to the app
   2498                         return -1;
   2499                     }
   2500                 }
   2501             }
   2502 
   2503             // Remember that home is pressed and handle special actions.
   2504             if (repeatCount == 0) {
   2505                 mHomePressed = true;
   2506                 if (mHomeDoubleTapPending) {
   2507                     mHomeDoubleTapPending = false;
   2508                     mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
   2509                     handleDoubleTapOnHome();
   2510                 } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI
   2511                         || mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
   2512                     preloadRecentApps();
   2513                 }
   2514             } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
   2515                 if (!keyguardOn) {
   2516                     handleLongPressOnHome();
   2517                 }
   2518             }
   2519             return -1;
   2520         } else if (keyCode == KeyEvent.KEYCODE_MENU) {
   2521             // Hijack modified menu keys for debugging features
   2522             final int chordBug = KeyEvent.META_SHIFT_ON;
   2523 
   2524             if (down && repeatCount == 0) {
   2525                 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
   2526                     Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
   2527                     mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
   2528                             null, null, null, 0, null, null);
   2529                     return -1;
   2530                 } else if (SHOW_PROCESSES_ON_ALT_MENU &&
   2531                         (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
   2532                     Intent service = new Intent();
   2533                     service.setClassName(mContext, "com.android.server.LoadAverageService");
   2534                     ContentResolver res = mContext.getContentResolver();
   2535                     boolean shown = Settings.Global.getInt(
   2536                             res, Settings.Global.SHOW_PROCESSES, 0) != 0;
   2537                     if (!shown) {
   2538                         mContext.startService(service);
   2539                     } else {
   2540                         mContext.stopService(service);
   2541                     }
   2542                     Settings.Global.putInt(
   2543                             res, Settings.Global.SHOW_PROCESSES, shown ? 0 : 1);
   2544                     return -1;
   2545                 }
   2546             }
   2547         } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
   2548             if (down) {
   2549                 if (repeatCount == 0) {
   2550                     mSearchKeyShortcutPending = true;
   2551                     mConsumeSearchKeyUp = false;
   2552                 }
   2553             } else {
   2554                 mSearchKeyShortcutPending = false;
   2555                 if (mConsumeSearchKeyUp) {
   2556                     mConsumeSearchKeyUp = false;
   2557                     return -1;
   2558                 }
   2559             }
   2560             return 0;
   2561         } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
   2562             if (!keyguardOn) {
   2563                 if (down && repeatCount == 0) {
   2564                     preloadRecentApps();
   2565                 } else if (!down) {
   2566                     toggleRecentApps();
   2567                 }
   2568             }
   2569             return -1;
   2570         } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
   2571             if (down) {
   2572                 if (repeatCount == 0) {
   2573                     mAssistKeyLongPressed = false;
   2574                 } else if (repeatCount == 1) {
   2575                     mAssistKeyLongPressed = true;
   2576                     if (!keyguardOn) {
   2577                          launchAssistLongPressAction();
   2578                     }
   2579                 }
   2580             } else {
   2581                 if (mAssistKeyLongPressed) {
   2582                     mAssistKeyLongPressed = false;
   2583                 } else {
   2584                     if (!keyguardOn) {
   2585                         launchAssistAction();
   2586                     }
   2587                 }
   2588             }
   2589             return -1;
   2590         } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
   2591             if (!down) {
   2592                 Intent voiceIntent;
   2593                 if (!keyguardOn) {
   2594                     voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
   2595                 } else {
   2596                     voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
   2597                     voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
   2598                 }
   2599                 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
   2600             }
   2601         } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
   2602             if (down && repeatCount == 0) {
   2603                 mHandler.post(mScreenshotRunnable);
   2604             }
   2605             return -1;
   2606         } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP
   2607                 || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) {
   2608             if (down) {
   2609                 int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
   2610 
   2611                 // Disable autobrightness if it's on
   2612                 int auto = Settings.System.getIntForUser(
   2613                         mContext.getContentResolver(),
   2614                         Settings.System.SCREEN_BRIGHTNESS_MODE,
   2615                         Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
   2616                         UserHandle.USER_CURRENT_OR_SELF);
   2617                 if (auto != 0) {
   2618                     Settings.System.putIntForUser(mContext.getContentResolver(),
   2619                             Settings.System.SCREEN_BRIGHTNESS_MODE,
   2620                             Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
   2621                             UserHandle.USER_CURRENT_OR_SELF);
   2622                 }
   2623 
   2624                 int min = mPowerManager.getMinimumScreenBrightnessSetting();
   2625                 int max = mPowerManager.getMaximumScreenBrightnessSetting();
   2626                 int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction;
   2627                 int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
   2628                         Settings.System.SCREEN_BRIGHTNESS,
   2629                         mPowerManager.getDefaultScreenBrightnessSetting(),
   2630                         UserHandle.USER_CURRENT_OR_SELF);
   2631                 brightness += step;
   2632                 // Make sure we don't go beyond the limits.
   2633                 brightness = Math.min(max, brightness);
   2634                 brightness = Math.max(min, brightness);
   2635 
   2636                 Settings.System.putIntForUser(mContext.getContentResolver(),
   2637                         Settings.System.SCREEN_BRIGHTNESS, brightness,
   2638                         UserHandle.USER_CURRENT_OR_SELF);
   2639                 startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
   2640                         UserHandle.CURRENT_OR_SELF);
   2641             }
   2642             return -1;
   2643         } else if (KeyEvent.isMetaKey(keyCode)) {
   2644             if (down) {
   2645                 mPendingMetaAction = true;
   2646             } else if (mPendingMetaAction) {
   2647                 launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD);
   2648             }
   2649             return -1;
   2650         }
   2651 
   2652         // Shortcuts are invoked through Search+key, so intercept those here
   2653         // Any printing key that is chorded with Search should be consumed
   2654         // even if no shortcut was invoked.  This prevents text from being
   2655         // inadvertently inserted when using a keyboard that has built-in macro
   2656         // shortcut keys (that emit Search+x) and some of them are not registered.
   2657         if (mSearchKeyShortcutPending) {
   2658             final KeyCharacterMap kcm = event.getKeyCharacterMap();
   2659             if (kcm.isPrintingKey(keyCode)) {
   2660                 mConsumeSearchKeyUp = true;
   2661                 mSearchKeyShortcutPending = false;
   2662                 if (down && repeatCount == 0 && !keyguardOn) {
   2663                     Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
   2664                     if (shortcutIntent != null) {
   2665                         shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   2666                         try {
   2667                             startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
   2668                         } catch (ActivityNotFoundException ex) {
   2669                             Slog.w(TAG, "Dropping shortcut key combination because "
   2670                                     + "the activity to which it is registered was not found: "
   2671                                     + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);
   2672                         }
   2673                     } else {
   2674                         Slog.i(TAG, "Dropping unregistered shortcut key combination: "
   2675                                 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));
   2676                     }
   2677                 }
   2678                 return -1;
   2679             }
   2680         }
   2681 
   2682         // Invoke shortcuts using Meta.
   2683         if (down && repeatCount == 0 && !keyguardOn
   2684                 && (metaState & KeyEvent.META_META_ON) != 0) {
   2685             final KeyCharacterMap kcm = event.getKeyCharacterMap();
   2686             if (kcm.isPrintingKey(keyCode)) {
   2687                 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
   2688                         metaState & ~(KeyEvent.META_META_ON
   2689                                 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
   2690                 if (shortcutIntent != null) {
   2691                     shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   2692                     try {
   2693                         startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
   2694                     } catch (ActivityNotFoundException ex) {
   2695                         Slog.w(TAG, "Dropping shortcut key combination because "
   2696                                 + "the activity to which it is registered was not found: "
   2697                                 + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
   2698                     }
   2699                     return -1;
   2700                 }
   2701             }
   2702         }
   2703 
   2704         // Handle application launch keys.
   2705         if (down && repeatCount == 0 && !keyguardOn) {
   2706             String category = sApplicationLaunchKeyCategories.get(keyCode);
   2707             if (category != null) {
   2708                 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
   2709                 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   2710                 try {
   2711                     startActivityAsUser(intent, UserHandle.CURRENT);
   2712                 } catch (ActivityNotFoundException ex) {
   2713                     Slog.w(TAG, "Dropping application launch key because "
   2714                             + "the activity to which it is registered was not found: "
   2715                             + "keyCode=" + keyCode + ", category=" + category, ex);
   2716                 }
   2717                 return -1;
   2718             }
   2719         }
   2720 
   2721         // Display task switcher for ALT-TAB.
   2722         if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
   2723             if (mRecentAppsHeldModifiers == 0 && !keyguardOn) {
   2724                 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
   2725                 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
   2726                     mRecentAppsHeldModifiers = shiftlessModifiers;
   2727                     showRecentApps(true);
   2728                     return -1;
   2729                 }
   2730             }
   2731         } else if (!down && mRecentAppsHeldModifiers != 0
   2732                 && (metaState & mRecentAppsHeldModifiers) == 0) {
   2733             mRecentAppsHeldModifiers = 0;
   2734             hideRecentApps(true, false);
   2735         }
   2736 
   2737         // Handle keyboard language switching.
   2738         if (down && repeatCount == 0
   2739                 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
   2740                         || (keyCode == KeyEvent.KEYCODE_SPACE
   2741                                 && (metaState & KeyEvent.META_CTRL_MASK) != 0))) {
   2742             int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
   2743             mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
   2744             return -1;
   2745         }
   2746         if (mLanguageSwitchKeyPressed && !down
   2747                 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
   2748                         || keyCode == KeyEvent.KEYCODE_SPACE)) {
   2749             mLanguageSwitchKeyPressed = false;
   2750             return -1;
   2751         }
   2752 
   2753         if (isValidGlobalKey(keyCode)
   2754                 && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
   2755             return -1;
   2756         }
   2757 
   2758         // Reserve all the META modifier combos for system behavior
   2759         if ((metaState & KeyEvent.META_META_ON) != 0) {
   2760             return -1;
   2761         }
   2762 
   2763         // Let the application handle the key.
   2764         return 0;
   2765     }
   2766 
   2767     /** {@inheritDoc} */
   2768     @Override
   2769     public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
   2770         // Note: This method is only called if the initial down was unhandled.
   2771         if (DEBUG_INPUT) {
   2772             Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
   2773                     + ", flags=" + event.getFlags()
   2774                     + ", keyCode=" + event.getKeyCode()
   2775                     + ", scanCode=" + event.getScanCode()
   2776                     + ", metaState=" + event.getMetaState()
   2777                     + ", repeatCount=" + event.getRepeatCount()
   2778                     + ", policyFlags=" + policyFlags);
   2779         }
   2780 
   2781         KeyEvent fallbackEvent = null;
   2782         if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
   2783             final KeyCharacterMap kcm = event.getKeyCharacterMap();
   2784             final int keyCode = event.getKeyCode();
   2785             final int metaState = event.getMetaState();
   2786             final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
   2787                     && event.getRepeatCount() == 0;
   2788 
   2789             // Check for fallback actions specified by the key character map.
   2790             final FallbackAction fallbackAction;
   2791             if (initialDown) {
   2792                 fallbackAction = kcm.getFallbackAction(keyCode, metaState);
   2793             } else {
   2794                 fallbackAction = mFallbackActions.get(keyCode);
   2795             }
   2796 
   2797             if (fallbackAction != null) {
   2798                 if (DEBUG_INPUT) {
   2799                     Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode
   2800                             + " metaState=" + Integer.toHexString(fallbackAction.metaState));
   2801                 }
   2802 
   2803                 final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
   2804                 fallbackEvent = KeyEvent.obtain(
   2805                         event.getDownTime(), event.getEventTime(),
   2806                         event.getAction(), fallbackAction.keyCode,
   2807                         event.getRepeatCount(), fallbackAction.metaState,
   2808                         event.getDeviceId(), event.getScanCode(),
   2809                         flags, event.getSource(), null);
   2810 
   2811                 if (!interceptFallback(win, fallbackEvent, policyFlags)) {
   2812                     fallbackEvent.recycle();
   2813                     fallbackEvent = null;
   2814                 }
   2815 
   2816                 if (initialDown) {
   2817                     mFallbackActions.put(keyCode, fallbackAction);
   2818                 } else if (event.getAction() == KeyEvent.ACTION_UP) {
   2819                     mFallbackActions.remove(keyCode);
   2820                     fallbackAction.recycle();
   2821                 }
   2822             }
   2823         }
   2824 
   2825         if (DEBUG_INPUT) {
   2826             if (fallbackEvent == null) {
   2827                 Slog.d(TAG, "No fallback.");
   2828             } else {
   2829                 Slog.d(TAG, "Performing fallback: " + fallbackEvent);
   2830             }
   2831         }
   2832         return fallbackEvent;
   2833     }
   2834 
   2835     private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
   2836         int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
   2837         if ((actions & ACTION_PASS_TO_USER) != 0) {
   2838             long delayMillis = interceptKeyBeforeDispatching(
   2839                     win, fallbackEvent, policyFlags);
   2840             if (delayMillis == 0) {
   2841                 return true;
   2842             }
   2843         }
   2844         return false;
   2845     }
   2846 
   2847     private void launchAssistLongPressAction() {
   2848         performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
   2849         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
   2850 
   2851         // launch the search activity
   2852         Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
   2853         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   2854         try {
   2855             // TODO: This only stops the factory-installed search manager.
   2856             // Need to formalize an API to handle others
   2857             SearchManager searchManager = getSearchManager();
   2858             if (searchManager != null) {
   2859                 searchManager.stopSearch();
   2860             }
   2861             startActivityAsUser(intent, UserHandle.CURRENT);
   2862         } catch (ActivityNotFoundException e) {
   2863             Slog.w(TAG, "No activity to handle assist long press action.", e);
   2864         }
   2865     }
   2866 
   2867     private void launchAssistAction() {
   2868         launchAssistAction(null);
   2869     }
   2870 
   2871     private void launchAssistAction(String hint) {
   2872         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
   2873         Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
   2874                 .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
   2875         if (intent != null) {
   2876             if (hint != null) {
   2877                 intent.putExtra(hint, true);
   2878             }
   2879             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
   2880                     | Intent.FLAG_ACTIVITY_SINGLE_TOP
   2881                     | Intent.FLAG_ACTIVITY_CLEAR_TOP);
   2882             try {
   2883                 startActivityAsUser(intent, UserHandle.CURRENT);
   2884             } catch (ActivityNotFoundException e) {
   2885                 Slog.w(TAG, "No activity to handle assist action.", e);
   2886             }
   2887         }
   2888     }
   2889 
   2890     private void startActivityAsUser(Intent intent, UserHandle handle) {
   2891         if (isUserSetupComplete()) {
   2892             mContext.startActivityAsUser(intent, handle);
   2893         } else {
   2894             Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent);
   2895         }
   2896     }
   2897 
   2898     private SearchManager getSearchManager() {
   2899         if (mSearchManager == null) {
   2900             mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
   2901         }
   2902         return mSearchManager;
   2903     }
   2904 
   2905     private void preloadRecentApps() {
   2906         mPreloadedRecentApps = true;
   2907         try {
   2908             IStatusBarService statusbar = getStatusBarService();
   2909             if (statusbar != null) {
   2910                 statusbar.preloadRecentApps();
   2911             }
   2912         } catch (RemoteException e) {
   2913             Slog.e(TAG, "RemoteException when preloading recent apps", e);
   2914             // re-acquire status bar service next time it is needed.
   2915             mStatusBarService = null;
   2916         }
   2917     }
   2918 
   2919     private void cancelPreloadRecentApps() {
   2920         if (mPreloadedRecentApps) {
   2921             mPreloadedRecentApps = false;
   2922             try {
   2923                 IStatusBarService statusbar = getStatusBarService();
   2924                 if (statusbar != null) {
   2925                     statusbar.cancelPreloadRecentApps();
   2926                 }
   2927             } catch (RemoteException e) {
   2928                 Slog.e(TAG, "RemoteException when cancelling recent apps preload", e);
   2929                 // re-acquire status bar service next time it is needed.
   2930                 mStatusBarService = null;
   2931             }
   2932         }
   2933     }
   2934 
   2935     private void toggleRecentApps() {
   2936         mPreloadedRecentApps = false; // preloading no longer needs to be canceled
   2937         try {
   2938             IStatusBarService statusbar = getStatusBarService();
   2939             if (statusbar != null) {
   2940                 statusbar.toggleRecentApps();
   2941             }
   2942         } catch (RemoteException e) {
   2943             Slog.e(TAG, "RemoteException when toggling recent apps", e);
   2944             // re-acquire status bar service next time it is needed.
   2945             mStatusBarService = null;
   2946         }
   2947     }
   2948 
   2949     @Override
   2950     public void showRecentApps() {
   2951         mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
   2952         mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_RECENTS);
   2953     }
   2954 
   2955     private void showRecentApps(boolean triggeredFromAltTab) {
   2956         mPreloadedRecentApps = false; // preloading no longer needs to be canceled
   2957         try {
   2958             IStatusBarService statusbar = getStatusBarService();
   2959             if (statusbar != null) {
   2960                 statusbar.showRecentApps(triggeredFromAltTab);
   2961             }
   2962         } catch (RemoteException e) {
   2963             Slog.e(TAG, "RemoteException when showing recent apps", e);
   2964             // re-acquire status bar service next time it is needed.
   2965             mStatusBarService = null;
   2966         }
   2967     }
   2968 
   2969     private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
   2970         mPreloadedRecentApps = false; // preloading no longer needs to be canceled
   2971         try {
   2972             IStatusBarService statusbar = getStatusBarService();
   2973             if (statusbar != null) {
   2974                 statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
   2975             }
   2976         } catch (RemoteException e) {
   2977             Slog.e(TAG, "RemoteException when closing recent apps", e);
   2978             // re-acquire status bar service next time it is needed.
   2979             mStatusBarService = null;
   2980         }
   2981     }
   2982 
   2983     /**
   2984      * A home key -> launch home action was detected.  Take the appropriate action
   2985      * given the situation with the keyguard.
   2986      */
   2987     void launchHomeFromHotKey() {
   2988         if (isKeyguardShowingAndNotOccluded()) {
   2989             // don't launch home if keyguard showing
   2990         } else if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) {
   2991             // when in keyguard restricted mode, must first verify unlock
   2992             // before launching home
   2993             mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
   2994                 @Override
   2995                 public void onKeyguardExitResult(boolean success) {
   2996                     if (success) {
   2997                         try {
   2998                             ActivityManagerNative.getDefault().stopAppSwitches();
   2999                         } catch (RemoteException e) {
   3000                         }
   3001                         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
   3002                         startDockOrHome();
   3003                     }
   3004                 }
   3005             });
   3006         } else {
   3007             // no keyguard stuff to worry about, just launch home!
   3008             try {
   3009                 ActivityManagerNative.getDefault().stopAppSwitches();
   3010             } catch (RemoteException e) {
   3011             }
   3012             if (mRecentsVisible) {
   3013                 // Hide Recents and notify it to launch Home
   3014                 awakenDreams();
   3015                 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
   3016                 hideRecentApps(false, true);
   3017             } else {
   3018                 // Otherwise, just launch Home
   3019                 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
   3020                 startDockOrHome();
   3021             }
   3022         }
   3023     }
   3024 
   3025     private final Runnable mClearHideNavigationFlag = new Runnable() {
   3026         @Override
   3027         public void run() {
   3028             synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
   3029                 // Clear flags.
   3030                 mForceClearedSystemUiFlags &=
   3031                         ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
   3032             }
   3033             mWindowManagerFuncs.reevaluateStatusBarVisibility();
   3034         }
   3035     };
   3036 
   3037     /**
   3038      * Input handler used while nav bar is hidden.  Captures any touch on the screen,
   3039      * to determine when the nav bar should be shown and prevent applications from
   3040      * receiving those touches.
   3041      */
   3042     final class HideNavInputEventReceiver extends InputEventReceiver {
   3043         public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
   3044             super(inputChannel, looper);
   3045         }
   3046 
   3047         @Override
   3048         public void onInputEvent(InputEvent event) {
   3049             boolean handled = false;
   3050             try {
   3051                 if (event instanceof MotionEvent
   3052                         && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
   3053                     final MotionEvent motionEvent = (MotionEvent)event;
   3054                     if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
   3055                         // When the user taps down, we re-show the nav bar.
   3056                         boolean changed = false;
   3057                         synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
   3058                             // Any user activity always causes us to show the
   3059                             // navigation controls, if they had been hidden.
   3060                             // We also clear the low profile and only content
   3061                             // flags so that tapping on the screen will atomically
   3062                             // restore all currently hidden screen decorations.
   3063                             int newVal = mResettingSystemUiFlags |
   3064                                     View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
   3065                                     View.SYSTEM_UI_FLAG_LOW_PROFILE |
   3066                                     View.SYSTEM_UI_FLAG_FULLSCREEN;
   3067                             if (mResettingSystemUiFlags != newVal) {
   3068                                 mResettingSystemUiFlags = newVal;
   3069                                 changed = true;
   3070                             }
   3071                             // We don't allow the system's nav bar to be hidden
   3072                             // again for 1 second, to prevent applications from
   3073                             // spamming us and keeping it from being shown.
   3074                             newVal = mForceClearedSystemUiFlags |
   3075                                     View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
   3076                             if (mForceClearedSystemUiFlags != newVal) {
   3077                                 mForceClearedSystemUiFlags = newVal;
   3078                                 changed = true;
   3079                                 mHandler.postDelayed(mClearHideNavigationFlag, 1000);
   3080                             }
   3081                         }
   3082                         if (changed) {
   3083                             mWindowManagerFuncs.reevaluateStatusBarVisibility();
   3084                         }
   3085                     }
   3086                 }
   3087             } finally {
   3088                 finishInputEvent(event, handled);
   3089             }
   3090         }
   3091     }
   3092     final InputEventReceiver.Factory mHideNavInputEventReceiverFactory =
   3093             new InputEventReceiver.Factory() {
   3094         @Override
   3095         public InputEventReceiver createInputEventReceiver(
   3096                 InputChannel inputChannel, Looper looper) {
   3097             return new HideNavInputEventReceiver(inputChannel, looper);
   3098         }
   3099     };
   3100 
   3101     @Override
   3102     public int adjustSystemUiVisibilityLw(int visibility) {
   3103         mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
   3104         mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
   3105         mRecentsVisible = (visibility & View.RECENT_APPS_VISIBLE) > 0;
   3106 
   3107         // Reset any bits in mForceClearingStatusBarVisibility that
   3108         // are now clear.
   3109         mResettingSystemUiFlags &= visibility;
   3110         // Clear any bits in the new visibility that are currently being
   3111         // force cleared, before reporting it.
   3112         return visibility & ~mResettingSystemUiFlags
   3113                 & ~mForceClearedSystemUiFlags;
   3114     }
   3115 
   3116     @Override
   3117     public void getInsetHintLw(WindowManager.LayoutParams attrs, Rect outContentInsets,
   3118             Rect outStableInsets) {
   3119         final int fl = PolicyControl.getWindowFlags(null, attrs);
   3120         final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
   3121         final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
   3122 
   3123         if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
   3124                 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
   3125             int availRight, availBottom;
   3126             if (canHideNavigationBar() &&
   3127                     (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
   3128                 availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
   3129                 availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
   3130             } else {
   3131                 availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
   3132                 availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
   3133             }
   3134             if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
   3135                 if ((fl & FLAG_FULLSCREEN) != 0) {
   3136                     outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop,
   3137                             availRight - mStableFullscreenRight,
   3138                             availBottom - mStableFullscreenBottom);
   3139                 } else {
   3140                     outContentInsets.set(mStableLeft, mStableTop,
   3141                             availRight - mStableRight, availBottom - mStableBottom);
   3142                 }
   3143             } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
   3144                 outContentInsets.setEmpty();
   3145             } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
   3146                         | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
   3147                 outContentInsets.set(mCurLeft, mCurTop,
   3148                         availRight - mCurRight, availBottom - mCurBottom);
   3149             } else {
   3150                 outContentInsets.set(mCurLeft, mCurTop,
   3151                         availRight - mCurRight, availBottom - mCurBottom);
   3152             }
   3153 
   3154             outStableInsets.set(mStableLeft, mStableTop,
   3155                     availRight - mStableRight, availBottom - mStableBottom);
   3156             return;
   3157         }
   3158         outContentInsets.setEmpty();
   3159         outStableInsets.setEmpty();
   3160     }
   3161 
   3162     /** {@inheritDoc} */
   3163     @Override
   3164     public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
   3165                               int displayRotation) {
   3166         final int overscanLeft, overscanTop, overscanRight, overscanBottom;
   3167         if (isDefaultDisplay) {
   3168             switch (displayRotation) {
   3169                 case Surface.ROTATION_90:
   3170                     overscanLeft = mOverscanTop;
   3171                     overscanTop = mOverscanRight;
   3172                     overscanRight = mOverscanBottom;
   3173                     overscanBottom = mOverscanLeft;
   3174                     break;
   3175                 case Surface.ROTATION_180:
   3176                     overscanLeft = mOverscanRight;
   3177                     overscanTop = mOverscanBottom;
   3178                     overscanRight = mOverscanLeft;
   3179                     overscanBottom = mOverscanTop;
   3180                     break;
   3181                 case Surface.ROTATION_270:
   3182                     overscanLeft = mOverscanBottom;
   3183                     overscanTop = mOverscanLeft;
   3184                     overscanRight = mOverscanTop;
   3185                     overscanBottom = mOverscanRight;
   3186                     break;
   3187                 default:
   3188                     overscanLeft = mOverscanLeft;
   3189                     overscanTop = mOverscanTop;
   3190                     overscanRight = mOverscanRight;
   3191                     overscanBottom = mOverscanBottom;
   3192                     break;
   3193             }
   3194         } else {
   3195             overscanLeft = 0;
   3196             overscanTop = 0;
   3197             overscanRight = 0;
   3198             overscanBottom = 0;
   3199         }
   3200         mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0;
   3201         mOverscanScreenTop = mRestrictedOverscanScreenTop = 0;
   3202         mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth;
   3203         mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight;
   3204         mSystemLeft = 0;
   3205         mSystemTop = 0;
   3206         mSystemRight = displayWidth;
   3207         mSystemBottom = displayHeight;
   3208         mUnrestrictedScreenLeft = overscanLeft;
   3209         mUnrestrictedScreenTop = overscanTop;
   3210         mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight;
   3211         mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom;
   3212         mRestrictedScreenLeft = mUnrestrictedScreenLeft;
   3213         mRestrictedScreenTop = mUnrestrictedScreenTop;
   3214         mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth;
   3215         mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight;
   3216         mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft
   3217                 = mCurLeft = mUnrestrictedScreenLeft;
   3218         mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop
   3219                 = mCurTop = mUnrestrictedScreenTop;
   3220         mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight
   3221                 = mCurRight = displayWidth - overscanRight;
   3222         mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom
   3223                 = mCurBottom = displayHeight - overscanBottom;
   3224         mDockLayer = 0x10000000;
   3225         mStatusBarLayer = -1;
   3226 
   3227         // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
   3228         final Rect pf = mTmpParentFrame;
   3229         final Rect df = mTmpDisplayFrame;
   3230         final Rect of = mTmpOverscanFrame;
   3231         final Rect vf = mTmpVisibleFrame;
   3232         final Rect dcf = mTmpDecorFrame;
   3233         pf.left = df.left = of.left = vf.left = mDockLeft;
   3234         pf.top = df.top = of.top = vf.top = mDockTop;
   3235         pf.right = df.right = of.right = vf.right = mDockRight;
   3236         pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom;
   3237         dcf.setEmpty();  // Decor frame N/A for system bars.
   3238 
   3239         if (isDefaultDisplay) {
   3240             // For purposes of putting out fake window up to steal focus, we will
   3241             // drive nav being hidden only by whether it is requested.
   3242             final int sysui = mLastSystemUiFlags;
   3243             boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
   3244             boolean navTranslucent = (sysui
   3245                     & (View.NAVIGATION_BAR_TRANSLUCENT | View.SYSTEM_UI_TRANSPARENT)) != 0;
   3246             boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
   3247             boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
   3248             boolean navAllowedHidden = immersive || immersiveSticky;
   3249             navTranslucent &= !immersiveSticky;  // transient trumps translucent
   3250             boolean isKeyguardShowing = isStatusBarKeyguard() && !mHideLockScreen;
   3251             if (!isKeyguardShowing) {
   3252                 navTranslucent &= areTranslucentBarsAllowed();
   3253             }
   3254 
   3255             // When the navigation bar isn't visible, we put up a fake
   3256             // input window to catch all touch events.  This way we can
   3257             // detect when the user presses anywhere to bring back the nav
   3258             // bar and ensure the application doesn't see the event.
   3259             if (navVisible || navAllowedHidden) {
   3260                 if (mHideNavFakeWindow != null) {
   3261                     mHideNavFakeWindow.dismiss();
   3262                     mHideNavFakeWindow = null;
   3263                 }
   3264             } else if (mHideNavFakeWindow == null) {
   3265                 mHideNavFakeWindow = mWindowManagerFuncs.addFakeWindow(
   3266                         mHandler.getLooper(), mHideNavInputEventReceiverFactory,
   3267                         "hidden nav", WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER, 0,
   3268                         0, false, false, true);
   3269             }
   3270 
   3271             // For purposes of positioning and showing the nav bar, if we have
   3272             // decided that it can't be hidden (because of the screen aspect ratio),
   3273             // then take that into account.
   3274             navVisible |= !canHideNavigationBar();
   3275 
   3276             boolean updateSysUiVisibility = false;
   3277             if (mNavigationBar != null) {
   3278                 boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
   3279                 // Force the navigation bar to its appropriate place and
   3280                 // size.  We need to do this directly, instead of relying on
   3281                 // it to bubble up from the nav bar, because this needs to
   3282                 // change atomically with screen rotations.
   3283                 mNavigationBarOnBottom = (!mNavigationBarCanMove || displayWidth < displayHeight);
   3284                 if (mNavigationBarOnBottom) {
   3285                     // It's a system nav bar or a portrait screen; nav bar goes on bottom.
   3286                     int top = displayHeight - overscanBottom
   3287                             - mNavigationBarHeightForRotation[displayRotation];
   3288                     mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
   3289                     mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
   3290                     if (transientNavBarShowing) {
   3291                         mNavigationBarController.setBarShowingLw(true);
   3292                     } else if (navVisible) {
   3293                         mNavigationBarController.setBarShowingLw(true);
   3294                         mDockBottom = mTmpNavigationFrame.top;
   3295                         mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
   3296                         mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
   3297                     } else {
   3298                         // We currently want to hide the navigation UI.
   3299                         mNavigationBarController.setBarShowingLw(false);
   3300                     }
   3301                     if (navVisible && !navTranslucent && !navAllowedHidden
   3302                             && !mNavigationBar.isAnimatingLw()
   3303                             && !mNavigationBarController.wasRecentlyTranslucent()) {
   3304                         // If the opaque nav bar is currently requested to be visible,
   3305                         // and not in the process of animating on or off, then
   3306                         // we can tell the app that it is covered by it.
   3307                         mSystemBottom = mTmpNavigationFrame.top;
   3308                     }
   3309                 } else {
   3310                     // Landscape screen; nav bar goes to the right.
   3311                     int left = displayWidth - overscanRight
   3312                             - mNavigationBarWidthForRotation[displayRotation];
   3313                     mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
   3314                     mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
   3315                     if (transientNavBarShowing) {
   3316                         mNavigationBarController.setBarShowingLw(true);
   3317                     } else if (navVisible) {
   3318                         mNavigationBarController.setBarShowingLw(true);
   3319                         mDockRight = mTmpNavigationFrame.left;
   3320                         mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
   3321                         mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
   3322                     } else {
   3323                         // We currently want to hide the navigation UI.
   3324                         mNavigationBarController.setBarShowingLw(false);
   3325                     }
   3326                     if (navVisible && !navTranslucent && !mNavigationBar.isAnimatingLw()
   3327                             && !mNavigationBarController.wasRecentlyTranslucent()) {
   3328                         // If the nav bar is currently requested to be visible,
   3329                         // and not in the process of animating on or off, then
   3330                         // we can tell the app that it is covered by it.
   3331                         mSystemRight = mTmpNavigationFrame.left;
   3332                     }
   3333                 }
   3334                 // Make sure the content and current rectangles are updated to
   3335                 // account for the restrictions from the navigation bar.
   3336                 mContentTop = mVoiceContentTop = mCurTop = mDockTop;
   3337                 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
   3338                 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
   3339                 mContentRight = mVoiceContentRight = mCurRight = mDockRight;
   3340                 mStatusBarLayer = mNavigationBar.getSurfaceLayer();
   3341                 // And compute the final frame.
   3342                 mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
   3343                         mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
   3344                         mTmpNavigationFrame);
   3345                 if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
   3346                 if (mNavigationBarController.checkHiddenLw()) {
   3347                     updateSysUiVisibility = true;
   3348                 }
   3349             }
   3350             if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
   3351                     mDockLeft, mDockTop, mDockRight, mDockBottom));
   3352 
   3353             // decide where the status bar goes ahead of time
   3354             if (mStatusBar != null) {
   3355                 // apply any navigation bar insets
   3356                 pf.left = df.left = of.left = mUnrestrictedScreenLeft;
   3357                 pf.top = df.top = of.top = mUnrestrictedScreenTop;
   3358                 pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
   3359                 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
   3360                         + mUnrestrictedScreenTop;
   3361                 vf.left = mStableLeft;
   3362                 vf.top = mStableTop;
   3363                 vf.right = mStableRight;
   3364                 vf.bottom = mStableBottom;
   3365 
   3366                 mStatusBarLayer = mStatusBar.getSurfaceLayer();
   3367 
   3368                 // Let the status bar determine its size.
   3369                 mStatusBar.computeFrameLw(pf, df, vf, vf, vf, dcf, vf);
   3370 
   3371                 // For layout, the status bar is always at the top with our fixed height.
   3372                 mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
   3373 
   3374                 boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
   3375                 boolean statusBarTranslucent = (sysui
   3376                         & (View.STATUS_BAR_TRANSLUCENT | View.SYSTEM_UI_TRANSPARENT)) != 0;
   3377                 if (!isKeyguardShowing) {
   3378                     statusBarTranslucent &= areTranslucentBarsAllowed();
   3379                 }
   3380 
   3381                 // If the status bar is hidden, we don't want to cause
   3382                 // windows behind it to scroll.
   3383                 if (mStatusBar.isVisibleLw() && !statusBarTransient) {
   3384                     // Status bar may go away, so the screen area it occupies
   3385                     // is available to apps but just covering them when the
   3386                     // status bar is visible.
   3387                     mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
   3388 
   3389                     mContentTop = mVoiceContentTop = mCurTop = mDockTop;
   3390                     mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
   3391                     mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
   3392                     mContentRight = mVoiceContentRight = mCurRight = mDockRight;
   3393 
   3394                     if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " +
   3395                         String.format(
   3396                             "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
   3397                             mDockLeft, mDockTop, mDockRight, mDockBottom,
   3398                             mContentLeft, mContentTop, mContentRight, mContentBottom,
   3399                             mCurLeft, mCurTop, mCurRight, mCurBottom));
   3400                 }
   3401                 if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
   3402                         && !statusBarTransient && !statusBarTranslucent
   3403                         && !mStatusBarController.wasRecentlyTranslucent()) {
   3404                     // If the opaque status bar is currently requested to be visible,
   3405                     // and not in the process of animating on or off, then
   3406                     // we can tell the app that it is covered by it.
   3407                     mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
   3408                 }
   3409                 if (mStatusBarController.checkHiddenLw()) {
   3410                     updateSysUiVisibility = true;
   3411                 }
   3412             }
   3413             if (updateSysUiVisibility) {
   3414                 updateSystemUiVisibilityLw();
   3415             }
   3416         }
   3417     }
   3418 
   3419     /** {@inheritDoc} */
   3420     @Override
   3421     public int getSystemDecorLayerLw() {
   3422         if (mStatusBar != null) return mStatusBar.getSurfaceLayer();
   3423         if (mNavigationBar != null) return mNavigationBar.getSurfaceLayer();
   3424         return 0;
   3425     }
   3426 
   3427     @Override
   3428     public void getContentRectLw(Rect r) {
   3429         r.set(mContentLeft, mContentTop, mContentRight, mContentBottom);
   3430     }
   3431 
   3432     void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
   3433             boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
   3434         if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
   3435             // Here's a special case: if this attached window is a panel that is
   3436             // above the dock window, and the window it is attached to is below
   3437             // the dock window, then the frames we computed for the window it is
   3438             // attached to can not be used because the dock is effectively part
   3439             // of the underlying window and the attached window is floating on top
   3440             // of the whole thing.  So, we ignore the attached window and explicitly
   3441             // compute the frames that would be appropriate without the dock.
   3442             df.left = of.left = cf.left = vf.left = mDockLeft;
   3443             df.top = of.top = cf.top = vf.top = mDockTop;
   3444             df.right = of.right = cf.right = vf.right = mDockRight;
   3445             df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom;
   3446         } else {
   3447             // The effective display frame of the attached window depends on
   3448             // whether it is taking care of insetting its content.  If not,
   3449             // we need to use the parent's content frame so that the entire
   3450             // window is positioned within that content.  Otherwise we can use
   3451             // the overscan frame and let the attached window take care of
   3452             // positioning its content appropriately.
   3453             if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
   3454                 // Set the content frame of the attached window to the parent's decor frame
   3455                 // (same as content frame when IME isn't present) if specifically requested by
   3456                 // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
   3457                 // Otherwise, use the overscan frame.
   3458                 cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
   3459                         ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
   3460             } else {
   3461                 // If the window is resizing, then we want to base the content
   3462                 // frame on our attached content frame to resize...  however,
   3463                 // things can be tricky if the attached window is NOT in resize
   3464                 // mode, in which case its content frame will be larger.
   3465                 // Ungh.  So to deal with that, make sure the content frame
   3466                 // we end up using is not covering the IM dock.
   3467                 cf.set(attached.getContentFrameLw());
   3468                 if (attached.isVoiceInteraction()) {
   3469                     if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft;
   3470                     if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop;
   3471                     if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight;
   3472                     if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom;
   3473                 } else if (attached.getSurfaceLayer() < mDockLayer) {
   3474                     if (cf.left < mContentLeft) cf.left = mContentLeft;
   3475                     if (cf.top < mContentTop) cf.top = mContentTop;
   3476                     if (cf.right > mContentRight) cf.right = mContentRight;
   3477                     if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
   3478                 }
   3479             }
   3480             df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
   3481             of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
   3482             vf.set(attached.getVisibleFrameLw());
   3483         }
   3484         // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
   3485         // window should be positioned relative to its parent or the entire
   3486         // screen.
   3487         pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
   3488                 ? attached.getFrameLw() : df);
   3489     }
   3490 
   3491     private void applyStableConstraints(int sysui, int fl, Rect r) {
   3492         if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
   3493             // If app is requesting a stable layout, don't let the
   3494             // content insets go below the stable values.
   3495             if ((fl & FLAG_FULLSCREEN) != 0) {
   3496                 if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft;
   3497                 if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop;
   3498                 if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight;
   3499                 if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom;
   3500             } else {
   3501                 if (r.left < mStableLeft) r.left = mStableLeft;
   3502                 if (r.top < mStableTop) r.top = mStableTop;
   3503                 if (r.right > mStableRight) r.right = mStableRight;
   3504                 if (r.bottom > mStableBottom) r.bottom = mStableBottom;
   3505             }
   3506         }
   3507     }
   3508 
   3509     /** {@inheritDoc} */
   3510     @Override
   3511     public void layoutWindowLw(WindowState win, WindowState attached) {
   3512         // we've already done the status bar
   3513         final WindowManager.LayoutParams attrs = win.getAttrs();
   3514         if ((win == mStatusBar && (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) == 0) ||
   3515                 win == mNavigationBar) {
   3516             return;
   3517         }
   3518         final boolean isDefaultDisplay = win.isDefaultDisplay();
   3519         final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
   3520                 (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
   3521         if (needsToOffsetInputMethodTarget) {
   3522             if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
   3523             offsetInputMethodWindowLw(mLastInputMethodWindow);
   3524         }
   3525 
   3526         final int fl = PolicyControl.getWindowFlags(win, attrs);
   3527         final int sim = attrs.softInputMode;
   3528         final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
   3529 
   3530         final Rect pf = mTmpParentFrame;
   3531         final Rect df = mTmpDisplayFrame;
   3532         final Rect of = mTmpOverscanFrame;
   3533         final Rect cf = mTmpContentFrame;
   3534         final Rect vf = mTmpVisibleFrame;
   3535         final Rect dcf = mTmpDecorFrame;
   3536         final Rect sf = mTmpStableFrame;
   3537         dcf.setEmpty();
   3538 
   3539         final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
   3540                 && mNavigationBar != null && mNavigationBar.isVisibleLw());
   3541 
   3542         final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
   3543 
   3544         if (isDefaultDisplay) {
   3545             sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom);
   3546         } else {
   3547             sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom);
   3548         }
   3549 
   3550         if (!isDefaultDisplay) {
   3551             if (attached != null) {
   3552                 // If this window is attached to another, our display
   3553                 // frame is the same as the one we are attached to.
   3554                 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
   3555             } else {
   3556                 // Give the window full screen.
   3557                 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
   3558                 pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
   3559                 pf.right = df.right = of.right = cf.right
   3560                         = mOverscanScreenLeft + mOverscanScreenWidth;
   3561                 pf.bottom = df.bottom = of.bottom = cf.bottom
   3562                         = mOverscanScreenTop + mOverscanScreenHeight;
   3563             }
   3564         } else  if (attrs.type == TYPE_INPUT_METHOD) {
   3565             pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
   3566             pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
   3567             pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
   3568             // IM dock windows layout below the nav bar...
   3569             pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
   3570             // ...with content insets above the nav bar
   3571             cf.bottom = vf.bottom = mStableBottom;
   3572             // IM dock windows always go to the bottom of the screen.
   3573             attrs.gravity = Gravity.BOTTOM;
   3574             mDockLayer = win.getSurfaceLayer();
   3575         } else if (win == mStatusBar && (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
   3576             pf.left = df.left = of.left = mUnrestrictedScreenLeft;
   3577             pf.top = df.top = of.top = mUnrestrictedScreenTop;
   3578             pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
   3579             pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop;
   3580             cf.left = vf.left = mStableLeft;
   3581             cf.top = vf.top = mStableTop;
   3582             cf.right = vf.right = mStableRight;
   3583             vf.bottom = mStableBottom;
   3584             cf.bottom = mContentBottom;
   3585         } else {
   3586 
   3587             // Default policy decor for the default display
   3588             dcf.left = mSystemLeft;
   3589             dcf.top = mSystemTop;
   3590             dcf.right = mSystemRight;
   3591             dcf.bottom = mSystemBottom;
   3592             final boolean inheritTranslucentDecor = (attrs.privateFlags
   3593                     & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0;
   3594             final boolean isAppWindow =
   3595                     attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW &&
   3596                     attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
   3597             final boolean topAtRest =
   3598                     win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
   3599             if (isAppWindow && !inheritTranslucentDecor && !topAtRest) {
   3600                 if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
   3601                         && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0
   3602                         && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
   3603                         && (fl & WindowManager.LayoutParams.
   3604                                 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
   3605                     // Ensure policy decor includes status bar
   3606                     dcf.top = mStableTop;
   3607                 }
   3608                 if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0
   3609                         && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
   3610                         && (fl & WindowManager.LayoutParams.
   3611                                 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
   3612                     // Ensure policy decor includes navigation bar
   3613                     dcf.bottom = mStableBottom;
   3614                     dcf.right = mStableRight;
   3615                 }
   3616             }
   3617 
   3618             if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
   3619                     == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
   3620                 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
   3621                             + "): IN_SCREEN, INSET_DECOR");
   3622                 // This is the case for a normal activity window: we want it
   3623                 // to cover all of the screen space, and it can take care of
   3624                 // moving its contents to account for screen decorations that
   3625                 // intrude into that space.
   3626                 if (attached != null) {
   3627                     // If this window is attached to another, our display
   3628                     // frame is the same as the one we are attached to.
   3629                     setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
   3630                 } else {
   3631                     if (attrs.type == TYPE_STATUS_BAR_PANEL
   3632                             || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
   3633                         // Status bar panels are the only windows who can go on top of
   3634                         // the status bar.  They are protected by the STATUS_BAR_SERVICE
   3635                         // permission, so they have the same privileges as the status
   3636                         // bar itself.
   3637                         //
   3638                         // However, they should still dodge the navigation bar if it exists.
   3639 
   3640                         pf.left = df.left = of.left = hasNavBar
   3641                                 ? mDockLeft : mUnrestrictedScreenLeft;
   3642                         pf.top = df.top = of.top = mUnrestrictedScreenTop;
   3643                         pf.right = df.right = of.right = hasNavBar
   3644                                 ? mRestrictedScreenLeft+mRestrictedScreenWidth
   3645                                 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
   3646                         pf.bottom = df.bottom = of.bottom = hasNavBar
   3647                                 ? mRestrictedScreenTop+mRestrictedScreenHeight
   3648                                 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
   3649 
   3650                         if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
   3651                                         "Laying out status bar window: (%d,%d - %d,%d)",
   3652                                         pf.left, pf.top, pf.right, pf.bottom));
   3653                     } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
   3654                             && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
   3655                             && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
   3656                         // Asking to layout into the overscan region, so give it that pure
   3657                         // unrestricted area.
   3658                         pf.left = df.left = of.left = mOverscanScreenLeft;
   3659                         pf.top = df.top = of.top = mOverscanScreenTop;
   3660                         pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth;
   3661                         pf.bottom = df.bottom = of.bottom = mOverscanScreenTop
   3662                                 + mOverscanScreenHeight;
   3663                     } else if (canHideNavigationBar()
   3664                             && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
   3665                             && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
   3666                             && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
   3667                         // Asking for layout as if the nav bar is hidden, lets the
   3668                         // application extend into the unrestricted overscan screen area.  We
   3669                         // only do this for application windows to ensure no window that
   3670                         // can be above the nav bar can do this.
   3671                         pf.left = df.left = mOverscanScreenLeft;
   3672                         pf.top = df.top = mOverscanScreenTop;
   3673                         pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
   3674                         pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
   3675                         // We need to tell the app about where the frame inside the overscan
   3676                         // is, so it can inset its content by that amount -- it didn't ask
   3677                         // to actually extend itself into the overscan region.
   3678                         of.left = mUnrestrictedScreenLeft;
   3679                         of.top = mUnrestrictedScreenTop;
   3680                         of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
   3681                         of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
   3682                     } else {
   3683                         pf.left = df.left = mRestrictedOverscanScreenLeft;
   3684                         pf.top = df.top = mRestrictedOverscanScreenTop;
   3685                         pf.right = df.right = mRestrictedOverscanScreenLeft
   3686                                 + mRestrictedOverscanScreenWidth;
   3687                         pf.bottom = df.bottom = mRestrictedOverscanScreenTop
   3688                                 + mRestrictedOverscanScreenHeight;
   3689                         // We need to tell the app about where the frame inside the overscan
   3690                         // is, so it can inset its content by that amount -- it didn't ask
   3691                         // to actually extend itself into the overscan region.
   3692                         of.left = mUnrestrictedScreenLeft;
   3693                         of.top = mUnrestrictedScreenTop;
   3694                         of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
   3695                         of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
   3696                     }
   3697 
   3698                     if ((fl & FLAG_FULLSCREEN) == 0) {
   3699                         if (win.isVoiceInteraction()) {
   3700                             cf.left = mVoiceContentLeft;
   3701                             cf.top = mVoiceContentTop;
   3702                             cf.right = mVoiceContentRight;
   3703                             cf.bottom = mVoiceContentBottom;
   3704                         } else {
   3705                             if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
   3706                                 cf.left = mDockLeft;
   3707                                 cf.top = mDockTop;
   3708                                 cf.right = mDockRight;
   3709                                 cf.bottom = mDockBottom;
   3710                             } else {
   3711                                 cf.left = mContentLeft;
   3712                                 cf.top = mContentTop;
   3713                                 cf.right = mContentRight;
   3714                                 cf.bottom = mContentBottom;
   3715                             }
   3716                         }
   3717                     } else {
   3718                         // Full screen windows are always given a layout that is as if the
   3719                         // status bar and other transient decors are gone.  This is to avoid
   3720                         // bad states when moving from a window that is not hding the
   3721                         // status bar to one that is.
   3722                         cf.left = mRestrictedScreenLeft;
   3723                         cf.top = mRestrictedScreenTop;
   3724                         cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
   3725                         cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight;
   3726                     }
   3727                     applyStableConstraints(sysUiFl, fl, cf);
   3728                     if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
   3729                         vf.left = mCurLeft;
   3730                         vf.top = mCurTop;
   3731                         vf.right = mCurRight;
   3732                         vf.bottom = mCurBottom;
   3733                     } else {
   3734                         vf.set(cf);
   3735                     }
   3736                 }
   3737             } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
   3738                     & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
   3739                             | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
   3740                 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
   3741                         "): IN_SCREEN");
   3742                 // A window that has requested to fill the entire screen just
   3743                 // gets everything, period.
   3744                 if (attrs.type == TYPE_STATUS_BAR_PANEL
   3745                         || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
   3746                     pf.left = df.left = of.left = cf.left = hasNavBar
   3747                             ? mDockLeft : mUnrestrictedScreenLeft;
   3748                     pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
   3749                     pf.right = df.right = of.right = cf.right = hasNavBar
   3750                                         ? mRestrictedScreenLeft+mRestrictedScreenWidth
   3751                                         : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
   3752                     pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar
   3753                                           ? mRestrictedScreenTop+mRestrictedScreenHeight
   3754                                           : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
   3755                     if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
   3756                                     "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
   3757                                     pf.left, pf.top, pf.right, pf.bottom));
   3758                 } else if (attrs.type == TYPE_NAVIGATION_BAR
   3759                         || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
   3760                     // The navigation bar has Real Ultimate Power.
   3761                     pf.left = df.left = of.left = mUnrestrictedScreenLeft;
   3762                     pf.top = df.top = of.top = mUnrestrictedScreenTop;
   3763                     pf.right = df.right = of.right = mUnrestrictedScreenLeft
   3764                             + mUnrestrictedScreenWidth;
   3765                     pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop
   3766                             + mUnrestrictedScreenHeight;
   3767                     if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
   3768                                     "Laying out navigation bar window: (%d,%d - %d,%d)",
   3769                                     pf.left, pf.top, pf.right, pf.bottom));
   3770                 } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
   3771                                 || attrs.type == TYPE_BOOT_PROGRESS)
   3772                         && ((fl & FLAG_FULLSCREEN) != 0)) {
   3773                     // Fullscreen secure system overlays get what they ask for.
   3774                     pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
   3775                     pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
   3776                     pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
   3777                             + mOverscanScreenWidth;
   3778                     pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
   3779                             + mOverscanScreenHeight;
   3780                 } else if (attrs.type == TYPE_BOOT_PROGRESS
   3781                         || attrs.type == TYPE_UNIVERSE_BACKGROUND) {
   3782                     // Boot progress screen always covers entire display.
   3783                     pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
   3784                     pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
   3785                     pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
   3786                             + mOverscanScreenWidth;
   3787                     pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
   3788                             + mOverscanScreenHeight;
   3789                 } else if (attrs.type == TYPE_WALLPAPER) {
   3790                     // The wallpaper also has Real Ultimate Power, but we want to tell
   3791                     // it about the overscan area.
   3792                     pf.left = df.left = mOverscanScreenLeft;
   3793                     pf.top = df.top = mOverscanScreenTop;
   3794                     pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
   3795                     pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
   3796                     of.left = cf.left = mUnrestrictedScreenLeft;
   3797                     of.top = cf.top = mUnrestrictedScreenTop;
   3798                     of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
   3799                     of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
   3800                 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
   3801                         && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
   3802                         && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
   3803                     // Asking to layout into the overscan region, so give it that pure
   3804                     // unrestricted area.
   3805                     pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
   3806                     pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
   3807                     pf.right = df.right = of.right = cf.right
   3808                             = mOverscanScreenLeft + mOverscanScreenWidth;
   3809                     pf.bottom = df.bottom = of.bottom = cf.bottom
   3810                             = mOverscanScreenTop + mOverscanScreenHeight;
   3811                 } else if (canHideNavigationBar()
   3812                         && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
   3813                         && (attrs.type == TYPE_STATUS_BAR
   3814                             || attrs.type == TYPE_TOAST
   3815                             || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
   3816                             && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
   3817                     // Asking for layout as if the nav bar is hidden, lets the
   3818                     // application extend into the unrestricted screen area.  We
   3819                     // only do this for application windows (or toasts) to ensure no window that
   3820                     // can be above the nav bar can do this.
   3821                     // XXX This assumes that an app asking for this will also
   3822                     // ask for layout in only content.  We can't currently figure out
   3823                     // what the screen would be if only laying out to hide the nav bar.
   3824                     pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
   3825                     pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
   3826                     pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft
   3827                             + mUnrestrictedScreenWidth;
   3828                     pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
   3829                             + mUnrestrictedScreenHeight;
   3830                 } else {
   3831                     pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
   3832                     pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
   3833                     pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
   3834                             + mRestrictedScreenWidth;
   3835                     pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
   3836                             + mRestrictedScreenHeight;
   3837                 }
   3838 
   3839                 applyStableConstraints(sysUiFl, fl, cf);
   3840 
   3841                 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
   3842                     vf.left = mCurLeft;
   3843                     vf.top = mCurTop;
   3844                     vf.right = mCurRight;
   3845                     vf.bottom = mCurBottom;
   3846                 } else {
   3847                     vf.set(cf);
   3848                 }
   3849             } else if (attached != null) {
   3850                 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
   3851                         "): attached to " + attached);
   3852                 // A child window should be placed inside of the same visible
   3853                 // frame that its parent had.
   3854                 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf);
   3855             } else {
   3856                 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
   3857                         "): normal window");
   3858                 // Otherwise, a normal window must be placed inside the content
   3859                 // of all screen decorations.
   3860                 if (attrs.type == TYPE_STATUS_BAR_PANEL) {
   3861                     // Status bar panels are the only windows who can go on top of
   3862                     // the status bar.  They are protected by the STATUS_BAR_SERVICE
   3863                     // permission, so they have the same privileges as the status
   3864                     // bar itself.
   3865                     pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
   3866                     pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
   3867                     pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
   3868                             + mRestrictedScreenWidth;
   3869                     pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
   3870                             + mRestrictedScreenHeight;
   3871                 } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT
   3872                         || attrs.type == TYPE_VOLUME_OVERLAY) {
   3873                     // These dialogs are stable to interim decor changes.
   3874                     pf.left = df.left = of.left = cf.left = mStableLeft;
   3875                     pf.top = df.top = of.top = cf.top = mStableTop;
   3876                     pf.right = df.right = of.right = cf.right = mStableRight;
   3877                     pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom;
   3878                 } else {
   3879                     pf.left = mContentLeft;
   3880                     pf.top = mContentTop;
   3881                     pf.right = mContentRight;
   3882                     pf.bottom = mContentBottom;
   3883                     if (win.isVoiceInteraction()) {
   3884                         df.left = of.left = cf.left = mVoiceContentLeft;
   3885                         df.top = of.top = cf.top = mVoiceContentTop;
   3886                         df.right = of.right = cf.right = mVoiceContentRight;
   3887                         df.bottom = of.bottom = cf.bottom = mVoiceContentBottom;
   3888                     } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
   3889                         df.left = of.left = cf.left = mDockLeft;
   3890                         df.top = of.top = cf.top = mDockTop;
   3891                         df.right = of.right = cf.right = mDockRight;
   3892                         df.bottom = of.bottom = cf.bottom = mDockBottom;
   3893                     } else {
   3894                         df.left = of.left = cf.left = mContentLeft;
   3895                         df.top = of.top = cf.top = mContentTop;
   3896                         df.right = of.right = cf.right = mContentRight;
   3897                         df.bottom = of.bottom = cf.bottom = mContentBottom;
   3898                     }
   3899                     if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
   3900                         vf.left = mCurLeft;
   3901                         vf.top = mCurTop;
   3902                         vf.right = mCurRight;
   3903                         vf.bottom = mCurBottom;
   3904                     } else {
   3905                         vf.set(cf);
   3906                     }
   3907                 }
   3908             }
   3909         }
   3910 
   3911         // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
   3912         if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR) {
   3913             df.left = df.top = -10000;
   3914             df.right = df.bottom = 10000;
   3915             if (attrs.type != TYPE_WALLPAPER) {
   3916                 of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
   3917                 of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
   3918             }
   3919         }
   3920 
   3921         if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
   3922                 + ": sim=#" + Integer.toHexString(sim)
   3923                 + " attach=" + attached + " type=" + attrs.type
   3924                 + String.format(" flags=0x%08x", fl)
   3925                 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
   3926                 + " of=" + of.toShortString()
   3927                 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
   3928                 + " dcf=" + dcf.toShortString()
   3929                 + " sf=" + sf.toShortString());
   3930 
   3931         win.computeFrameLw(pf, df, of, cf, vf, dcf, sf);
   3932 
   3933         // Dock windows carve out the bottom of the screen, so normal windows
   3934         // can't appear underneath them.
   3935         if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleOrBehindKeyguardLw()
   3936                 && !win.getGivenInsetsPendingLw()) {
   3937             setLastInputMethodWindowLw(null, null);
   3938             offsetInputMethodWindowLw(win);
   3939         }
   3940         if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleOrBehindKeyguardLw()
   3941                 && !win.getGivenInsetsPendingLw()) {
   3942             offsetVoiceInputWindowLw(win);
   3943         }
   3944     }
   3945 
   3946     private void offsetInputMethodWindowLw(WindowState win) {
   3947         int top = win.getContentFrameLw().top;
   3948         top += win.getGivenContentInsetsLw().top;
   3949         if (mContentBottom > top) {
   3950             mContentBottom = top;
   3951         }
   3952         if (mVoiceContentBottom > top) {
   3953             mVoiceContentBottom = top;
   3954         }
   3955         top = win.getVisibleFrameLw().top;
   3956         top += win.getGivenVisibleInsetsLw().top;
   3957         if (mCurBottom > top) {
   3958             mCurBottom = top;
   3959         }
   3960         if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
   3961                 + mDockBottom + " mContentBottom="
   3962                 + mContentBottom + " mCurBottom=" + mCurBottom);
   3963     }
   3964 
   3965     private void offsetVoiceInputWindowLw(WindowState win) {
   3966         final int gravity = win.getAttrs().gravity;
   3967         switch (gravity&((Gravity.AXIS_PULL_BEFORE|Gravity.AXIS_PULL_AFTER)
   3968                 << Gravity.AXIS_X_SHIFT)) {
   3969             case Gravity.AXIS_PULL_BEFORE<<Gravity.AXIS_X_SHIFT: {
   3970                 int right = win.getContentFrameLw().right - win.getGivenContentInsetsLw().right;
   3971                 if (mVoiceContentLeft < right) {
   3972                     mVoiceContentLeft = right;
   3973                 }
   3974             } break;
   3975             case Gravity.AXIS_PULL_AFTER<<Gravity.AXIS_X_SHIFT: {
   3976                 int left = win.getContentFrameLw().left - win.getGivenContentInsetsLw().left;
   3977                 if (mVoiceContentRight < left) {
   3978                     mVoiceContentRight = left;
   3979                 }
   3980             } break;
   3981         }
   3982         switch (gravity&((Gravity.AXIS_PULL_BEFORE|Gravity.AXIS_PULL_AFTER)
   3983                 << Gravity.AXIS_Y_SHIFT)) {
   3984             case Gravity.AXIS_PULL_BEFORE<<Gravity.AXIS_Y_SHIFT: {
   3985                 int bottom = win.getContentFrameLw().bottom - win.getGivenContentInsetsLw().bottom;
   3986                 if (mVoiceContentTop < bottom) {
   3987                     mVoiceContentTop = bottom;
   3988                 }
   3989             } break;
   3990             case Gravity.AXIS_PULL_AFTER<<Gravity.AXIS_Y_SHIFT: {
   3991                 int top = win.getContentFrameLw().top - win.getGivenContentInsetsLw().top;
   3992                 if (mVoiceContentBottom < top) {
   3993                     mVoiceContentBottom = top;
   3994                 }
   3995             } break;
   3996         }
   3997     }
   3998 
   3999     /** {@inheritDoc} */
   4000     @Override
   4001     public void finishLayoutLw() {
   4002         return;
   4003     }
   4004 
   4005     /** {@inheritDoc} */
   4006     @Override
   4007     public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
   4008         mTopFullscreenOpaqueWindowState = null;
   4009         mAppsToBeHidden.clear();
   4010         mAppsThatDismissKeyguard.clear();
   4011         mForceStatusBar = false;
   4012         mForceStatusBarFromKeyguard = false;
   4013         mForcingShowNavBar = false;
   4014         mForcingShowNavBarLayer = -1;
   4015 
   4016         mHideLockScreen = false;
   4017         mAllowLockscreenWhenOn = false;
   4018         mDismissKeyguard = DISMISS_KEYGUARD_NONE;
   4019         mShowingLockscreen = false;
   4020         mShowingDream = false;
   4021         mWinShowWhenLocked = null;
   4022         mKeyguardSecure = isKeyguardSecure();
   4023         mKeyguardSecureIncludingHidden = mKeyguardSecure
   4024                 && (mKeyguardDelegate != null && mKeyguardDelegate.isShowing());
   4025     }
   4026 
   4027     /** {@inheritDoc} */
   4028     @Override
   4029     public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
   4030             WindowState attached) {
   4031 
   4032         if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
   4033                 + win.isVisibleOrBehindKeyguardLw());
   4034         final int fl = PolicyControl.getWindowFlags(win, attrs);
   4035         if (mTopFullscreenOpaqueWindowState == null
   4036                 && win.isVisibleLw() && attrs.type == TYPE_INPUT_METHOD) {
   4037             mForcingShowNavBar = true;
   4038             mForcingShowNavBarLayer = win.getSurfaceLayer();
   4039         }
   4040         if (attrs.type == TYPE_STATUS_BAR && (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
   4041             mForceStatusBarFromKeyguard = true;
   4042         }
   4043         if (mTopFullscreenOpaqueWindowState == null &&
   4044                 win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
   4045             if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
   4046                 if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
   4047                     mForceStatusBarFromKeyguard = true;
   4048                 } else {
   4049                     mForceStatusBar = true;
   4050                 }
   4051             }
   4052             if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
   4053                 mShowingLockscreen = true;
   4054             }
   4055             boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
   4056                     && attrs.type < FIRST_SYSTEM_WINDOW;
   4057             if (attrs.type == TYPE_DREAM) {
   4058                 // If the lockscreen was showing when the dream started then wait
   4059                 // for the dream to draw before hiding the lockscreen.
   4060                 if (!mDreamingLockscreen
   4061                         || (win.isVisibleLw() && win.hasDrawnLw())) {
   4062                     mShowingDream = true;
   4063                     appWindow = true;
   4064                 }
   4065             }
   4066 
   4067             final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0;
   4068             final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0;
   4069             final IApplicationToken appToken = win.getAppToken();
   4070 
   4071             // For app windows that are not attached, we decide if all windows in the app they
   4072             // represent should be hidden or if we should hide the lockscreen. For attached app
   4073             // windows we defer the decision to the window it is attached to.
   4074             if (appWindow && attached == null) {
   4075                 if (showWhenLocked) {
   4076                     // Remove any previous windows with the same appToken.
   4077                     mAppsToBeHidden.remove(appToken);
   4078                     mAppsThatDismissKeyguard.remove(appToken);
   4079                     if (mAppsToBeHidden.isEmpty()) {
   4080                         if (dismissKeyguard && !mKeyguardSecure) {
   4081                             mAppsThatDismissKeyguard.add(appToken);
   4082                         } else {
   4083                             mWinShowWhenLocked = win;
   4084                             mHideLockScreen = true;
   4085                             mForceStatusBarFromKeyguard = false;
   4086                         }
   4087                     }
   4088                 } else if (dismissKeyguard) {
   4089                     if (mKeyguardSecure) {
   4090                         mAppsToBeHidden.add(appToken);
   4091                     } else {
   4092                         mAppsToBeHidden.remove(appToken);
   4093                     }
   4094                     mAppsThatDismissKeyguard.add(appToken);
   4095                 } else {
   4096                     mAppsToBeHidden.add(appToken);
   4097                 }
   4098                 if (attrs.x == 0 && attrs.y == 0
   4099                         && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
   4100                         && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
   4101                     if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
   4102                     mTopFullscreenOpaqueWindowState = win;
   4103                     if (!mAppsThatDismissKeyguard.isEmpty() &&
   4104                             mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
   4105                         if (DEBUG_LAYOUT) Slog.v(TAG,
   4106                                 "Setting mDismissKeyguard true by win " + win);
   4107                         mDismissKeyguard = mWinDismissingKeyguard == win ?
   4108                                 DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
   4109                         mWinDismissingKeyguard = win;
   4110                         mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure;
   4111                     } else if (mAppsToBeHidden.isEmpty() && showWhenLocked) {
   4112                         if (DEBUG_LAYOUT) Slog.v(TAG,
   4113                                 "Setting mHideLockScreen to true by win " + win);
   4114                         mHideLockScreen = true;
   4115                         mForceStatusBarFromKeyguard = false;
   4116                     }
   4117                     if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
   4118                         mAllowLockscreenWhenOn = true;
   4119                     }
   4120                 }
   4121 
   4122                 if (mWinShowWhenLocked != null &&
   4123                         mWinShowWhenLocked.getAppToken() != win.getAppToken()) {
   4124                     win.hideLw(false);
   4125                 }
   4126             }
   4127         }
   4128     }
   4129 
   4130     /** {@inheritDoc} */
   4131     @Override
   4132     public int finishPostLayoutPolicyLw() {
   4133         if (mWinShowWhenLocked != null &&
   4134                 mWinShowWhenLocked != mTopFullscreenOpaqueWindowState) {
   4135             // A dialog is dismissing the keyguard. Put the wallpaper behind it and hide the
   4136             // fullscreen window.
   4137             // TODO: Make sure FLAG_SHOW_WALLPAPER is restored when dialog is dismissed. Or not.
   4138             mWinShowWhenLocked.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
   4139             mTopFullscreenOpaqueWindowState.hideLw(false);
   4140             mTopFullscreenOpaqueWindowState = mWinShowWhenLocked;
   4141         }
   4142 
   4143         int changes = 0;
   4144         boolean topIsFullscreen = false;
   4145 
   4146         final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
   4147                 ? mTopFullscreenOpaqueWindowState.getAttrs()
   4148                 : null;
   4149 
   4150         // If we are not currently showing a dream then remember the current
   4151         // lockscreen state.  We will use this to determine whether the dream
   4152         // started while the lockscreen was showing and remember this state
   4153         // while the dream is showing.
   4154         if (!mShowingDream) {
   4155             mDreamingLockscreen = mShowingLockscreen;
   4156         }
   4157 
   4158         if (mStatusBar != null) {
   4159             if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
   4160                     + " forcefkg=" + mForceStatusBarFromKeyguard
   4161                     + " top=" + mTopFullscreenOpaqueWindowState);
   4162             if (mForceStatusBar || mForceStatusBarFromKeyguard) {
   4163                 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
   4164                 if (mStatusBarController.setBarShowingLw(true)) {
   4165                     changes |= FINISH_LAYOUT_REDO_LAYOUT;
   4166                 }
   4167                 // Maintain fullscreen layout until incoming animation is complete.
   4168                 topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
   4169                 // Transient status bar on the lockscreen is not allowed
   4170                 if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) {
   4171                     mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
   4172                             mLastSystemUiFlags, mLastSystemUiFlags);
   4173                 }
   4174             } else if (mTopFullscreenOpaqueWindowState != null) {
   4175                 final int fl = PolicyControl.getWindowFlags(null, lp);
   4176                 if (localLOGV) {
   4177                     Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
   4178                             + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw());
   4179                     Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
   4180                             + " lp.flags=0x" + Integer.toHexString(fl));
   4181                 }
   4182                 topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
   4183                         || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
   4184                 // The subtle difference between the window for mTopFullscreenOpaqueWindowState
   4185                 // and mTopIsFullscreen is that that mTopIsFullscreen is set only if the window
   4186                 // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
   4187                 // case though.
   4188                 if (mStatusBarController.isTransientShowing()) {
   4189                     if (mStatusBarController.setBarShowingLw(true)) {
   4190                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
   4191                     }
   4192                 } else if (topIsFullscreen) {
   4193                     if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
   4194                     if (mStatusBarController.setBarShowingLw(false)) {
   4195                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
   4196                     } else {
   4197                         if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
   4198                     }
   4199                 } else {
   4200                     if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
   4201                     if (mStatusBarController.setBarShowingLw(true)) {
   4202                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
   4203                     }
   4204                 }
   4205             }
   4206         }
   4207 
   4208         if (mTopIsFullscreen != topIsFullscreen) {
   4209             if (!topIsFullscreen) {
   4210                 // Force another layout when status bar becomes fully shown.
   4211                 changes |= FINISH_LAYOUT_REDO_LAYOUT;
   4212             }
   4213             mTopIsFullscreen = topIsFullscreen;
   4214         }
   4215 
   4216         // Hide the key guard if a visible window explicitly specifies that it wants to be
   4217         // displayed when the screen is locked.
   4218         if (mKeyguardDelegate != null && mStatusBar != null) {
   4219             if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
   4220                     + mHideLockScreen);
   4221             if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardSecure) {
   4222                 mKeyguardHidden = true;
   4223                 if (setKeyguardOccludedLw(true)) {
   4224                     changes |= FINISH_LAYOUT_REDO_LAYOUT
   4225                             | FINISH_LAYOUT_REDO_CONFIG
   4226                             | FINISH_LAYOUT_REDO_WALLPAPER;
   4227                 }
   4228                 if (mKeyguardDelegate.isShowing()) {
   4229                     mHandler.post(new Runnable() {
   4230                         @Override
   4231                         public void run() {
   4232                             mKeyguardDelegate.keyguardDone(false, false);
   4233                         }
   4234                     });
   4235                 }
   4236             } else if (mHideLockScreen) {
   4237                 mKeyguardHidden = true;
   4238                 if (setKeyguardOccludedLw(true)) {
   4239                     changes |= FINISH_LAYOUT_REDO_LAYOUT
   4240                             | FINISH_LAYOUT_REDO_CONFIG
   4241                             | FINISH_LAYOUT_REDO_WALLPAPER;
   4242                 }
   4243             } else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) {
   4244                 // This is the case of keyguard isSecure() and not mHideLockScreen.
   4245                 if (mDismissKeyguard == DISMISS_KEYGUARD_START) {
   4246                     // Only launch the next keyguard unlock window once per window.
   4247                     mKeyguardHidden = false;
   4248                     if (setKeyguardOccludedLw(false)) {
   4249                         changes |= FINISH_LAYOUT_REDO_LAYOUT
   4250                                 | FINISH_LAYOUT_REDO_CONFIG
   4251                                 | FINISH_LAYOUT_REDO_WALLPAPER;
   4252                     }
   4253                     mHandler.post(new Runnable() {
   4254                         @Override
   4255                         public void run() {
   4256                             mKeyguardDelegate.dismiss();
   4257                         }
   4258                     });
   4259                 }
   4260             } else {
   4261                 mWinDismissingKeyguard = null;
   4262                 mKeyguardHidden = false;
   4263                 if (setKeyguardOccludedLw(false)) {
   4264                     changes |= FINISH_LAYOUT_REDO_LAYOUT
   4265                             | FINISH_LAYOUT_REDO_CONFIG
   4266                             | FINISH_LAYOUT_REDO_WALLPAPER;
   4267                 }
   4268             }
   4269         }
   4270 
   4271         if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
   4272             // If the navigation bar has been hidden or shown, we need to do another
   4273             // layout pass to update that window.
   4274             changes |= FINISH_LAYOUT_REDO_LAYOUT;
   4275         }
   4276 
   4277         // update since mAllowLockscreenWhenOn might have changed
   4278         updateLockScreenTimeout();
   4279         return changes;
   4280     }
   4281 
   4282     /**
   4283      * Updates the occluded state of the Keyguard.
   4284      *
   4285      * @return Whether the flags have changed and we have to redo the layout.
   4286      */
   4287     private boolean setKeyguardOccludedLw(boolean isOccluded) {
   4288         boolean wasOccluded = mKeyguardOccluded;
   4289         boolean showing = mKeyguardDelegate.isShowing();
   4290         if (wasOccluded && !isOccluded && showing) {
   4291             mKeyguardOccluded = false;
   4292             mKeyguardDelegate.setOccluded(false);
   4293             mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
   4294             mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
   4295             return true;
   4296         } else if (!wasOccluded && isOccluded && showing) {
   4297             mKeyguardOccluded = true;
   4298             mKeyguardDelegate.setOccluded(true);
   4299             mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
   4300             mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
   4301             return true;
   4302         } else {
   4303             return false;
   4304         }
   4305     }
   4306 
   4307     private boolean isStatusBarKeyguard() {
   4308         return mStatusBar != null
   4309                 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
   4310     }
   4311 
   4312     @Override
   4313     public boolean allowAppAnimationsLw() {
   4314         if (isStatusBarKeyguard() || mShowingDream) {
   4315             // If keyguard or dreams is currently visible, no reason to animate behind it.
   4316             return false;
   4317         }
   4318         return true;
   4319     }
   4320 
   4321     @Override
   4322     public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
   4323         mFocusedWindow = newFocus;
   4324         if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
   4325             // If the navigation bar has been hidden or shown, we need to do another
   4326             // layout pass to update that window.
   4327             return FINISH_LAYOUT_REDO_LAYOUT;
   4328         }
   4329         return 0;
   4330     }
   4331 
   4332     /** {@inheritDoc} */
   4333     @Override
   4334     public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
   4335         // lid changed state
   4336         final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
   4337         if (newLidState == mLidState) {
   4338             return;
   4339         }
   4340 
   4341         mLidState = newLidState;
   4342         applyLidSwitchState();
   4343         updateRotation(true);
   4344 
   4345         if (lidOpen) {
   4346             wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch);
   4347         } else if (!mLidControlsSleep) {
   4348             mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
   4349         }
   4350     }
   4351 
   4352     @Override
   4353     public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
   4354         int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
   4355         if (mCameraLensCoverState == lensCoverState) {
   4356             return;
   4357         }
   4358         if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
   4359                 lensCoverState == CAMERA_LENS_UNCOVERED) {
   4360             Intent intent;
   4361             final boolean keyguardActive = mKeyguardDelegate == null ? false :
   4362                     mKeyguardDelegate.isShowing();
   4363             if (keyguardActive) {
   4364                 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
   4365             } else {
   4366                 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
   4367             }
   4368             wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens);
   4369             startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
   4370         }
   4371         mCameraLensCoverState = lensCoverState;
   4372     }
   4373 
   4374     void setHdmiPlugged(boolean plugged) {
   4375         if (mHdmiPlugged != plugged) {
   4376             mHdmiPlugged = plugged;
   4377             updateRotation(true, true);
   4378             Intent intent = new Intent(ACTION_HDMI_PLUGGED);
   4379             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
   4380             intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
   4381             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
   4382         }
   4383     }
   4384 
   4385     void initializeHdmiState() {
   4386         boolean plugged = false;
   4387         // watch for HDMI plug messages if the hdmi switch exists
   4388         if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
   4389             mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
   4390 
   4391             final String filename = "/sys/class/switch/hdmi/state";
   4392             FileReader reader = null;
   4393             try {
   4394                 reader = new FileReader(filename);
   4395                 char[] buf = new char[15];
   4396                 int n = reader.read(buf);
   4397                 if (n > 1) {
   4398                     plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
   4399                 }
   4400             } catch (IOException ex) {
   4401                 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
   4402             } catch (NumberFormatException ex) {
   4403                 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
   4404             } finally {
   4405                 if (reader != null) {
   4406                     try {
   4407                         reader.close();
   4408                     } catch (IOException ex) {
   4409                     }
   4410                 }
   4411             }
   4412         }
   4413         // This dance forces the code in setHdmiPlugged to run.
   4414         // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
   4415         mHdmiPlugged = !plugged;
   4416         setHdmiPlugged(!mHdmiPlugged);
   4417     }
   4418 
   4419     final Object mScreenshotLock = new Object();
   4420     ServiceConnection mScreenshotConnection = null;
   4421 
   4422     final Runnable mScreenshotTimeout = new Runnable() {
   4423         @Override public void run() {
   4424             synchronized (mScreenshotLock) {
   4425                 if (mScreenshotConnection != null) {
   4426                     mContext.unbindService(mScreenshotConnection);
   4427                     mScreenshotConnection = null;
   4428                 }
   4429             }
   4430         }
   4431     };
   4432 
   4433     // Assume this is called from the Handler thread.
   4434     private void takeScreenshot() {
   4435         synchronized (mScreenshotLock) {
   4436             if (mScreenshotConnection != null) {
   4437                 return;
   4438             }
   4439             ComponentName cn = new ComponentName("com.android.systemui",
   4440                     "com.android.systemui.screenshot.TakeScreenshotService");
   4441             Intent intent = new Intent();
   4442             intent.setComponent(cn);
   4443             ServiceConnection conn = new ServiceConnection() {
   4444                 @Override
   4445                 public void onServiceConnected(ComponentName name, IBinder service) {
   4446                     synchronized (mScreenshotLock) {
   4447                         if (mScreenshotConnection != this) {
   4448                             return;
   4449                         }
   4450                         Messenger messenger = new Messenger(service);
   4451                         Message msg = Message.obtain(null, 1);
   4452                         final ServiceConnection myConn = this;
   4453                         Handler h = new Handler(mHandler.getLooper()) {
   4454                             @Override
   4455                             public void handleMessage(Message msg) {
   4456                                 synchronized (mScreenshotLock) {
   4457                                     if (mScreenshotConnection == myConn) {
   4458                                         mContext.unbindService(mScreenshotConnection);
   4459                                         mScreenshotConnection = null;
   4460                                         mHandler.removeCallbacks(mScreenshotTimeout);
   4461                                     }
   4462                                 }
   4463                             }
   4464                         };
   4465                         msg.replyTo = new Messenger(h);
   4466                         msg.arg1 = msg.arg2 = 0;
   4467                         if (mStatusBar != null && mStatusBar.isVisibleLw())
   4468                             msg.arg1 = 1;
   4469                         if (mNavigationBar != null && mNavigationBar.isVisibleLw())
   4470                             msg.arg2 = 1;
   4471                         try {
   4472                             messenger.send(msg);
   4473                         } catch (RemoteException e) {
   4474                         }
   4475                     }
   4476                 }
   4477                 @Override
   4478                 public void onServiceDisconnected(ComponentName name) {}
   4479             };
   4480             if (mContext.bindServiceAsUser(
   4481                     intent, conn, Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) {
   4482                 mScreenshotConnection = conn;
   4483                 mHandler.postDelayed(mScreenshotTimeout, 10000);
   4484             }
   4485         }
   4486     }
   4487 
   4488     /** {@inheritDoc} */
   4489     @Override
   4490     public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
   4491         if (!mSystemBooted) {
   4492             // If we have not yet booted, don't let key events do anything.
   4493             return 0;
   4494         }
   4495 
   4496         final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
   4497         final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
   4498         final boolean canceled = event.isCanceled();
   4499         final int keyCode = event.getKeyCode();
   4500 
   4501         final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
   4502 
   4503         // If screen is off then we treat the case where the keyguard is open but hidden
   4504         // the same as if it were open and in front.
   4505         // This will prevent any keys other than the power button from waking the screen
   4506         // when the keyguard is hidden by another activity.
   4507         final boolean keyguardActive = (mKeyguardDelegate == null ? false :
   4508                                             (interactive ?
   4509                                                 isKeyguardShowingAndNotOccluded() :
   4510                                                 mKeyguardDelegate.isShowing()));
   4511 
   4512         if (DEBUG_INPUT) {
   4513             Log.d(TAG, "interceptKeyTq keycode=" + keyCode
   4514                     + " interactive=" + interactive + " keyguardActive=" + keyguardActive
   4515                     + " policyFlags=" + Integer.toHexString(policyFlags));
   4516         }
   4517 
   4518         // Basic policy based on interactive state.
   4519         int result;
   4520         boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
   4521                 || event.isWakeKey();
   4522         if (interactive || (isInjected && !isWakeKey)) {
   4523             // When the device is interactive or the key is injected pass the
   4524             // key to the application.
   4525             result = ACTION_PASS_TO_USER;
   4526             isWakeKey = false;
   4527         } else if (!interactive && shouldDispatchInputWhenNonInteractive()) {
   4528             // If we're currently dozing with the screen on and the keyguard showing, pass the key
   4529             // to the application but preserve its wake key status to make sure we still move
   4530             // from dozing to fully interactive if we would normally go from off to fully
   4531             // interactive.
   4532             result = ACTION_PASS_TO_USER;
   4533         } else {
   4534             // When the screen is off and the key is not injected, determine whether
   4535             // to wake the device but don't pass the key to the application.
   4536             result = 0;
   4537             if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
   4538                 isWakeKey = false;
   4539             }
   4540         }
   4541 
   4542         // If the key would be handled globally, just return the result, don't worry about special
   4543         // key processing.
   4544         if (isValidGlobalKey(keyCode)
   4545                 && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
   4546             if (isWakeKey) {
   4547                 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey);
   4548             }
   4549             return result;
   4550         }
   4551 
   4552         boolean useHapticFeedback = down
   4553                 && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
   4554                 && event.getRepeatCount() == 0;
   4555 
   4556         // Handle special keys.
   4557         switch (keyCode) {
   4558             case KeyEvent.KEYCODE_VOLUME_DOWN:
   4559             case KeyEvent.KEYCODE_VOLUME_UP:
   4560             case KeyEvent.KEYCODE_VOLUME_MUTE: {
   4561                 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
   4562                     if (down) {
   4563                         if (interactive && !mScreenshotChordVolumeDownKeyTriggered
   4564                                 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
   4565                             mScreenshotChordVolumeDownKeyTriggered = true;
   4566                             mScreenshotChordVolumeDownKeyTime = event.getDownTime();
   4567                             mScreenshotChordVolumeDownKeyConsumed = false;
   4568                             cancelPendingPowerKeyAction();
   4569                             interceptScreenshotChord();
   4570                         }
   4571                     } else {
   4572                         mScreenshotChordVolumeDownKeyTriggered = false;
   4573                         cancelPendingScreenshotChordAction();
   4574                     }
   4575                 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
   4576                     if (down) {
   4577                         if (interactive && !mScreenshotChordVolumeUpKeyTriggered
   4578                                 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
   4579                             mScreenshotChordVolumeUpKeyTriggered = true;
   4580                             cancelPendingPowerKeyAction();
   4581                             cancelPendingScreenshotChordAction();
   4582                         }
   4583                     } else {
   4584                         mScreenshotChordVolumeUpKeyTriggered = false;
   4585                         cancelPendingScreenshotChordAction();
   4586                     }
   4587                 }
   4588                 if (down) {
   4589                     TelecomManager telecomManager = getTelecommService();
   4590                     if (telecomManager != null) {
   4591                         if (telecomManager.isRinging()) {
   4592                             // If an incoming call is ringing, either VOLUME key means
   4593                             // "silence ringer".  We handle these keys here, rather than
   4594                             // in the InCallScreen, to make sure we'll respond to them
   4595                             // even if the InCallScreen hasn't come to the foreground yet.
   4596                             // Look for the DOWN event here, to agree with the "fallback"
   4597                             // behavior in the InCallScreen.
   4598                             Log.i(TAG, "interceptKeyBeforeQueueing:"
   4599                                   + " VOLUME key-down while ringing: Silence ringer!");
   4600 
   4601                             // Silence the ringer.  (It's safe to call this
   4602                             // even if the ringer has already been silenced.)
   4603                             telecomManager.silenceRinger();
   4604 
   4605                             // And *don't* pass this key thru to the current activity
   4606                             // (which is probably the InCallScreen.)
   4607                             result &= ~ACTION_PASS_TO_USER;
   4608                             break;
   4609                         }
   4610                         if (telecomManager.isInCall()
   4611                                 && (result & ACTION_PASS_TO_USER) == 0) {
   4612                             // If we are in call but we decided not to pass the key to
   4613                             // the application, just pass it to the session service.
   4614 
   4615                             MediaSessionLegacyHelper.getHelper(mContext)
   4616                                     .sendVolumeKeyEvent(event, false);
   4617                             break;
   4618                         }
   4619                     }
   4620 
   4621                     if ((result & ACTION_PASS_TO_USER) == 0) {
   4622                         // If we aren't passing to the user and no one else
   4623                         // handled it send it to the session manager to figure
   4624                         // out.
   4625                         MediaSessionLegacyHelper.getHelper(mContext)
   4626                                 .sendVolumeKeyEvent(event, true);
   4627                         break;
   4628                     }
   4629                 }
   4630                 break;
   4631             }
   4632 
   4633             case KeyEvent.KEYCODE_ENDCALL: {
   4634                 result &= ~ACTION_PASS_TO_USER;
   4635                 if (down) {
   4636                     TelecomManager telecomManager = getTelecommService();
   4637                     boolean hungUp = false;
   4638                     if (telecomManager != null) {
   4639                         hungUp = telecomManager.endCall();
   4640                     }
   4641                     if (interactive && !hungUp) {
   4642                         mEndCallKeyHandled = false;
   4643                         mHandler.postDelayed(mEndCallLongPress,
   4644                                 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
   4645                     } else {
   4646                         mEndCallKeyHandled = true;
   4647                     }
   4648                 } else {
   4649                     if (!mEndCallKeyHandled) {
   4650                         mHandler.removeCallbacks(mEndCallLongPress);
   4651                         if (!canceled) {
   4652                             if ((mEndcallBehavior
   4653                                     & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
   4654                                 if (goHome()) {
   4655                                     break;
   4656                                 }
   4657                             }
   4658                             if ((mEndcallBehavior
   4659                                     & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
   4660                                 mPowerManager.goToSleep(event.getEventTime(),
   4661                                         PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
   4662                                 isWakeKey = false;
   4663                             }
   4664                         }
   4665                     }
   4666                 }
   4667                 break;
   4668             }
   4669 
   4670             case KeyEvent.KEYCODE_POWER: {
   4671                 result &= ~ACTION_PASS_TO_USER;
   4672                 isWakeKey = false; // wake-up will be handled separately
   4673                 if (down) {
   4674                     interceptPowerKeyDown(event, interactive);
   4675                 } else {
   4676                     interceptPowerKeyUp(event, interactive, canceled);
   4677                 }
   4678                 break;
   4679             }
   4680 
   4681             case KeyEvent.KEYCODE_SLEEP: {
   4682                 result &= ~ACTION_PASS_TO_USER;
   4683                 if (!mPowerManager.isInteractive()) {
   4684                     useHapticFeedback = false; // suppress feedback if already non-interactive
   4685                 }
   4686                 mPowerManager.goToSleep(event.getEventTime(),
   4687                         PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
   4688                 isWakeKey = false;
   4689                 break;
   4690             }
   4691 
   4692             case KeyEvent.KEYCODE_WAKEUP: {
   4693                 result &= ~ACTION_PASS_TO_USER;
   4694                 isWakeKey = true;
   4695                 break;
   4696             }
   4697 
   4698             case KeyEvent.KEYCODE_MEDIA_PLAY:
   4699             case KeyEvent.KEYCODE_MEDIA_PAUSE:
   4700             case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
   4701             case KeyEvent.KEYCODE_HEADSETHOOK:
   4702             case KeyEvent.KEYCODE_MUTE:
   4703             case KeyEvent.KEYCODE_MEDIA_STOP:
   4704             case KeyEvent.KEYCODE_MEDIA_NEXT:
   4705             case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
   4706             case KeyEvent.KEYCODE_MEDIA_REWIND:
   4707             case KeyEvent.KEYCODE_MEDIA_RECORD:
   4708             case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
   4709             case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
   4710                 if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
   4711                     // If the global session is active pass all media keys to it
   4712                     // instead of the active window.
   4713                     result &= ~ACTION_PASS_TO_USER;
   4714                 }
   4715                 if ((result & ACTION_PASS_TO_USER) == 0) {
   4716                     // Only do this if we would otherwise not pass it to the user. In that
   4717                     // case, the PhoneWindow class will do the same thing, except it will
   4718                     // only do it if the showing app doesn't process the key on its own.
   4719                     // Note that we need to make a copy of the key event here because the
   4720                     // original key event will be recycled when we return.
   4721                     mBroadcastWakeLock.acquire();
   4722                     Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
   4723                             new KeyEvent(event));
   4724                     msg.setAsynchronous(true);
   4725                     msg.sendToTarget();
   4726                 }
   4727                 break;
   4728             }
   4729 
   4730             case KeyEvent.KEYCODE_CALL: {
   4731                 if (down) {
   4732                     TelecomManager telecomManager = getTelecommService();
   4733                     if (telecomManager != null) {
   4734                         if (telecomManager.isRinging()) {
   4735                             Log.i(TAG, "interceptKeyBeforeQueueing:"
   4736                                   + " CALL key-down while ringing: Answer the call!");
   4737                             telecomManager.acceptRingingCall();
   4738 
   4739                             // And *don't* pass this key thru to the current activity
   4740                             // (which is presumably the InCallScreen.)
   4741                             result &= ~ACTION_PASS_TO_USER;
   4742                         }
   4743                     }
   4744                 }
   4745                 break;
   4746             }
   4747             case KeyEvent.KEYCODE_VOICE_ASSIST: {
   4748                 // Only do this if we would otherwise not pass it to the user. In that case,
   4749                 // interceptKeyBeforeDispatching would apply a similar but different policy in
   4750                 // order to invoke voice assist actions. Note that we need to make a copy of the
   4751                 // key event here because the original key event will be recycled when we return.
   4752                 if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
   4753                     mBroadcastWakeLock.acquire();
   4754                     Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
   4755                             keyguardActive ? 1 : 0, 0);
   4756                     msg.setAsynchronous(true);
   4757                     msg.sendToTarget();
   4758                 }
   4759             }
   4760         }
   4761 
   4762         if (useHapticFeedback) {
   4763             performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
   4764         }
   4765 
   4766         if (isWakeKey) {
   4767             wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey);
   4768         }
   4769 
   4770         return result;
   4771     }
   4772 
   4773     /**
   4774      * Returns true if the key can have global actions attached to it.
   4775      * We reserve all power management keys for the system since they require
   4776      * very careful handling.
   4777      */
   4778     private static boolean isValidGlobalKey(int keyCode) {
   4779         switch (keyCode) {
   4780             case KeyEvent.KEYCODE_POWER:
   4781             case KeyEvent.KEYCODE_WAKEUP:
   4782             case KeyEvent.KEYCODE_SLEEP:
   4783                 return false;
   4784             default:
   4785                 return true;
   4786         }
   4787     }
   4788 
   4789     /**
   4790      * When the screen is off we ignore some keys that might otherwise typically
   4791      * be considered wake keys.  We filter them out here.
   4792      *
   4793      * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
   4794      * is always considered a wake key.
   4795      */
   4796     private boolean isWakeKeyWhenScreenOff(int keyCode) {
   4797         switch (keyCode) {
   4798             // ignore volume keys unless docked
   4799             case KeyEvent.KEYCODE_VOLUME_UP:
   4800             case KeyEvent.KEYCODE_VOLUME_DOWN:
   4801             case KeyEvent.KEYCODE_VOLUME_MUTE:
   4802                 return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
   4803 
   4804             // ignore media and camera keys
   4805             case KeyEvent.KEYCODE_MUTE:
   4806             case KeyEvent.KEYCODE_HEADSETHOOK:
   4807             case KeyEvent.KEYCODE_MEDIA_PLAY:
   4808             case KeyEvent.KEYCODE_MEDIA_PAUSE:
   4809             case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
   4810             case KeyEvent.KEYCODE_MEDIA_STOP:
   4811             case KeyEvent.KEYCODE_MEDIA_NEXT:
   4812             case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
   4813             case KeyEvent.KEYCODE_MEDIA_REWIND:
   4814             case KeyEvent.KEYCODE_MEDIA_RECORD:
   4815             case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
   4816             case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
   4817             case KeyEvent.KEYCODE_CAMERA:
   4818                 return false;
   4819         }
   4820         return true;
   4821     }
   4822 
   4823 
   4824     /** {@inheritDoc} */
   4825     @Override
   4826     public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
   4827         if ((policyFlags & FLAG_WAKE) != 0) {
   4828             if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion)) {
   4829                 return 0;
   4830             }
   4831         }
   4832 
   4833         if (shouldDispatchInputWhenNonInteractive()) {
   4834             return ACTION_PASS_TO_USER;
   4835         }
   4836 
   4837         // If we have not passed the action up and we are in theater mode without dreaming,
   4838         // there will be no dream to intercept the touch and wake into ambient.  The device should
   4839         // wake up in this case.
   4840         if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
   4841             wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming);
   4842         }
   4843 
   4844         return 0;
   4845     }
   4846 
   4847     private boolean shouldDispatchInputWhenNonInteractive() {
   4848         // Send events to keyguard while the screen is on.
   4849         if (isKeyguardShowingAndNotOccluded() && mDisplay != null
   4850                 && mDisplay.getState() != Display.STATE_OFF) {
   4851             return true;
   4852         }
   4853 
   4854         // Send events to a dozing dream even if the screen is off since the dream
   4855         // is in control of the state of the screen.
   4856         IDreamManager dreamManager = getDreamManager();
   4857 
   4858         try {
   4859             if (dreamManager != null && dreamManager.isDreaming()) {
   4860                 return true;
   4861             }
   4862         } catch (RemoteException e) {
   4863             Slog.e(TAG, "RemoteException when checking if dreaming", e);
   4864         }
   4865 
   4866         // Otherwise, consume events since the user can't see what is being
   4867         // interacted with.
   4868         return false;
   4869     }
   4870 
   4871     void dispatchMediaKeyWithWakeLock(KeyEvent event) {
   4872         if (DEBUG_INPUT) {
   4873             Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
   4874         }
   4875 
   4876         if (mHavePendingMediaKeyRepeatWithWakeLock) {
   4877             if (DEBUG_INPUT) {
   4878                 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
   4879             }
   4880 
   4881             mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
   4882             mHavePendingMediaKeyRepeatWithWakeLock = false;
   4883             mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
   4884         }
   4885 
   4886         dispatchMediaKeyWithWakeLockToAudioService(event);
   4887 
   4888         if (event.getAction() == KeyEvent.ACTION_DOWN
   4889                 && event.getRepeatCount() == 0) {
   4890             mHavePendingMediaKeyRepeatWithWakeLock = true;
   4891 
   4892             Message msg = mHandler.obtainMessage(
   4893                     MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
   4894             msg.setAsynchronous(true);
   4895             mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
   4896         } else {
   4897             mBroadcastWakeLock.release();
   4898         }
   4899     }
   4900 
   4901     void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
   4902         mHavePendingMediaKeyRepeatWithWakeLock = false;
   4903 
   4904         KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
   4905                 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
   4906         if (DEBUG_INPUT) {
   4907             Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
   4908         }
   4909 
   4910         dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
   4911         mBroadcastWakeLock.release();
   4912     }
   4913 
   4914     void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
   4915         if (ActivityManagerNative.isSystemReady()) {
   4916             MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
   4917         }
   4918     }
   4919 
   4920     void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
   4921         Intent voiceIntent =
   4922             new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
   4923         voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
   4924         startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
   4925         mBroadcastWakeLock.release();
   4926     }
   4927 
   4928     BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
   4929         @Override
   4930         public void onReceive(Context context, Intent intent) {
   4931             if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
   4932                 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
   4933                         Intent.EXTRA_DOCK_STATE_UNDOCKED);
   4934             } else {
   4935                 try {
   4936                     IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
   4937                             ServiceManager.getService(Context.UI_MODE_SERVICE));
   4938                     mUiMode = uiModeService.getCurrentModeType();
   4939                 } catch (RemoteException e) {
   4940                 }
   4941             }
   4942             updateRotation(true);
   4943             synchronized (mLock) {
   4944                 updateOrientationListenerLp();
   4945             }
   4946         }
   4947     };
   4948 
   4949     BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
   4950         @Override
   4951         public void onReceive(Context context, Intent intent) {
   4952             if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
   4953                 if (mKeyguardDelegate != null) {
   4954                     mKeyguardDelegate.onDreamingStarted();
   4955                 }
   4956             } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
   4957                 if (mKeyguardDelegate != null) {
   4958                     mKeyguardDelegate.onDreamingStopped();
   4959                 }
   4960             }
   4961         }
   4962     };
   4963 
   4964     BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
   4965         @Override
   4966         public void onReceive(Context context, Intent intent) {
   4967             if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
   4968                 // tickle the settings observer: this first ensures that we're
   4969                 // observing the relevant settings for the newly-active user,
   4970                 // and then updates our own bookkeeping based on the now-
   4971                 // current user.
   4972                 mSettingsObserver.onChange(false);
   4973 
   4974                 // force a re-application of focused window sysui visibility.
   4975                 // the window may never have been shown for this user
   4976                 // e.g. the keyguard when going through the new-user setup flow
   4977                 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
   4978                     mLastSystemUiFlags = 0;
   4979                     updateSystemUiVisibilityLw();
   4980                 }
   4981             }
   4982         }
   4983     };
   4984 
   4985     private final Runnable mRequestTransientNav = new Runnable() {
   4986         @Override
   4987         public void run() {
   4988             requestTransientBars(mNavigationBar);
   4989         }
   4990     };
   4991 
   4992     private void requestTransientBars(WindowState swipeTarget) {
   4993         synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
   4994             if (!isUserSetupComplete()) {
   4995                 // Swipe-up for navigation bar is disabled during setup
   4996                 return;
   4997             }
   4998             boolean sb = mStatusBarController.checkShowTransientBarLw();
   4999             boolean nb = mNavigationBarController.checkShowTransientBarLw();
   5000             if (sb || nb) {
   5001                 WindowState barTarget = sb ? mStatusBar : mNavigationBar;
   5002                 if (sb ^ nb && barTarget != swipeTarget) {
   5003                     if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
   5004                     return;
   5005                 }
   5006                 if (sb) mStatusBarController.showTransient();
   5007                 if (nb) mNavigationBarController.showTransient();
   5008                 mImmersiveModeConfirmation.confirmCurrentPrompt();
   5009                 updateSystemUiVisibilityLw();
   5010             }
   5011         }
   5012     }
   5013 
   5014     // Called on the PowerManager's Notifier thread.
   5015     @Override
   5016     public void goingToSleep(int why) {
   5017         EventLog.writeEvent(70000, 0);
   5018         if (DEBUG_WAKEUP) Slog.i(TAG, "Going to sleep...");
   5019 
   5020         // We must get this work done here because the power manager will drop
   5021         // the wake lock and let the system suspend once this function returns.
   5022         synchronized (mLock) {
   5023             mAwake = false;
   5024             mKeyguardDrawComplete = false;
   5025             updateWakeGestureListenerLp();
   5026             updateOrientationListenerLp();
   5027             updateLockScreenTimeout();
   5028         }
   5029 
   5030         if (mKeyguardDelegate != null) {
   5031             mKeyguardDelegate.onScreenTurnedOff(why);
   5032         }
   5033     }
   5034 
   5035     private void wakeUpFromPowerKey(long eventTime) {
   5036         wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey);
   5037     }
   5038 
   5039     private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode) {
   5040         if (!wakeInTheaterMode && isTheaterModeEnabled()) {
   5041             return false;
   5042         }
   5043 
   5044         mPowerManager.wakeUp(wakeTime);
   5045         return true;
   5046     }
   5047 
   5048     // Called on the PowerManager's Notifier thread.
   5049     @Override
   5050     public void wakingUp() {
   5051         EventLog.writeEvent(70000, 1);
   5052         if (DEBUG_WAKEUP) Slog.i(TAG, "Waking up...");
   5053 
   5054         // Since goToSleep performs these functions synchronously, we must
   5055         // do the same here.  We cannot post this work to a handler because
   5056         // that might cause it to become reordered with respect to what
   5057         // may happen in a future call to goToSleep.
   5058         synchronized (mLock) {
   5059             mAwake = true;
   5060             mKeyguardDrawComplete = false;
   5061             if (mKeyguardDelegate != null) {
   5062                 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
   5063                 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
   5064             }
   5065 
   5066             updateWakeGestureListenerLp();
   5067             updateOrientationListenerLp();
   5068             updateLockScreenTimeout();
   5069         }
   5070 
   5071         if (mKeyguardDelegate != null) {
   5072             mKeyguardDelegate.onScreenTurnedOn(mKeyguardDelegateCallback);
   5073             // ... eventually calls finishKeyguardDrawn
   5074         } else {
   5075             if (DEBUG_WAKEUP) Slog.d(TAG, "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
   5076             finishKeyguardDrawn();
   5077         }
   5078     }
   5079 
   5080     private void finishKeyguardDrawn() {
   5081         synchronized (mLock) {
   5082             if (!mAwake || mKeyguardDrawComplete) {
   5083                 return; // spurious
   5084             }
   5085 
   5086             mKeyguardDrawComplete = true;
   5087             if (mKeyguardDelegate != null) {
   5088                 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
   5089             }
   5090         }
   5091 
   5092         finishScreenTurningOn();
   5093     }
   5094 
   5095     // Called on the DisplayManager's DisplayPowerController thread.
   5096     @Override
   5097     public void screenTurnedOff() {
   5098         if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
   5099 
   5100         synchronized (mLock) {
   5101             mScreenOnEarly = false;
   5102             mScreenOnFully = false;
   5103             mWindowManagerDrawComplete = false;
   5104             mScreenOnListener = null;
   5105             updateOrientationListenerLp();
   5106         }
   5107     }
   5108 
   5109     // Called on the DisplayManager's DisplayPowerController thread.
   5110     @Override
   5111     public void screenTurningOn(final ScreenOnListener screenOnListener) {
   5112         if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
   5113 
   5114         synchronized (mLock) {
   5115             mScreenOnEarly = true;
   5116             mScreenOnFully = false;
   5117             mWindowManagerDrawComplete = false;
   5118             mScreenOnListener = screenOnListener;
   5119             updateOrientationListenerLp();
   5120         }
   5121 
   5122         mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
   5123                 WAITING_FOR_DRAWN_TIMEOUT);
   5124         // ... eventually calls finishWindowsDrawn
   5125     }
   5126 
   5127     private void finishWindowsDrawn() {
   5128         synchronized (mLock) {
   5129             if (!mScreenOnEarly || mWindowManagerDrawComplete) {
   5130                 return; // spurious
   5131             }
   5132 
   5133             mWindowManagerDrawComplete = true;
   5134         }
   5135 
   5136         finishScreenTurningOn();
   5137     }
   5138 
   5139     private void finishScreenTurningOn() {
   5140         final ScreenOnListener listener;
   5141         final boolean enableScreen;
   5142         synchronized (mLock) {
   5143             if (DEBUG_WAKEUP) Slog.d(TAG,
   5144                     "finishScreenTurningOn: mAwake=" + mAwake
   5145                             + ", mScreenOnEarly=" + mScreenOnEarly
   5146                             + ", mScreenOnFully=" + mScreenOnFully
   5147                             + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
   5148                             + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
   5149 
   5150             if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
   5151                     || (mAwake && !mKeyguardDrawComplete)) {
   5152                 return; // spurious or not ready yet
   5153             }
   5154 
   5155             if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
   5156             listener = mScreenOnListener;
   5157             mScreenOnListener = null;
   5158             mScreenOnFully = true;
   5159 
   5160             // Remember the first time we draw the keyguard so we know when we're done with
   5161             // the main part of booting and can enable the screen and hide boot messages.
   5162             if (!mKeyguardDrawnOnce && mAwake) {
   5163                 mKeyguardDrawnOnce = true;
   5164                 enableScreen = true;
   5165                 if (mBootMessageNeedsHiding) {
   5166                     mBootMessageNeedsHiding = false;
   5167                     hideBootMessages();
   5168                 }
   5169             } else {
   5170                 enableScreen = false;
   5171             }
   5172         }
   5173 
   5174         if (listener != null) {
   5175             listener.onScreenOn();
   5176         }
   5177 
   5178         if (enableScreen) {
   5179             try {
   5180                 mWindowManager.enableScreenIfNeeded();
   5181             } catch (RemoteException unhandled) {
   5182             }
   5183         }
   5184     }
   5185 
   5186     private void handleHideBootMessage() {
   5187         synchronized (mLock) {
   5188             if (!mKeyguardDrawnOnce) {
   5189                 mBootMessageNeedsHiding = true;
   5190                 return; // keyguard hasn't drawn the first time yet, not done booting
   5191             }
   5192         }
   5193 
   5194         if (mBootMsgDialog != null) {
   5195             if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
   5196             mBootMsgDialog.dismiss();
   5197             mBootMsgDialog = null;
   5198         }
   5199     }
   5200 
   5201     @Override
   5202     public boolean isScreenOn() {
   5203         return mScreenOnFully;
   5204     }
   5205 
   5206     /** {@inheritDoc} */
   5207     @Override
   5208     public void enableKeyguard(boolean enabled) {
   5209         if (mKeyguardDelegate != null) {
   5210             mKeyguardDelegate.setKeyguardEnabled(enabled);
   5211         }
   5212     }
   5213 
   5214     /** {@inheritDoc} */
   5215     @Override
   5216     public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
   5217         if (mKeyguardDelegate != null) {
   5218             mKeyguardDelegate.verifyUnlock(callback);
   5219         }
   5220     }
   5221 
   5222     private boolean isKeyguardShowingAndNotOccluded() {
   5223         if (mKeyguardDelegate == null) return false;
   5224         return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
   5225     }
   5226 
   5227     /** {@inheritDoc} */
   5228     @Override
   5229     public boolean isKeyguardLocked() {
   5230         return keyguardOn();
   5231     }
   5232 
   5233     /** {@inheritDoc} */
   5234     @Override
   5235     public boolean isKeyguardSecure() {
   5236         if (mKeyguardDelegate == null) return false;
   5237         return mKeyguardDelegate.isSecure();
   5238     }
   5239 
   5240     /** {@inheritDoc} */
   5241     @Override
   5242     public boolean inKeyguardRestrictedKeyInputMode() {
   5243         if (mKeyguardDelegate == null) return false;
   5244         return mKeyguardDelegate.isInputRestricted();
   5245     }
   5246 
   5247     @Override
   5248     public void dismissKeyguardLw() {
   5249         if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
   5250             if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
   5251             mHandler.post(new Runnable() {
   5252                 @Override
   5253                 public void run() {
   5254                     // ask the keyguard to prompt the user to authenticate if necessary
   5255                     mKeyguardDelegate.dismiss();
   5256                 }
   5257             });
   5258         }
   5259     }
   5260 
   5261     public void notifyActivityDrawnForKeyguardLw() {
   5262         if (mKeyguardDelegate != null) {
   5263             mHandler.post(new Runnable() {
   5264                 @Override
   5265                 public void run() {
   5266                     mKeyguardDelegate.onActivityDrawn();
   5267                 }
   5268             });
   5269         }
   5270     }
   5271 
   5272     @Override
   5273     public boolean isKeyguardDrawnLw() {
   5274         synchronized (mLock) {
   5275             return mKeyguardDrawnOnce;
   5276         }
   5277     }
   5278 
   5279     @Override
   5280     public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
   5281         if (mKeyguardDelegate != null) {
   5282             if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
   5283             mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
   5284         }
   5285     }
   5286 
   5287     void sendCloseSystemWindows() {
   5288         sendCloseSystemWindows(mContext, null);
   5289     }
   5290 
   5291     void sendCloseSystemWindows(String reason) {
   5292         sendCloseSystemWindows(mContext, reason);
   5293     }
   5294 
   5295     static void sendCloseSystemWindows(Context context, String reason) {
   5296         if (ActivityManagerNative.isSystemReady()) {
   5297             try {
   5298                 ActivityManagerNative.getDefault().closeSystemDialogs(reason);
   5299             } catch (RemoteException e) {
   5300             }
   5301         }
   5302     }
   5303 
   5304     @Override
   5305     public int rotationForOrientationLw(int orientation, int lastRotation) {
   5306         if (false) {
   5307             Slog.v(TAG, "rotationForOrientationLw(orient="
   5308                         + orientation + ", last=" + lastRotation
   5309                         + "); user=" + mUserRotation + " "
   5310                         + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
   5311                             ? "USER_ROTATION_LOCKED" : "")
   5312                         );
   5313         }
   5314 
   5315         if (mForceDefaultOrientation) {
   5316             return Surface.ROTATION_0;
   5317         }
   5318 
   5319         synchronized (mLock) {
   5320             int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
   5321             if (sensorRotation < 0) {
   5322                 sensorRotation = lastRotation;
   5323             }
   5324 
   5325             final int preferredRotation;
   5326             if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
   5327                 // Ignore sensor when lid switch is open and rotation is forced.
   5328                 preferredRotation = mLidOpenRotation;
   5329             } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
   5330                     && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
   5331                 // Ignore sensor when in car dock unless explicitly enabled.
   5332                 // This case can override the behavior of NOSENSOR, and can also
   5333                 // enable 180 degree rotation while docked.
   5334                 preferredRotation = mCarDockEnablesAccelerometer
   5335                         ? sensorRotation : mCarDockRotation;
   5336             } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
   5337                     || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
   5338                     || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
   5339                     && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
   5340                 // Ignore sensor when in desk dock unless explicitly enabled.
   5341                 // This case can override the behavior of NOSENSOR, and can also
   5342                 // enable 180 degree rotation while docked.
   5343                 preferredRotation = mDeskDockEnablesAccelerometer
   5344                         ? sensorRotation : mDeskDockRotation;
   5345             } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
   5346                 // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
   5347                 // Note that the dock orientation overrides the HDMI orientation.
   5348                 preferredRotation = mDemoHdmiRotation;
   5349             } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
   5350                     && mUndockedHdmiRotation >= 0) {
   5351                 // Ignore sensor when plugged into HDMI and an undocked orientation has
   5352                 // been specified in the configuration (only for legacy devices without
   5353                 // full multi-display support).
   5354                 // Note that the dock orientation overrides the HDMI orientation.
   5355                 preferredRotation = mUndockedHdmiRotation;
   5356             } else if (mDemoRotationLock) {
   5357                 // Ignore sensor when demo rotation lock is enabled.
   5358                 // Note that the dock orientation and HDMI rotation lock override this.
   5359                 preferredRotation = mDemoRotation;
   5360             } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
   5361                 // Application just wants to remain locked in the last rotation.
   5362                 preferredRotation = lastRotation;
   5363             } else if (!mSupportAutoRotation) {
   5364                 // If we don't support auto-rotation then bail out here and ignore
   5365                 // the sensor and any rotation lock settings.
   5366                 preferredRotation = -1;
   5367             } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
   5368                             && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
   5369                                     || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
   5370                                     || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
   5371                                     || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
   5372                                     || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
   5373                     || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
   5374                     || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
   5375                     || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
   5376                     || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
   5377                 // Otherwise, use sensor only if requested by the application or enabled
   5378                 // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
   5379                 if (mAllowAllRotations < 0) {
   5380                     // Can't read this during init() because the context doesn't
   5381                     // have display metrics at that time so we cannot determine
   5382                     // tablet vs. phone then.
   5383                     mAllowAllRotations = mContext.getResources().getBoolean(
   5384                             com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
   5385                 }
   5386                 if (sensorRotation != Surface.ROTATION_180
   5387                         || mAllowAllRotations == 1
   5388                         || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
   5389                         || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
   5390                     preferredRotation = sensorRotation;
   5391                 } else {
   5392                     preferredRotation = lastRotation;
   5393                 }
   5394             } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
   5395                     && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
   5396                 // Apply rotation lock.  Does not apply to NOSENSOR.
   5397                 // The idea is that the user rotation expresses a weak preference for the direction
   5398                 // of gravity and as NOSENSOR is never affected by gravity, then neither should
   5399                 // NOSENSOR be affected by rotation lock (although it will be affected by docks).
   5400                 preferredRotation = mUserRotation;
   5401             } else {
   5402                 // No overriding preference.
   5403                 // We will do exactly what the application asked us to do.
   5404                 preferredRotation = -1;
   5405             }
   5406 
   5407             switch (orientation) {
   5408                 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
   5409                     // Return portrait unless overridden.
   5410                     if (isAnyPortrait(preferredRotation)) {
   5411                         return preferredRotation;
   5412                     }
   5413                     return mPortraitRotation;
   5414 
   5415                 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
   5416                     // Return landscape unless overridden.
   5417                     if (isLandscapeOrSeascape(preferredRotation)) {
   5418                         return preferredRotation;
   5419                     }
   5420                     return mLandscapeRotation;
   5421 
   5422                 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
   5423                     // Return reverse portrait unless overridden.
   5424                     if (isAnyPortrait(preferredRotation)) {
   5425                         return preferredRotation;
   5426                     }
   5427                     return mUpsideDownRotation;
   5428 
   5429                 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
   5430                     // Return seascape unless overridden.
   5431                     if (isLandscapeOrSeascape(preferredRotation)) {
   5432                         return preferredRotation;
   5433                     }
   5434                     return mSeascapeRotation;
   5435 
   5436                 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
   5437                 case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
   5438                     // Return either landscape rotation.
   5439                     if (isLandscapeOrSeascape(preferredRotation)) {
   5440                         return preferredRotation;
   5441                     }
   5442                     if (isLandscapeOrSeascape(lastRotation)) {
   5443                         return lastRotation;
   5444                     }
   5445                     return mLandscapeRotation;
   5446 
   5447                 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
   5448                 case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
   5449                     // Return either portrait rotation.
   5450                     if (isAnyPortrait(preferredRotation)) {
   5451                         return preferredRotation;
   5452                     }
   5453                     if (isAnyPortrait(lastRotation)) {
   5454                         return lastRotation;
   5455                     }
   5456                     return mPortraitRotation;
   5457 
   5458                 default:
   5459                     // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
   5460                     // just return the preferred orientation we already calculated.
   5461                     if (preferredRotation >= 0) {
   5462                         return preferredRotation;
   5463                     }
   5464                     return Surface.ROTATION_0;
   5465             }
   5466         }
   5467     }
   5468 
   5469     @Override
   5470     public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
   5471         switch (orientation) {
   5472             case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
   5473             case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
   5474             case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
   5475                 return isAnyPortrait(rotation);
   5476 
   5477             case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
   5478             case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
   5479             case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
   5480                 return isLandscapeOrSeascape(rotation);
   5481 
   5482             default:
   5483                 return true;
   5484         }
   5485     }
   5486 
   5487     @Override
   5488     public void setRotationLw(int rotation) {
   5489         mOrientationListener.setCurrentRotation(rotation);
   5490     }
   5491 
   5492     private boolean isLandscapeOrSeascape(int rotation) {
   5493         return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
   5494     }
   5495 
   5496     private boolean isAnyPortrait(int rotation) {
   5497         return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
   5498     }
   5499 
   5500     @Override
   5501     public int getUserRotationMode() {
   5502         return Settings.System.getIntForUser(mContext.getContentResolver(),
   5503                 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
   5504                         WindowManagerPolicy.USER_ROTATION_FREE :
   5505                                 WindowManagerPolicy.USER_ROTATION_LOCKED;
   5506     }
   5507 
   5508     // User rotation: to be used when all else fails in assigning an orientation to the device
   5509     @Override
   5510     public void setUserRotationMode(int mode, int rot) {
   5511         ContentResolver res = mContext.getContentResolver();
   5512 
   5513         // mUserRotationMode and mUserRotation will be assigned by the content observer
   5514         if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
   5515             Settings.System.putIntForUser(res,
   5516                     Settings.System.USER_ROTATION,
   5517                     rot,
   5518                     UserHandle.USER_CURRENT);
   5519             Settings.System.putIntForUser(res,
   5520                     Settings.System.ACCELEROMETER_ROTATION,
   5521                     0,
   5522                     UserHandle.USER_CURRENT);
   5523         } else {
   5524             Settings.System.putIntForUser(res,
   5525                     Settings.System.ACCELEROMETER_ROTATION,
   5526                     1,
   5527                     UserHandle.USER_CURRENT);
   5528         }
   5529     }
   5530 
   5531     @Override
   5532     public void setSafeMode(boolean safeMode) {
   5533         mSafeMode = safeMode;
   5534         performHapticFeedbackLw(null, safeMode
   5535                 ? HapticFeedbackConstants.SAFE_MODE_ENABLED
   5536                 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
   5537     }
   5538 
   5539     static long[] getLongIntArray(Resources r, int resid) {
   5540         int[] ar = r.getIntArray(resid);
   5541         if (ar == null) {
   5542             return null;
   5543         }
   5544         long[] out = new long[ar.length];
   5545         for (int i=0; i<ar.length; i++) {
   5546             out[i] = ar[i];
   5547         }
   5548         return out;
   5549     }
   5550 
   5551     /** {@inheritDoc} */
   5552     @Override
   5553     public void systemReady() {
   5554         mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
   5555         mKeyguardDelegate.onSystemReady();
   5556 
   5557         readCameraLensCoverState();
   5558         updateUiMode();
   5559         synchronized (mLock) {
   5560             updateOrientationListenerLp();
   5561             mSystemReady = true;
   5562             mHandler.post(new Runnable() {
   5563                 @Override
   5564                 public void run() {
   5565                     updateSettings();
   5566                 }
   5567             });
   5568         }
   5569     }
   5570 
   5571     /** {@inheritDoc} */
   5572     @Override
   5573     public void systemBooted() {
   5574         if (mKeyguardDelegate != null) {
   5575             mKeyguardDelegate.bindService(mContext);
   5576             mKeyguardDelegate.onBootCompleted();
   5577         }
   5578         synchronized (mLock) {
   5579             mSystemBooted = true;
   5580         }
   5581         wakingUp();
   5582         screenTurningOn(null);
   5583     }
   5584 
   5585     ProgressDialog mBootMsgDialog = null;
   5586 
   5587     /** {@inheritDoc} */
   5588     @Override
   5589     public void showBootMessage(final CharSequence msg, final boolean always) {
   5590         mHandler.post(new Runnable() {
   5591             @Override public void run() {
   5592                 if (mBootMsgDialog == null) {
   5593                     int theme;
   5594                     if (mContext.getPackageManager().hasSystemFeature(
   5595                             PackageManager.FEATURE_WATCH)) {
   5596                         theme = com.android.internal.R.style.Theme_Micro_Dialog_Alert;
   5597                     } else if (mContext.getPackageManager().hasSystemFeature(
   5598                             PackageManager.FEATURE_TELEVISI