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