Home | History | Annotate | Download | only in impl
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.internal.policy.impl;
     18 
     19 import android.app.Activity;
     20 import android.app.ActivityManagerNative;
     21 import android.app.IActivityManager;
     22 import android.app.IUiModeManager;
     23 import android.app.ProgressDialog;
     24 import android.app.UiModeManager;
     25 import android.content.ActivityNotFoundException;
     26 import android.content.BroadcastReceiver;
     27 import android.content.ComponentName;
     28 import android.content.ContentResolver;
     29 import android.content.Context;
     30 import android.content.Intent;
     31 import android.content.IntentFilter;
     32 import android.content.ServiceConnection;
     33 import android.content.pm.ActivityInfo;
     34 import android.content.pm.PackageManager;
     35 import android.content.res.CompatibilityInfo;
     36 import android.content.res.Configuration;
     37 import android.content.res.Resources;
     38 import android.database.ContentObserver;
     39 import android.graphics.PixelFormat;
     40 import android.graphics.Rect;
     41 import android.graphics.RectF;
     42 import android.os.BatteryManager;
     43 import android.os.Bundle;
     44 import android.os.Handler;
     45 import android.os.IBinder;
     46 import android.os.IRemoteCallback;
     47 import android.os.LocalPowerManager;
     48 import android.os.Message;
     49 import android.os.Messenger;
     50 import android.os.PowerManager;
     51 import android.os.RemoteException;
     52 import android.os.ServiceManager;
     53 import android.os.SystemClock;
     54 import android.os.SystemProperties;
     55 import android.os.UEventObserver;
     56 import android.os.Vibrator;
     57 import android.provider.Settings;
     58 
     59 import com.android.internal.R;
     60 import com.android.internal.app.ShutdownThread;
     61 import com.android.internal.policy.PolicyManager;
     62 import com.android.internal.statusbar.IStatusBarService;
     63 import com.android.internal.telephony.ITelephony;
     64 import com.android.internal.view.BaseInputHandler;
     65 import com.android.internal.widget.PointerLocationView;
     66 
     67 import android.util.DisplayMetrics;
     68 import android.util.EventLog;
     69 import android.util.Log;
     70 import android.util.Slog;
     71 import android.util.SparseArray;
     72 import android.view.Gravity;
     73 import android.view.HapticFeedbackConstants;
     74 import android.view.IApplicationToken;
     75 import android.view.IWindowManager;
     76 import android.view.InputChannel;
     77 import android.view.InputDevice;
     78 import android.view.InputQueue;
     79 import android.view.InputHandler;
     80 import android.view.KeyCharacterMap;
     81 import android.view.KeyEvent;
     82 import android.view.MotionEvent;
     83 import android.view.WindowOrientationListener;
     84 import android.view.Surface;
     85 import android.view.View;
     86 import android.view.ViewConfiguration;
     87 import android.view.Window;
     88 import android.view.WindowManager;
     89 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
     90 import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
     91 import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
     92 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
     93 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
     94 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
     95 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
     96 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
     97 import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
     98 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
     99 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
    100 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
    101 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
    102 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
    103 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
    104 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
    105 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
    106 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
    107 import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
    108 import static android.view.WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER;
    109 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD;
    110 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
    111 import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
    112 import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
    113 import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR;
    114 import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
    115 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
    116 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
    117 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
    118 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
    119 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
    120 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
    121 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
    122 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
    123 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
    124 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
    125 import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
    126 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
    127 import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
    128 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
    129 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
    130 import android.view.WindowManagerImpl;
    131 import android.view.WindowManagerPolicy;
    132 import android.view.KeyCharacterMap.FallbackAction;
    133 import android.view.accessibility.AccessibilityEvent;
    134 import android.view.animation.Animation;
    135 import android.view.animation.AnimationUtils;
    136 import android.media.IAudioService;
    137 import android.media.AudioManager;
    138 
    139 import java.io.File;
    140 import java.io.FileDescriptor;
    141 import java.io.FileReader;
    142 import java.io.IOException;
    143 import java.io.PrintWriter;
    144 import java.util.ArrayList;
    145 
    146 /**
    147  * WindowManagerPolicy implementation for the Android phone UI.  This
    148  * introduces a new method suffix, Lp, for an internal lock of the
    149  * PhoneWindowManager.  This is used to protect some internal state, and
    150  * can be acquired with either thw Lw and Li lock held, so has the restrictions
    151  * of both of those when held.
    152  */
    153 public class PhoneWindowManager implements WindowManagerPolicy {
    154     static final String TAG = "WindowManager";
    155     static final boolean DEBUG = false;
    156     static final boolean localLOGV = false;
    157     static final boolean DEBUG_LAYOUT = false;
    158     static final boolean DEBUG_FALLBACK = false;
    159     static final boolean SHOW_STARTING_ANIMATIONS = true;
    160     static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
    161 
    162     // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
    163     // No longer recommended for desk docks; still useful in car docks.
    164     static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true;
    165     static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
    166 
    167     static final int LONG_PRESS_POWER_NOTHING = 0;
    168     static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
    169     static final int LONG_PRESS_POWER_SHUT_OFF = 2;
    170 
    171     // These need to match the documentation/constant in
    172     // core/res/res/values/config.xml
    173     static final int LONG_PRESS_HOME_NOTHING = 0;
    174     static final int LONG_PRESS_HOME_RECENT_DIALOG = 1;
    175     static final int LONG_PRESS_HOME_RECENT_SYSTEM_UI = 2;
    176 
    177     // wallpaper is at the bottom, though the window manager may move it.
    178     static final int WALLPAPER_LAYER = 2;
    179     static final int APPLICATION_LAYER = 2;
    180     static final int PHONE_LAYER = 3;
    181     static final int SEARCH_BAR_LAYER = 4;
    182     static final int SYSTEM_DIALOG_LAYER = 5;
    183     // toasts and the plugged-in battery thing
    184     static final int TOAST_LAYER = 6;
    185     // SIM errors and unlock.  Not sure if this really should be in a high layer.
    186     static final int PRIORITY_PHONE_LAYER = 7;
    187     // like the ANR / app crashed dialogs
    188     static final int SYSTEM_ALERT_LAYER = 8;
    189     // on-screen keyboards and other such input method user interfaces go here.
    190     static final int INPUT_METHOD_LAYER = 9;
    191     // on-screen keyboards and other such input method user interfaces go here.
    192     static final int INPUT_METHOD_DIALOG_LAYER = 10;
    193     // the keyguard; nothing on top of these can take focus, since they are
    194     // responsible for power management when displayed.
    195     static final int KEYGUARD_LAYER = 11;
    196     static final int KEYGUARD_DIALOG_LAYER = 12;
    197     static final int STATUS_BAR_SUB_PANEL_LAYER = 13;
    198     static final int STATUS_BAR_LAYER = 14;
    199     static final int STATUS_BAR_PANEL_LAYER = 15;
    200     // the on-screen volume indicator and controller shown when the user
    201     // changes the device volume
    202     static final int VOLUME_OVERLAY_LAYER = 16;
    203     // things in here CAN NOT take focus, but are shown on top of everything else.
    204     static final int SYSTEM_OVERLAY_LAYER = 17;
    205     // the navigation bar, if available, shows atop most things
    206     static final int NAVIGATION_BAR_LAYER = 18;
    207     // system-level error dialogs
    208     static final int SYSTEM_ERROR_LAYER = 19;
    209     // the drag layer: input for drag-and-drop is associated with this window,
    210     // which sits above all other focusable windows
    211     static final int DRAG_LAYER = 20;
    212     static final int SECURE_SYSTEM_OVERLAY_LAYER = 21;
    213     static final int BOOT_PROGRESS_LAYER = 22;
    214     // the (mouse) pointer layer
    215     static final int POINTER_LAYER = 23;
    216     static final int HIDDEN_NAV_CONSUMER_LAYER = 24;
    217 
    218     static final int APPLICATION_MEDIA_SUBLAYER = -2;
    219     static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
    220     static final int APPLICATION_PANEL_SUBLAYER = 1;
    221     static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
    222 
    223     static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
    224     static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
    225     static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
    226     static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
    227 
    228     // Useful scan codes.
    229     private static final int SW_LID = 0x00;
    230     private static final int BTN_MOUSE = 0x110;
    231 
    232     /* Table of Application Launch keys.  Maps from key codes to intent categories.
    233      *
    234      * These are special keys that are used to launch particular kinds of applications,
    235      * such as a web browser.  HID defines nearly a hundred of them in the Consumer (0x0C)
    236      * usage page.  We don't support quite that many yet...
    237      */
    238     static SparseArray<String> sApplicationLaunchKeyCategories;
    239     static {
    240         sApplicationLaunchKeyCategories = new SparseArray<String>();
    241         sApplicationLaunchKeyCategories.append(
    242                 KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER);
    243         sApplicationLaunchKeyCategories.append(
    244                 KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL);
    245         sApplicationLaunchKeyCategories.append(
    246                 KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS);
    247         sApplicationLaunchKeyCategories.append(
    248                 KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR);
    249         sApplicationLaunchKeyCategories.append(
    250                 KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC);
    251         sApplicationLaunchKeyCategories.append(
    252                 KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
    253     }
    254 
    255     /**
    256      * Lock protecting internal state.  Must not call out into window
    257      * manager with lock held.  (This lock will be acquired in places
    258      * where the window manager is calling in with its own lock held.)
    259      */
    260     final Object mLock = new Object();
    261 
    262     Context mContext;
    263     IWindowManager mWindowManager;
    264     WindowManagerFuncs mWindowManagerFuncs;
    265     LocalPowerManager mPowerManager;
    266     IStatusBarService mStatusBarService;
    267     Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
    268 
    269     // Vibrator pattern for haptic feedback of a long press.
    270     long[] mLongPressVibePattern;
    271 
    272     // Vibrator pattern for haptic feedback of virtual key press.
    273     long[] mVirtualKeyVibePattern;
    274 
    275     // Vibrator pattern for a short vibration.
    276     long[] mKeyboardTapVibePattern;
    277 
    278     // Vibrator pattern for haptic feedback during boot when safe mode is disabled.
    279     long[] mSafeModeDisabledVibePattern;
    280 
    281     // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
    282     long[] mSafeModeEnabledVibePattern;
    283 
    284     /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
    285     boolean mEnableShiftMenuBugReports = false;
    286 
    287     boolean mSafeMode;
    288     WindowState mStatusBar = null;
    289     boolean mStatusBarCanHide;
    290     int mStatusBarHeight;
    291     final ArrayList<WindowState> mStatusBarPanels = new ArrayList<WindowState>();
    292     WindowState mNavigationBar = null;
    293     boolean mHasNavigationBar = false;
    294     int mNavigationBarWidth = 0, mNavigationBarHeight = 0;
    295 
    296     WindowState mKeyguard = null;
    297     KeyguardViewMediator mKeyguardMediator;
    298     GlobalActions mGlobalActions;
    299     volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
    300     boolean mPendingPowerKeyUpCanceled;
    301     Handler mHandler;
    302 
    303     static final int RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS = 0;
    304     static final int RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW = 1;
    305     static final int RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH = 2;
    306 
    307     RecentApplicationsDialog mRecentAppsDialog;
    308     int mRecentAppsDialogHeldModifiers;
    309 
    310     private static final int LID_ABSENT = -1;
    311     private static final int LID_CLOSED = 0;
    312     private static final int LID_OPEN = 1;
    313 
    314     int mLidOpen = LID_ABSENT;
    315 
    316     boolean mSystemReady;
    317     boolean mSystemBooted;
    318     boolean mHdmiPlugged;
    319     int mUiMode = Configuration.UI_MODE_TYPE_NORMAL;
    320     int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
    321     int mLidOpenRotation;
    322     int mCarDockRotation;
    323     int mDeskDockRotation;
    324     int mHdmiRotation;
    325 
    326     int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
    327     int mUserRotation = Surface.ROTATION_0;
    328 
    329     int mAllowAllRotations = -1;
    330     boolean mCarDockEnablesAccelerometer;
    331     boolean mDeskDockEnablesAccelerometer;
    332     int mLidKeyboardAccessibility;
    333     int mLidNavigationAccessibility;
    334     int mLongPressOnPowerBehavior = -1;
    335     boolean mScreenOnEarly = false;
    336     boolean mScreenOnFully = false;
    337     boolean mOrientationSensorEnabled = false;
    338     int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
    339     static final int DEFAULT_ACCELEROMETER_ROTATION = 0;
    340     int mAccelerometerDefault = DEFAULT_ACCELEROMETER_ROTATION;
    341     boolean mHasSoftInput = false;
    342 
    343     int mPointerLocationMode = 0;
    344     PointerLocationView mPointerLocationView = null;
    345     InputChannel mPointerLocationInputChannel;
    346 
    347     // The last window we were told about in focusChanged.
    348     WindowState mFocusedWindow;
    349     IApplicationToken mFocusedApp;
    350 
    351     private final InputHandler mPointerLocationInputHandler = new BaseInputHandler() {
    352         @Override
    353         public void handleMotion(MotionEvent event, InputQueue.FinishedCallback finishedCallback) {
    354             boolean handled = false;
    355             try {
    356                 if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
    357                     synchronized (mLock) {
    358                         if (mPointerLocationView != null) {
    359                             mPointerLocationView.addPointerEvent(event);
    360                             handled = true;
    361                         }
    362                     }
    363                 }
    364             } finally {
    365                 finishedCallback.finished(handled);
    366             }
    367         }
    368     };
    369 
    370     // The current size of the screen; really; (ir)regardless of whether the status
    371     // bar can be hidden or not
    372     int mUnrestrictedScreenLeft, mUnrestrictedScreenTop;
    373     int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight;
    374     // The current size of the screen; these may be different than (0,0)-(dw,dh)
    375     // if the status bar can't be hidden; in that case it effectively carves out
    376     // that area of the display from all other windows.
    377     int mRestrictedScreenLeft, mRestrictedScreenTop;
    378     int mRestrictedScreenWidth, mRestrictedScreenHeight;
    379     // During layout, the current screen borders with all outer decoration
    380     // (status bar, input method dock) accounted for.
    381     int mCurLeft, mCurTop, mCurRight, mCurBottom;
    382     // During layout, the frame in which content should be displayed
    383     // to the user, accounting for all screen decoration except for any
    384     // space they deem as available for other content.  This is usually
    385     // the same as mCur*, but may be larger if the screen decor has supplied
    386     // content insets.
    387     int mContentLeft, mContentTop, mContentRight, mContentBottom;
    388     // During layout, the current screen borders along which input method
    389     // windows are placed.
    390     int mDockLeft, mDockTop, mDockRight, mDockBottom;
    391     // During layout, the layer at which the doc window is placed.
    392     int mDockLayer;
    393     int mLastSystemUiFlags;
    394     // Bits that we are in the process of clearing, so we want to prevent
    395     // them from being set by applications until everything has been updated
    396     // to have them clear.
    397     int mResettingSystemUiFlags = 0;
    398     // Bits that we are currently always keeping cleared.
    399     int mForceClearedSystemUiFlags = 0;
    400     // What we last reported to system UI about whether the compatibility
    401     // menu needs to be displayed.
    402     boolean mLastFocusNeedsMenu = false;
    403 
    404     FakeWindow mHideNavFakeWindow = null;
    405 
    406     static final Rect mTmpParentFrame = new Rect();
    407     static final Rect mTmpDisplayFrame = new Rect();
    408     static final Rect mTmpContentFrame = new Rect();
    409     static final Rect mTmpVisibleFrame = new Rect();
    410     static final Rect mTmpNavigationFrame = new Rect();
    411 
    412     WindowState mTopFullscreenOpaqueWindowState;
    413     boolean mTopIsFullscreen;
    414     boolean mForceStatusBar;
    415     boolean mHideLockScreen;
    416     boolean mDismissKeyguard;
    417     boolean mHomePressed;
    418     Intent mHomeIntent;
    419     Intent mCarDockIntent;
    420     Intent mDeskDockIntent;
    421     int mShortcutKeyPressed = -1;
    422     boolean mConsumeShortcutKeyUp;
    423 
    424     // support for activating the lock screen while the screen is on
    425     boolean mAllowLockscreenWhenOn;
    426     int mLockScreenTimeout;
    427     boolean mLockScreenTimerActive;
    428 
    429     // Behavior of ENDCALL Button.  (See Settings.System.END_BUTTON_BEHAVIOR.)
    430     int mEndcallBehavior;
    431 
    432     // Behavior of POWER button while in-call and screen on.
    433     // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
    434     int mIncallPowerBehavior;
    435 
    436     int mLandscapeRotation = 0;  // default landscape rotation
    437     int mSeascapeRotation = 0;   // "other" landscape rotation, 180 degrees from mLandscapeRotation
    438     int mPortraitRotation = 0;   // default portrait rotation
    439     int mUpsideDownRotation = 0; // "other" portrait rotation
    440 
    441     // What we do when the user long presses on home
    442     private int mLongPressOnHomeBehavior = -1;
    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     private boolean mVolumeDownKeyTriggered;
    448     private long mVolumeDownKeyTime;
    449     private boolean mVolumeDownKeyConsumedByScreenshotChord;
    450     private boolean mVolumeUpKeyTriggered;
    451     private boolean mPowerKeyTriggered;
    452     private long mPowerKeyTime;
    453 
    454     ShortcutManager mShortcutManager;
    455     PowerManager.WakeLock mBroadcastWakeLock;
    456 
    457     final KeyCharacterMap.FallbackAction mFallbackAction = new KeyCharacterMap.FallbackAction();
    458 
    459     private UEventObserver mHDMIObserver = new UEventObserver() {
    460         @Override
    461         public void onUEvent(UEventObserver.UEvent event) {
    462             setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
    463         }
    464     };
    465 
    466     class SettingsObserver extends ContentObserver {
    467         SettingsObserver(Handler handler) {
    468             super(handler);
    469         }
    470 
    471         void observe() {
    472             ContentResolver resolver = mContext.getContentResolver();
    473             resolver.registerContentObserver(Settings.System.getUriFor(
    474                     Settings.System.END_BUTTON_BEHAVIOR), false, this);
    475             resolver.registerContentObserver(Settings.Secure.getUriFor(
    476                     Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this);
    477             resolver.registerContentObserver(Settings.System.getUriFor(
    478                     Settings.System.ACCELEROMETER_ROTATION), false, this);
    479             resolver.registerContentObserver(Settings.System.getUriFor(
    480                     Settings.System.USER_ROTATION), false, this);
    481             resolver.registerContentObserver(Settings.System.getUriFor(
    482                     Settings.System.SCREEN_OFF_TIMEOUT), false, this);
    483             resolver.registerContentObserver(Settings.System.getUriFor(
    484                     Settings.System.WINDOW_ORIENTATION_LISTENER_LOG), false, this);
    485             resolver.registerContentObserver(Settings.System.getUriFor(
    486                     Settings.System.POINTER_LOCATION), false, this);
    487             resolver.registerContentObserver(Settings.Secure.getUriFor(
    488                     Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
    489             resolver.registerContentObserver(Settings.System.getUriFor(
    490                     "fancy_rotation_anim"), false, this);
    491             updateSettings();
    492         }
    493 
    494         @Override public void onChange(boolean selfChange) {
    495             updateSettings();
    496             updateRotation(false);
    497         }
    498     }
    499 
    500     class MyOrientationListener extends WindowOrientationListener {
    501         MyOrientationListener(Context context) {
    502             super(context);
    503         }
    504 
    505         @Override
    506         public void onProposedRotationChanged(int rotation) {
    507             if (localLOGV) Log.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
    508             updateRotation(false);
    509         }
    510     }
    511     MyOrientationListener mOrientationListener;
    512 
    513     /*
    514      * We always let the sensor be switched on by default except when
    515      * the user has explicitly disabled sensor based rotation or when the
    516      * screen is switched off.
    517      */
    518     boolean needSensorRunningLp() {
    519         if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
    520                 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
    521                 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
    522                 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
    523             // If the application has explicitly requested to follow the
    524             // orientation, then we need to turn the sensor or.
    525             return true;
    526         }
    527         if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
    528                 (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
    529                         || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
    530                         || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
    531             // enable accelerometer if we are docked in a dock that enables accelerometer
    532             // orientation management,
    533             return true;
    534         }
    535         if (mAccelerometerDefault == 0) {
    536             // If the setting for using the sensor by default is enabled, then
    537             // we will always leave it on.  Note that the user could go to
    538             // a window that forces an orientation that does not use the
    539             // sensor and in theory we could turn it off... however, when next
    540             // turning it on we won't have a good value for the current
    541             // orientation for a little bit, which can cause orientation
    542             // changes to lag, so we'd like to keep it always on.  (It will
    543             // still be turned off when the screen is off.)
    544             return false;
    545         }
    546         return true;
    547     }
    548 
    549     /*
    550      * Various use cases for invoking this function
    551      * screen turning off, should always disable listeners if already enabled
    552      * screen turned on and current app has sensor based orientation, enable listeners
    553      * if not already enabled
    554      * screen turned on and current app does not have sensor orientation, disable listeners if
    555      * already enabled
    556      * screen turning on and current app has sensor based orientation, enable listeners if needed
    557      * screen turning on and current app has nosensor based orientation, do nothing
    558      */
    559     void updateOrientationListenerLp() {
    560         if (!mOrientationListener.canDetectOrientation()) {
    561             // If sensor is turned off or nonexistent for some reason
    562             return;
    563         }
    564         //Could have been invoked due to screen turning on or off or
    565         //change of the currently visible window's orientation
    566         if (localLOGV) Log.v(TAG, "Screen status="+mScreenOnEarly+
    567                 ", current orientation="+mCurrentAppOrientation+
    568                 ", SensorEnabled="+mOrientationSensorEnabled);
    569         boolean disable = true;
    570         if (mScreenOnEarly) {
    571             if (needSensorRunningLp()) {
    572                 disable = false;
    573                 //enable listener if not already enabled
    574                 if (!mOrientationSensorEnabled) {
    575                     mOrientationListener.enable();
    576                     if(localLOGV) Log.v(TAG, "Enabling listeners");
    577                     mOrientationSensorEnabled = true;
    578                 }
    579             }
    580         }
    581         //check if sensors need to be disabled
    582         if (disable && mOrientationSensorEnabled) {
    583             mOrientationListener.disable();
    584             if(localLOGV) Log.v(TAG, "Disabling listeners");
    585             mOrientationSensorEnabled = false;
    586         }
    587     }
    588 
    589     private void interceptPowerKeyDown(boolean handled) {
    590         mPowerKeyHandled = handled;
    591         if (!handled) {
    592             mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
    593         }
    594     }
    595 
    596     private boolean interceptPowerKeyUp(boolean canceled) {
    597         if (!mPowerKeyHandled) {
    598             mHandler.removeCallbacks(mPowerLongPress);
    599             return !canceled;
    600         }
    601         return false;
    602     }
    603 
    604     private void cancelPendingPowerKeyAction() {
    605         if (!mPowerKeyHandled) {
    606             mHandler.removeCallbacks(mPowerLongPress);
    607         }
    608         if (mPowerKeyTriggered) {
    609             mPendingPowerKeyUpCanceled = true;
    610         }
    611     }
    612 
    613     private void interceptScreenshotChord() {
    614         if (mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) {
    615             final long now = SystemClock.uptimeMillis();
    616             if (now <= mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
    617                     && now <= mPowerKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
    618                 mVolumeDownKeyConsumedByScreenshotChord = true;
    619                 cancelPendingPowerKeyAction();
    620 
    621                 mHandler.postDelayed(mScreenshotChordLongPress,
    622                         ViewConfiguration.getGlobalActionKeyTimeout());
    623             }
    624         }
    625     }
    626 
    627     private void cancelPendingScreenshotChordAction() {
    628         mHandler.removeCallbacks(mScreenshotChordLongPress);
    629     }
    630 
    631     private final Runnable mPowerLongPress = new Runnable() {
    632         public void run() {
    633             // The context isn't read
    634             if (mLongPressOnPowerBehavior < 0) {
    635                 mLongPressOnPowerBehavior = mContext.getResources().getInteger(
    636                         com.android.internal.R.integer.config_longPressOnPowerBehavior);
    637             }
    638             switch (mLongPressOnPowerBehavior) {
    639             case LONG_PRESS_POWER_NOTHING:
    640                 break;
    641             case LONG_PRESS_POWER_GLOBAL_ACTIONS:
    642                 mPowerKeyHandled = true;
    643                 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
    644                 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
    645                 showGlobalActionsDialog();
    646                 break;
    647             case LONG_PRESS_POWER_SHUT_OFF:
    648                 mPowerKeyHandled = true;
    649                 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
    650                 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
    651                 ShutdownThread.shutdown(mContext, true);
    652                 break;
    653             }
    654         }
    655     };
    656 
    657     private final Runnable mScreenshotChordLongPress = new Runnable() {
    658         public void run() {
    659             takeScreenshot();
    660         }
    661     };
    662 
    663     void showGlobalActionsDialog() {
    664         if (mGlobalActions == null) {
    665             mGlobalActions = new GlobalActions(mContext);
    666         }
    667         final boolean keyguardShowing = mKeyguardMediator.isShowingAndNotHidden();
    668         mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
    669         if (keyguardShowing) {
    670             // since it took two seconds of long press to bring this up,
    671             // poke the wake lock so they have some time to see the dialog.
    672             mKeyguardMediator.pokeWakelock();
    673         }
    674     }
    675 
    676     boolean isDeviceProvisioned() {
    677         return Settings.Secure.getInt(
    678                 mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
    679     }
    680 
    681     private void handleLongPressOnHome() {
    682         // We can't initialize this in init() since the configuration hasn't been loaded yet.
    683         if (mLongPressOnHomeBehavior < 0) {
    684             mLongPressOnHomeBehavior
    685                     = mContext.getResources().getInteger(R.integer.config_longPressOnHomeBehavior);
    686             if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||
    687                     mLongPressOnHomeBehavior > LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
    688                 mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
    689             }
    690         }
    691 
    692         if (mLongPressOnHomeBehavior != LONG_PRESS_HOME_NOTHING) {
    693             performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
    694             sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
    695 
    696             // Eat the longpress so it won't dismiss the recent apps dialog when
    697             // the user lets go of the home key
    698             mHomePressed = false;
    699         }
    700 
    701         if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) {
    702             showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
    703         } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
    704             try {
    705                 mStatusBarService.toggleRecentApps();
    706             } catch (RemoteException e) {
    707                 Slog.e(TAG, "RemoteException when showing recent apps", e);
    708             }
    709         }
    710     }
    711 
    712     /**
    713      * Create (if necessary) and show or dismiss the recent apps dialog according
    714      * according to the requested behavior.
    715      */
    716     void showOrHideRecentAppsDialog(final int behavior) {
    717         mHandler.post(new Runnable() {
    718             @Override
    719             public void run() {
    720                 if (mRecentAppsDialog == null) {
    721                     mRecentAppsDialog = new RecentApplicationsDialog(mContext);
    722                 }
    723                 if (mRecentAppsDialog.isShowing()) {
    724                     switch (behavior) {
    725                         case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
    726                             mRecentAppsDialog.dismiss();
    727                             break;
    728                         case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
    729                             mRecentAppsDialog.dismissAndSwitch();
    730                             break;
    731                         case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
    732                         default:
    733                             break;
    734                     }
    735                 } else {
    736                     switch (behavior) {
    737                         case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
    738                             mRecentAppsDialog.show();
    739                             break;
    740                         case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
    741                             try {
    742                                 mWindowManager.setInTouchMode(false);
    743                             } catch (RemoteException e) {
    744                             }
    745                             mRecentAppsDialog.show();
    746                             break;
    747                         case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
    748                         default:
    749                             break;
    750                     }
    751                 }
    752             }
    753         });
    754     }
    755 
    756     /** {@inheritDoc} */
    757     public void init(Context context, IWindowManager windowManager,
    758             WindowManagerFuncs windowManagerFuncs,
    759             LocalPowerManager powerManager) {
    760         mContext = context;
    761         mWindowManager = windowManager;
    762         mWindowManagerFuncs = windowManagerFuncs;
    763         mPowerManager = powerManager;
    764         mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
    765         mHandler = new Handler();
    766         mOrientationListener = new MyOrientationListener(mContext);
    767         try {
    768             mOrientationListener.setCurrentRotation(windowManager.getRotation());
    769         } catch (RemoteException ex) { }
    770         SettingsObserver settingsObserver = new SettingsObserver(mHandler);
    771         settingsObserver.observe();
    772         mShortcutManager = new ShortcutManager(context, mHandler);
    773         mShortcutManager.observe();
    774         mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
    775         mHomeIntent.addCategory(Intent.CATEGORY_HOME);
    776         mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
    777                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
    778         mCarDockIntent =  new Intent(Intent.ACTION_MAIN, null);
    779         mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
    780         mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
    781                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
    782         mDeskDockIntent =  new Intent(Intent.ACTION_MAIN, null);
    783         mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
    784         mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
    785                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
    786 
    787         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
    788         mBroadcastWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
    789                 "PhoneWindowManager.mBroadcastWakeLock");
    790         mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
    791         mLidOpenRotation = readRotation(
    792                 com.android.internal.R.integer.config_lidOpenRotation);
    793         mCarDockRotation = readRotation(
    794                 com.android.internal.R.integer.config_carDockRotation);
    795         mDeskDockRotation = readRotation(
    796                 com.android.internal.R.integer.config_deskDockRotation);
    797         mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
    798                 com.android.internal.R.bool.config_carDockEnablesAccelerometer);
    799         mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
    800                 com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
    801         mLidKeyboardAccessibility = mContext.getResources().getInteger(
    802                 com.android.internal.R.integer.config_lidKeyboardAccessibility);
    803         mLidNavigationAccessibility = mContext.getResources().getInteger(
    804                 com.android.internal.R.integer.config_lidNavigationAccessibility);
    805         // register for dock events
    806         IntentFilter filter = new IntentFilter();
    807         filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
    808         filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
    809         filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
    810         filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
    811         filter.addAction(Intent.ACTION_DOCK_EVENT);
    812         Intent intent = context.registerReceiver(mDockReceiver, filter);
    813         if (intent != null) {
    814             // Retrieve current sticky dock event broadcast.
    815             mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
    816                     Intent.EXTRA_DOCK_STATE_UNDOCKED);
    817         }
    818 
    819         mVibrator = new Vibrator();
    820         mLongPressVibePattern = getLongIntArray(mContext.getResources(),
    821                 com.android.internal.R.array.config_longPressVibePattern);
    822         mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(),
    823                 com.android.internal.R.array.config_virtualKeyVibePattern);
    824         mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(),
    825                 com.android.internal.R.array.config_keyboardTapVibePattern);
    826         mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
    827                 com.android.internal.R.array.config_safeModeDisabledVibePattern);
    828         mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
    829                 com.android.internal.R.array.config_safeModeEnabledVibePattern);
    830 
    831         // Controls rotation and the like.
    832         initializeHdmiState();
    833 
    834         // Match current screen state.
    835         if (mPowerManager.isScreenOn()) {
    836             screenTurningOn(null);
    837         } else {
    838             screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
    839         }
    840     }
    841 
    842     public void setInitialDisplaySize(int width, int height) {
    843         int shortSize;
    844         if (width > height) {
    845             shortSize = height;
    846             mLandscapeRotation = Surface.ROTATION_0;
    847             mSeascapeRotation = Surface.ROTATION_180;
    848             if (mContext.getResources().getBoolean(
    849                     com.android.internal.R.bool.config_reverseDefaultRotation)) {
    850                 mPortraitRotation = Surface.ROTATION_90;
    851                 mUpsideDownRotation = Surface.ROTATION_270;
    852             } else {
    853                 mPortraitRotation = Surface.ROTATION_270;
    854                 mUpsideDownRotation = Surface.ROTATION_90;
    855             }
    856         } else {
    857             shortSize = width;
    858             mPortraitRotation = Surface.ROTATION_0;
    859             mUpsideDownRotation = Surface.ROTATION_180;
    860             if (mContext.getResources().getBoolean(
    861                     com.android.internal.R.bool.config_reverseDefaultRotation)) {
    862                 mLandscapeRotation = Surface.ROTATION_270;
    863                 mSeascapeRotation = Surface.ROTATION_90;
    864             } else {
    865                 mLandscapeRotation = Surface.ROTATION_90;
    866                 mSeascapeRotation = Surface.ROTATION_270;
    867             }
    868         }
    869 
    870         // Determine whether the status bar can hide based on the size
    871         // of the screen.  We assume sizes > 600dp are tablets where we
    872         // will use the system bar.
    873         int shortSizeDp = shortSize
    874                 * DisplayMetrics.DENSITY_DEFAULT
    875                 / DisplayMetrics.DENSITY_DEVICE;
    876         mStatusBarCanHide = shortSizeDp < 600;
    877         mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
    878                 mStatusBarCanHide
    879                 ? com.android.internal.R.dimen.status_bar_height
    880                 : com.android.internal.R.dimen.system_bar_height);
    881 
    882         mHasNavigationBar = mContext.getResources().getBoolean(
    883                 com.android.internal.R.bool.config_showNavigationBar);
    884         // Allow a system property to override this. Used by the emulator.
    885         // See also hasNavigationBar().
    886         String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
    887         if (! "".equals(navBarOverride)) {
    888             if      (navBarOverride.equals("1")) mHasNavigationBar = false;
    889             else if (navBarOverride.equals("0")) mHasNavigationBar = true;
    890         }
    891 
    892         mNavigationBarHeight = mHasNavigationBar
    893                 ? mContext.getResources().getDimensionPixelSize(
    894                     com.android.internal.R.dimen.navigation_bar_height)
    895                 : 0;
    896         mNavigationBarWidth = mHasNavigationBar
    897                 ? mContext.getResources().getDimensionPixelSize(
    898                     com.android.internal.R.dimen.navigation_bar_width)
    899                 : 0;
    900 
    901         if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
    902             mHdmiRotation = mPortraitRotation;
    903         } else {
    904             mHdmiRotation = mLandscapeRotation;
    905         }
    906     }
    907 
    908     public void updateSettings() {
    909         ContentResolver resolver = mContext.getContentResolver();
    910         boolean updateRotation = false;
    911         View addView = null;
    912         View removeView = null;
    913         synchronized (mLock) {
    914             mEndcallBehavior = Settings.System.getInt(resolver,
    915                     Settings.System.END_BUTTON_BEHAVIOR,
    916                     Settings.System.END_BUTTON_BEHAVIOR_DEFAULT);
    917             mIncallPowerBehavior = Settings.Secure.getInt(resolver,
    918                     Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
    919                     Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT);
    920             int accelerometerDefault = Settings.System.getInt(resolver,
    921                     Settings.System.ACCELEROMETER_ROTATION, DEFAULT_ACCELEROMETER_ROTATION);
    922 
    923             // set up rotation lock state
    924             mUserRotationMode = (accelerometerDefault == 0)
    925                 ? WindowManagerPolicy.USER_ROTATION_LOCKED
    926                 : WindowManagerPolicy.USER_ROTATION_FREE;
    927             mUserRotation = Settings.System.getInt(resolver,
    928                     Settings.System.USER_ROTATION,
    929                     Surface.ROTATION_0);
    930 
    931             if (mAccelerometerDefault != accelerometerDefault) {
    932                 mAccelerometerDefault = accelerometerDefault;
    933                 updateOrientationListenerLp();
    934             }
    935 
    936             mOrientationListener.setLogEnabled(
    937                     Settings.System.getInt(resolver,
    938                             Settings.System.WINDOW_ORIENTATION_LISTENER_LOG, 0) != 0);
    939 
    940             if (mSystemReady) {
    941                 int pointerLocation = Settings.System.getInt(resolver,
    942                         Settings.System.POINTER_LOCATION, 0);
    943                 if (mPointerLocationMode != pointerLocation) {
    944                     mPointerLocationMode = pointerLocation;
    945                     if (pointerLocation != 0) {
    946                         if (mPointerLocationView == null) {
    947                             mPointerLocationView = new PointerLocationView(mContext);
    948                             mPointerLocationView.setPrintCoords(false);
    949                             addView = mPointerLocationView;
    950                         }
    951                     } else {
    952                         removeView = mPointerLocationView;
    953                         mPointerLocationView = null;
    954                     }
    955                 }
    956             }
    957             // use screen off timeout setting as the timeout for the lockscreen
    958             mLockScreenTimeout = Settings.System.getInt(resolver,
    959                     Settings.System.SCREEN_OFF_TIMEOUT, 0);
    960             String imId = Settings.Secure.getString(resolver,
    961                     Settings.Secure.DEFAULT_INPUT_METHOD);
    962             boolean hasSoftInput = imId != null && imId.length() > 0;
    963             if (mHasSoftInput != hasSoftInput) {
    964                 mHasSoftInput = hasSoftInput;
    965                 updateRotation = true;
    966             }
    967         }
    968         if (updateRotation) {
    969             updateRotation(true);
    970         }
    971         if (addView != null) {
    972             WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
    973                     WindowManager.LayoutParams.MATCH_PARENT,
    974                     WindowManager.LayoutParams.MATCH_PARENT);
    975             lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
    976             lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
    977                     | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
    978                     | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
    979                     | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
    980             lp.format = PixelFormat.TRANSLUCENT;
    981             lp.setTitle("PointerLocation");
    982             WindowManager wm = (WindowManager)
    983                     mContext.getSystemService(Context.WINDOW_SERVICE);
    984             lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
    985             wm.addView(addView, lp);
    986 
    987             if (mPointerLocationInputChannel == null) {
    988                 try {
    989                     mPointerLocationInputChannel =
    990                         mWindowManager.monitorInput("PointerLocationView");
    991                     InputQueue.registerInputChannel(mPointerLocationInputChannel,
    992                             mPointerLocationInputHandler, mHandler.getLooper().getQueue());
    993                 } catch (RemoteException ex) {
    994                     Slog.e(TAG, "Could not set up input monitoring channel for PointerLocation.",
    995                             ex);
    996                 }
    997             }
    998         }
    999         if (removeView != null) {
   1000             if (mPointerLocationInputChannel != null) {
   1001                 InputQueue.unregisterInputChannel(mPointerLocationInputChannel);
   1002                 mPointerLocationInputChannel.dispose();
   1003                 mPointerLocationInputChannel = null;
   1004             }
   1005 
   1006             WindowManager wm = (WindowManager)
   1007                     mContext.getSystemService(Context.WINDOW_SERVICE);
   1008             wm.removeView(removeView);
   1009         }
   1010     }
   1011 
   1012     private int readRotation(int resID) {
   1013         try {
   1014             int rotation = mContext.getResources().getInteger(resID);
   1015             switch (rotation) {
   1016                 case 0:
   1017                     return Surface.ROTATION_0;
   1018                 case 90:
   1019                     return Surface.ROTATION_90;
   1020                 case 180:
   1021                     return Surface.ROTATION_180;
   1022                 case 270:
   1023                     return Surface.ROTATION_270;
   1024             }
   1025         } catch (Resources.NotFoundException e) {
   1026             // fall through
   1027         }
   1028         return -1;
   1029     }
   1030 
   1031     /** {@inheritDoc} */
   1032     public int checkAddPermission(WindowManager.LayoutParams attrs) {
   1033         int type = attrs.type;
   1034 
   1035         if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
   1036                 || type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
   1037             return WindowManagerImpl.ADD_OKAY;
   1038         }
   1039         String permission = null;
   1040         switch (type) {
   1041             case TYPE_TOAST:
   1042                 // XXX right now the app process has complete control over
   1043                 // this...  should introduce a token to let the system
   1044                 // monitor/control what they are doing.
   1045                 break;
   1046             case TYPE_INPUT_METHOD:
   1047             case TYPE_WALLPAPER:
   1048                 // The window manager will check these.
   1049                 break;
   1050             case TYPE_PHONE:
   1051             case TYPE_PRIORITY_PHONE:
   1052             case TYPE_SYSTEM_ALERT:
   1053             case TYPE_SYSTEM_ERROR:
   1054             case TYPE_SYSTEM_OVERLAY:
   1055                 permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
   1056                 break;
   1057             default:
   1058                 permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
   1059         }
   1060         if (permission != null) {
   1061             if (mContext.checkCallingOrSelfPermission(permission)
   1062                     != PackageManager.PERMISSION_GRANTED) {
   1063                 return WindowManagerImpl.ADD_PERMISSION_DENIED;
   1064             }
   1065         }
   1066         return WindowManagerImpl.ADD_OKAY;
   1067     }
   1068 
   1069     public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
   1070         switch (attrs.type) {
   1071             case TYPE_SYSTEM_OVERLAY:
   1072             case TYPE_SECURE_SYSTEM_OVERLAY:
   1073             case TYPE_TOAST:
   1074                 // These types of windows can't receive input events.
   1075                 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
   1076                         | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
   1077                 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
   1078                 break;
   1079         }
   1080     }
   1081 
   1082     void readLidState() {
   1083         try {
   1084             int sw = mWindowManager.getSwitchState(SW_LID);
   1085             if (sw > 0) {
   1086                 mLidOpen = LID_OPEN;
   1087             } else if (sw == 0) {
   1088                 mLidOpen = LID_CLOSED;
   1089             } else {
   1090                 mLidOpen = LID_ABSENT;
   1091             }
   1092         } catch (RemoteException e) {
   1093             // Ignore
   1094         }
   1095     }
   1096 
   1097     private int determineHiddenState(int mode, int hiddenValue, int visibleValue) {
   1098         if (mLidOpen != LID_ABSENT) {
   1099             switch (mode) {
   1100                 case 1:
   1101                     return mLidOpen == LID_OPEN ? visibleValue : hiddenValue;
   1102                 case 2:
   1103                     return mLidOpen == LID_OPEN ? hiddenValue : visibleValue;
   1104             }
   1105         }
   1106         return visibleValue;
   1107     }
   1108 
   1109     /** {@inheritDoc} */
   1110     public void adjustConfigurationLw(Configuration config) {
   1111         readLidState();
   1112         updateKeyboardVisibility();
   1113 
   1114         if (config.keyboard == Configuration.KEYBOARD_NOKEYS) {
   1115             config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
   1116         } else {
   1117             config.hardKeyboardHidden = determineHiddenState(mLidKeyboardAccessibility,
   1118                     Configuration.HARDKEYBOARDHIDDEN_YES, Configuration.HARDKEYBOARDHIDDEN_NO);
   1119         }
   1120 
   1121         if (config.navigation == Configuration.NAVIGATION_NONAV) {
   1122             config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
   1123         } else {
   1124             config.navigationHidden = determineHiddenState(mLidNavigationAccessibility,
   1125                     Configuration.NAVIGATIONHIDDEN_YES, Configuration.NAVIGATIONHIDDEN_NO);
   1126         }
   1127 
   1128         if (mHasSoftInput || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
   1129             config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
   1130         } else {
   1131             config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
   1132         }
   1133     }
   1134 
   1135     /** {@inheritDoc} */
   1136     public int windowTypeToLayerLw(int type) {
   1137         if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
   1138             return APPLICATION_LAYER;
   1139         }
   1140         switch (type) {
   1141         case TYPE_STATUS_BAR:
   1142             return STATUS_BAR_LAYER;
   1143         case TYPE_STATUS_BAR_PANEL:
   1144             return STATUS_BAR_PANEL_LAYER;
   1145         case TYPE_STATUS_BAR_SUB_PANEL:
   1146             return STATUS_BAR_SUB_PANEL_LAYER;
   1147         case TYPE_SYSTEM_DIALOG:
   1148             return SYSTEM_DIALOG_LAYER;
   1149         case TYPE_SEARCH_BAR:
   1150             return SEARCH_BAR_LAYER;
   1151         case TYPE_PHONE:
   1152             return PHONE_LAYER;
   1153         case TYPE_KEYGUARD:
   1154             return KEYGUARD_LAYER;
   1155         case TYPE_KEYGUARD_DIALOG:
   1156             return KEYGUARD_DIALOG_LAYER;
   1157         case TYPE_SYSTEM_ALERT:
   1158             return SYSTEM_ALERT_LAYER;
   1159         case TYPE_SYSTEM_ERROR:
   1160             return SYSTEM_ERROR_LAYER;
   1161         case TYPE_INPUT_METHOD:
   1162             return INPUT_METHOD_LAYER;
   1163         case TYPE_INPUT_METHOD_DIALOG:
   1164             return INPUT_METHOD_DIALOG_LAYER;
   1165         case TYPE_VOLUME_OVERLAY:
   1166             return VOLUME_OVERLAY_LAYER;
   1167         case TYPE_SYSTEM_OVERLAY:
   1168             return SYSTEM_OVERLAY_LAYER;
   1169         case TYPE_SECURE_SYSTEM_OVERLAY:
   1170             return SECURE_SYSTEM_OVERLAY_LAYER;
   1171         case TYPE_PRIORITY_PHONE:
   1172             return PRIORITY_PHONE_LAYER;
   1173         case TYPE_TOAST:
   1174             return TOAST_LAYER;
   1175         case TYPE_WALLPAPER:
   1176             return WALLPAPER_LAYER;
   1177         case TYPE_DRAG:
   1178             return DRAG_LAYER;
   1179         case TYPE_POINTER:
   1180             return POINTER_LAYER;
   1181         case TYPE_NAVIGATION_BAR:
   1182             return NAVIGATION_BAR_LAYER;
   1183         case TYPE_BOOT_PROGRESS:
   1184             return BOOT_PROGRESS_LAYER;
   1185         case TYPE_HIDDEN_NAV_CONSUMER:
   1186             return HIDDEN_NAV_CONSUMER_LAYER;
   1187         }
   1188         Log.e(TAG, "Unknown window type: " + type);
   1189         return APPLICATION_LAYER;
   1190     }
   1191 
   1192     /** {@inheritDoc} */
   1193     public int subWindowTypeToLayerLw(int type) {
   1194         switch (type) {
   1195         case TYPE_APPLICATION_PANEL:
   1196         case TYPE_APPLICATION_ATTACHED_DIALOG:
   1197             return APPLICATION_PANEL_SUBLAYER;
   1198         case TYPE_APPLICATION_MEDIA:
   1199             return APPLICATION_MEDIA_SUBLAYER;
   1200         case TYPE_APPLICATION_MEDIA_OVERLAY:
   1201             return APPLICATION_MEDIA_OVERLAY_SUBLAYER;
   1202         case TYPE_APPLICATION_SUB_PANEL:
   1203             return APPLICATION_SUB_PANEL_SUBLAYER;
   1204         }
   1205         Log.e(TAG, "Unknown sub-window type: " + type);
   1206         return 0;
   1207     }
   1208 
   1209     public int getMaxWallpaperLayer() {
   1210         return STATUS_BAR_LAYER;
   1211     }
   1212 
   1213     public boolean canStatusBarHide() {
   1214         return mStatusBarCanHide;
   1215     }
   1216 
   1217     public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation) {
   1218         // Assumes that the navigation bar appears on the side of the display in landscape.
   1219         if (fullWidth > fullHeight) {
   1220             return fullWidth - mNavigationBarWidth;
   1221         }
   1222         return fullWidth;
   1223     }
   1224 
   1225     public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation) {
   1226         // Assumes the navigation bar appears on the bottom of the display in portrait.
   1227         return fullHeight
   1228             - (mStatusBarCanHide ? 0 : mStatusBarHeight)
   1229             - ((fullWidth > fullHeight) ? 0 : mNavigationBarHeight);
   1230     }
   1231 
   1232     public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation) {
   1233         return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation);
   1234     }
   1235 
   1236     public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation) {
   1237         // This is the same as getNonDecorDisplayHeight, unless the status bar
   1238         // can hide.  If the status bar can hide, we don't count that as part
   1239         // of the decor; however for purposes of configurations, we do want to
   1240         // exclude it since applications can't generally use that part of the
   1241         // screen.
   1242         return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation)
   1243                 - (mStatusBarCanHide ? mStatusBarHeight : 0);
   1244     }
   1245 
   1246     public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) {
   1247         return attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD;
   1248     }
   1249 
   1250     public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
   1251         return attrs.type != WindowManager.LayoutParams.TYPE_STATUS_BAR
   1252                 && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER;
   1253     }
   1254 
   1255     /** {@inheritDoc} */
   1256     public View addStartingWindow(IBinder appToken, String packageName, int theme,
   1257             CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
   1258             int icon, int windowFlags) {
   1259         if (!SHOW_STARTING_ANIMATIONS) {
   1260             return null;
   1261         }
   1262         if (packageName == null) {
   1263             return null;
   1264         }
   1265 
   1266         try {
   1267             Context context = mContext;
   1268             //Log.i(TAG, "addStartingWindow " + packageName + ": nonLocalizedLabel="
   1269             //        + nonLocalizedLabel + " theme=" + Integer.toHexString(theme));
   1270             if (theme != context.getThemeResId() || labelRes != 0) {
   1271                 try {
   1272                     context = context.createPackageContext(packageName, 0);
   1273                     context.setTheme(theme);
   1274                 } catch (PackageManager.NameNotFoundException e) {
   1275                     // Ignore
   1276                 }
   1277             }
   1278 
   1279             Window win = PolicyManager.makeNewWindow(context);
   1280             if (win.getWindowStyle().getBoolean(
   1281                     com.android.internal.R.styleable.Window_windowDisablePreview, false)) {
   1282                 return null;
   1283             }
   1284 
   1285             Resources r = context.getResources();
   1286             win.setTitle(r.getText(labelRes, nonLocalizedLabel));
   1287 
   1288             win.setType(
   1289                 WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
   1290             // Force the window flags: this is a fake window, so it is not really
   1291             // touchable or focusable by the user.  We also add in the ALT_FOCUSABLE_IM
   1292             // flag because we do know that the next window will take input
   1293             // focus, so we want to get the IME window up on top of us right away.
   1294             win.setFlags(
   1295                 windowFlags|
   1296                 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
   1297                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
   1298                 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
   1299                 windowFlags|
   1300                 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
   1301                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
   1302                 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
   1303 
   1304             if (!compatInfo.supportsScreen()) {
   1305                 win.addFlags(WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW);
   1306             }
   1307 
   1308             win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
   1309                     WindowManager.LayoutParams.MATCH_PARENT);
   1310 
   1311             final WindowManager.LayoutParams params = win.getAttributes();
   1312             params.token = appToken;
   1313             params.packageName = packageName;
   1314             params.windowAnimations = win.getWindowStyle().getResourceId(
   1315                     com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
   1316             params.privateFlags |=
   1317                     WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
   1318             params.setTitle("Starting " + packageName);
   1319 
   1320             WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
   1321             View view = win.getDecorView();
   1322 
   1323             if (win.isFloating()) {
   1324                 // Whoops, there is no way to display an animation/preview
   1325                 // of such a thing!  After all that work...  let's skip it.
   1326                 // (Note that we must do this here because it is in
   1327                 // getDecorView() where the theme is evaluated...  maybe
   1328                 // we should peek the floating attribute from the theme
   1329                 // earlier.)
   1330                 return null;
   1331             }
   1332 
   1333             if (localLOGV) Log.v(
   1334                 TAG, "Adding starting window for " + packageName
   1335                 + " / " + appToken + ": "
   1336                 + (view.getParent() != null ? view : null));
   1337 
   1338             wm.addView(view, params);
   1339 
   1340             // Only return the view if it was successfully added to the
   1341             // window manager... which we can tell by it having a parent.
   1342             return view.getParent() != null ? view : null;
   1343         } catch (WindowManagerImpl.BadTokenException e) {
   1344             // ignore
   1345             Log.w(TAG, appToken + " already running, starting window not displayed");
   1346         } catch (RuntimeException e) {
   1347             // don't crash if something else bad happens, for example a
   1348             // failure loading resources because we are loading from an app
   1349             // on external storage that has been unmounted.
   1350             Log.w(TAG, appToken + " failed creating starting window", e);
   1351         }
   1352 
   1353         return null;
   1354     }
   1355 
   1356     /** {@inheritDoc} */
   1357     public void removeStartingWindow(IBinder appToken, View window) {
   1358         // RuntimeException e = new RuntimeException();
   1359         // Log.i(TAG, "remove " + appToken + " " + window, e);
   1360 
   1361         if (localLOGV) Log.v(
   1362             TAG, "Removing starting window for " + appToken + ": " + window);
   1363 
   1364         if (window != null) {
   1365             WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
   1366             wm.removeView(window);
   1367         }
   1368     }
   1369 
   1370     /**
   1371      * Preflight adding a window to the system.
   1372      *
   1373      * Currently enforces that three window types are singletons:
   1374      * <ul>
   1375      * <li>STATUS_BAR_TYPE</li>
   1376      * <li>KEYGUARD_TYPE</li>
   1377      * </ul>
   1378      *
   1379      * @param win The window to be added
   1380      * @param attrs Information about the window to be added
   1381      *
   1382      * @return If ok, WindowManagerImpl.ADD_OKAY.  If too many singletons, WindowManagerImpl.ADD_MULTIPLE_SINGLETON
   1383      */
   1384     public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
   1385         switch (attrs.type) {
   1386             case TYPE_STATUS_BAR:
   1387                 mContext.enforceCallingOrSelfPermission(
   1388                         android.Manifest.permission.STATUS_BAR_SERVICE,
   1389                         "PhoneWindowManager");
   1390                 // TODO: Need to handle the race condition of the status bar proc
   1391                 // dying and coming back before the removeWindowLw cleanup has happened.
   1392                 if (mStatusBar != null) {
   1393                     return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
   1394                 }
   1395                 mStatusBar = win;
   1396                 break;
   1397             case TYPE_NAVIGATION_BAR:
   1398                 mContext.enforceCallingOrSelfPermission(
   1399                         android.Manifest.permission.STATUS_BAR_SERVICE,
   1400                         "PhoneWindowManager");
   1401                 mNavigationBar = win;
   1402                 if (DEBUG_LAYOUT) Log.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
   1403                 break;
   1404             case TYPE_STATUS_BAR_PANEL:
   1405                 mContext.enforceCallingOrSelfPermission(
   1406                         android.Manifest.permission.STATUS_BAR_SERVICE,
   1407                         "PhoneWindowManager");
   1408                 mStatusBarPanels.add(win);
   1409                 break;
   1410             case TYPE_STATUS_BAR_SUB_PANEL:
   1411                 mContext.enforceCallingOrSelfPermission(
   1412                         android.Manifest.permission.STATUS_BAR_SERVICE,
   1413                         "PhoneWindowManager");
   1414                 mStatusBarPanels.add(win);
   1415                 break;
   1416             case TYPE_KEYGUARD:
   1417                 if (mKeyguard != null) {
   1418                     return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
   1419                 }
   1420                 mKeyguard = win;
   1421                 break;
   1422         }
   1423         return WindowManagerImpl.ADD_OKAY;
   1424     }
   1425 
   1426     /** {@inheritDoc} */
   1427     public void removeWindowLw(WindowState win) {
   1428         if (mStatusBar == win) {
   1429             mStatusBar = null;
   1430         } else if (mKeyguard == win) {
   1431             mKeyguard = null;
   1432         } else if (mNavigationBar == win) {
   1433             mNavigationBar = null;
   1434         } else {
   1435             mStatusBarPanels.remove(win);
   1436         }
   1437     }
   1438 
   1439     static final boolean PRINT_ANIM = false;
   1440 
   1441     /** {@inheritDoc} */
   1442     public int selectAnimationLw(WindowState win, int transit) {
   1443         if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
   1444               + ": transit=" + transit);
   1445         if (transit == TRANSIT_PREVIEW_DONE) {
   1446             if (win.hasAppShownWindows()) {
   1447                 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
   1448                 return com.android.internal.R.anim.app_starting_exit;
   1449             }
   1450         }
   1451 
   1452         return 0;
   1453     }
   1454 
   1455     public Animation createForceHideEnterAnimation() {
   1456         return AnimationUtils.loadAnimation(mContext,
   1457                 com.android.internal.R.anim.lock_screen_behind_enter);
   1458     }
   1459 
   1460     static ITelephony getTelephonyService() {
   1461         ITelephony telephonyService = ITelephony.Stub.asInterface(
   1462                 ServiceManager.checkService(Context.TELEPHONY_SERVICE));
   1463         if (telephonyService == null) {
   1464             Log.w(TAG, "Unable to find ITelephony interface.");
   1465         }
   1466         return telephonyService;
   1467     }
   1468 
   1469     static IAudioService getAudioService() {
   1470         IAudioService audioService = IAudioService.Stub.asInterface(
   1471                 ServiceManager.checkService(Context.AUDIO_SERVICE));
   1472         if (audioService == null) {
   1473             Log.w(TAG, "Unable to find IAudioService interface.");
   1474         }
   1475         return audioService;
   1476     }
   1477 
   1478     boolean keyguardOn() {
   1479         return keyguardIsShowingTq() || inKeyguardRestrictedKeyInputMode();
   1480     }
   1481 
   1482     private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
   1483             WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
   1484             WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
   1485         };
   1486 
   1487     /** {@inheritDoc} */
   1488     @Override
   1489     public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
   1490         final boolean keyguardOn = keyguardOn();
   1491         final int keyCode = event.getKeyCode();
   1492         final int repeatCount = event.getRepeatCount();
   1493         final int metaState = event.getMetaState();
   1494         final int flags = event.getFlags();
   1495         final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
   1496         final boolean canceled = event.isCanceled();
   1497 
   1498         if (false) {
   1499             Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
   1500                     + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed);
   1501         }
   1502 
   1503         // If we think we might have a volume down & power key chord on the way
   1504         // but we're not sure, then tell the dispatcher to wait a little while and
   1505         // try again later before dispatching.
   1506         if ((flags & KeyEvent.FLAG_FALLBACK) == 0) {
   1507             if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) {
   1508                 final long now = SystemClock.uptimeMillis();
   1509                 final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
   1510                 if (now < timeoutTime) {
   1511                     return timeoutTime - now;
   1512                 }
   1513             }
   1514             if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
   1515                     && mVolumeDownKeyConsumedByScreenshotChord) {
   1516                 if (!down) {
   1517                     mVolumeDownKeyConsumedByScreenshotChord = false;
   1518                 }
   1519                 return -1;
   1520             }
   1521         }
   1522 
   1523         // First we always handle the home key here, so applications
   1524         // can never break it, although if keyguard is on, we do let
   1525         // it handle it, because that gives us the correct 5 second
   1526         // timeout.
   1527         if (keyCode == KeyEvent.KEYCODE_HOME) {
   1528             // If we have released the home key, and didn't do anything else
   1529             // while it was pressed, then it is time to go home!
   1530             if (mHomePressed && !down) {
   1531                 mHomePressed = false;
   1532                 if (!canceled) {
   1533                     // If an incoming call is ringing, HOME is totally disabled.
   1534                     // (The user is already on the InCallScreen at this point,
   1535                     // and his ONLY options are to answer or reject the call.)
   1536                     boolean incomingRinging = false;
   1537                     try {
   1538                         ITelephony telephonyService = getTelephonyService();
   1539                         if (telephonyService != null) {
   1540                             incomingRinging = telephonyService.isRinging();
   1541                         }
   1542                     } catch (RemoteException ex) {
   1543                         Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
   1544                     }
   1545 
   1546                     if (incomingRinging) {
   1547                         Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
   1548                     } else {
   1549                         launchHomeFromHotKey();
   1550                     }
   1551                 } else {
   1552                     Log.i(TAG, "Ignoring HOME; event canceled.");
   1553                 }
   1554                 return -1;
   1555             }
   1556 
   1557             // If a system window has focus, then it doesn't make sense
   1558             // right now to interact with applications.
   1559             WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
   1560             if (attrs != null) {
   1561                 final int type = attrs.type;
   1562                 if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
   1563                         || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
   1564                     // the "app" is keyguard, so give it the key
   1565                     return 0;
   1566                 }
   1567                 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
   1568                 for (int i=0; i<typeCount; i++) {
   1569                     if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
   1570                         // don't do anything, but also don't pass it to the app
   1571                         return -1;
   1572                     }
   1573                 }
   1574             }
   1575 
   1576             if (down) {
   1577                 if (repeatCount == 0) {
   1578                     mHomePressed = true;
   1579                 } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
   1580                     if (!keyguardOn) {
   1581                         handleLongPressOnHome();
   1582                     }
   1583                 }
   1584             }
   1585             return -1;
   1586         } else if (keyCode == KeyEvent.KEYCODE_MENU) {
   1587             // Hijack modified menu keys for debugging features
   1588             final int chordBug = KeyEvent.META_SHIFT_ON;
   1589 
   1590             if (down && repeatCount == 0) {
   1591                 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
   1592                     Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
   1593                     mContext.sendOrderedBroadcast(intent, null);
   1594                     return -1;
   1595                 } else if (SHOW_PROCESSES_ON_ALT_MENU &&
   1596                         (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
   1597                     Intent service = new Intent();
   1598                     service.setClassName(mContext, "com.android.server.LoadAverageService");
   1599                     ContentResolver res = mContext.getContentResolver();
   1600                     boolean shown = Settings.System.getInt(
   1601                             res, Settings.System.SHOW_PROCESSES, 0) != 0;
   1602                     if (!shown) {
   1603                         mContext.startService(service);
   1604                     } else {
   1605                         mContext.stopService(service);
   1606                     }
   1607                     Settings.System.putInt(
   1608                             res, Settings.System.SHOW_PROCESSES, shown ? 0 : 1);
   1609                     return -1;
   1610                 }
   1611             }
   1612         } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
   1613             if (down) {
   1614                 if (repeatCount == 0) {
   1615                     mShortcutKeyPressed = keyCode;
   1616                     mConsumeShortcutKeyUp = false;
   1617                 }
   1618             } else if (keyCode == mShortcutKeyPressed) {
   1619                 mShortcutKeyPressed = -1;
   1620                 if (mConsumeShortcutKeyUp) {
   1621                     mConsumeShortcutKeyUp = false;
   1622                     return -1;
   1623                 }
   1624             }
   1625             return 0;
   1626         } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
   1627             if (down && repeatCount == 0) {
   1628                 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
   1629             }
   1630             return -1;
   1631         }
   1632 
   1633         // Shortcuts are invoked through Search+key, so intercept those here
   1634         // Any printing key that is chorded with Search should be consumed
   1635         // even if no shortcut was invoked.  This prevents text from being
   1636         // inadvertently inserted when using a keyboard that has built-in macro
   1637         // shortcut keys (that emit Search+x) and some of them are not registered.
   1638         if (mShortcutKeyPressed != -1) {
   1639             final KeyCharacterMap kcm = event.getKeyCharacterMap();
   1640             if (kcm.isPrintingKey(keyCode)) {
   1641                 mConsumeShortcutKeyUp = true;
   1642                 if (down && repeatCount == 0 && !keyguardOn) {
   1643                     Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
   1644                     if (shortcutIntent != null) {
   1645                         shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   1646                         try {
   1647                             mContext.startActivity(shortcutIntent);
   1648                         } catch (ActivityNotFoundException ex) {
   1649                             Slog.w(TAG, "Dropping shortcut key combination because "
   1650                                     + "the activity to which it is registered was not found: "
   1651                                     + KeyEvent.keyCodeToString(mShortcutKeyPressed)
   1652                                     + "+" + KeyEvent.keyCodeToString(keyCode), ex);
   1653                         }
   1654                     } else {
   1655                         Slog.i(TAG, "Dropping unregistered shortcut key combination: "
   1656                                 + KeyEvent.keyCodeToString(mShortcutKeyPressed)
   1657                                 + "+" + KeyEvent.keyCodeToString(keyCode));
   1658                     }
   1659                 }
   1660                 return -1;
   1661             }
   1662         }
   1663 
   1664         // Invoke shortcuts using Meta.
   1665         if (down && repeatCount == 0
   1666                 && (metaState & KeyEvent.META_META_ON) != 0) {
   1667             final KeyCharacterMap kcm = event.getKeyCharacterMap();
   1668             Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
   1669                     metaState & ~(KeyEvent.META_META_ON
   1670                             | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
   1671             if (shortcutIntent != null) {
   1672                 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   1673                 try {
   1674                     mContext.startActivity(shortcutIntent);
   1675                 } catch (ActivityNotFoundException ex) {
   1676                     Slog.w(TAG, "Dropping shortcut key combination because "
   1677                             + "the activity to which it is registered was not found: "
   1678                             + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
   1679                 }
   1680                 return -1;
   1681             }
   1682         }
   1683 
   1684         // Handle application launch keys.
   1685         if (down && repeatCount == 0) {
   1686             String category = sApplicationLaunchKeyCategories.get(keyCode);
   1687             if (category != null) {
   1688                 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
   1689                 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   1690                 try {
   1691                     mContext.startActivity(intent);
   1692                 } catch (ActivityNotFoundException ex) {
   1693                     Slog.w(TAG, "Dropping application launch key because "
   1694                             + "the activity to which it is registered was not found: "
   1695                             + "keyCode=" + keyCode + ", category=" + category, ex);
   1696                 }
   1697                 return -1;
   1698             }
   1699         }
   1700 
   1701         // Display task switcher for ALT-TAB or Meta-TAB.
   1702         if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
   1703             if (mRecentAppsDialogHeldModifiers == 0) {
   1704                 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
   1705                 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)
   1706                         || KeyEvent.metaStateHasModifiers(
   1707                                 shiftlessModifiers, KeyEvent.META_META_ON)) {
   1708                     mRecentAppsDialogHeldModifiers = shiftlessModifiers;
   1709                     showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW);
   1710                     return -1;
   1711                 }
   1712             }
   1713         } else if (!down && mRecentAppsDialogHeldModifiers != 0
   1714                 && (metaState & mRecentAppsDialogHeldModifiers) == 0) {
   1715             mRecentAppsDialogHeldModifiers = 0;
   1716             showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH);
   1717         }
   1718 
   1719         // Let the application handle the key.
   1720         return 0;
   1721     }
   1722 
   1723     /** {@inheritDoc} */
   1724     @Override
   1725     public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
   1726         // Note: This method is only called if the initial down was unhandled.
   1727         if (DEBUG_FALLBACK) {
   1728             Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
   1729                     + ", flags=" + event.getFlags()
   1730                     + ", keyCode=" + event.getKeyCode()
   1731                     + ", scanCode=" + event.getScanCode()
   1732                     + ", metaState=" + event.getMetaState()
   1733                     + ", repeatCount=" + event.getRepeatCount()
   1734                     + ", policyFlags=" + policyFlags);
   1735         }
   1736 
   1737         if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
   1738             final KeyCharacterMap kcm = event.getKeyCharacterMap();
   1739             final int keyCode = event.getKeyCode();
   1740             final int metaState = event.getMetaState();
   1741 
   1742             // Check for fallback actions specified by the key character map.
   1743             if (getFallbackAction(kcm, keyCode, metaState, mFallbackAction)) {
   1744                 if (DEBUG_FALLBACK) {
   1745                     Slog.d(TAG, "Fallback: keyCode=" + mFallbackAction.keyCode
   1746                             + " metaState=" + Integer.toHexString(mFallbackAction.metaState));
   1747                 }
   1748 
   1749                 int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
   1750                 KeyEvent fallbackEvent = KeyEvent.obtain(
   1751                         event.getDownTime(), event.getEventTime(),
   1752                         event.getAction(), mFallbackAction.keyCode,
   1753                         event.getRepeatCount(), mFallbackAction.metaState,
   1754                         event.getDeviceId(), event.getScanCode(),
   1755                         flags, event.getSource(), null);
   1756                 int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true);
   1757                 if ((actions & ACTION_PASS_TO_USER) != 0) {
   1758                     long delayMillis = interceptKeyBeforeDispatching(
   1759                             win, fallbackEvent, policyFlags);
   1760                     if (delayMillis == 0) {
   1761                         if (DEBUG_FALLBACK) {
   1762                             Slog.d(TAG, "Performing fallback.");
   1763                         }
   1764                         return fallbackEvent;
   1765                     }
   1766                 }
   1767                 fallbackEvent.recycle();
   1768             }
   1769         }
   1770 
   1771         if (DEBUG_FALLBACK) {
   1772             Slog.d(TAG, "No fallback.");
   1773         }
   1774         return null;
   1775     }
   1776 
   1777     private boolean getFallbackAction(KeyCharacterMap kcm, int keyCode, int metaState,
   1778             FallbackAction outFallbackAction) {
   1779         // Consult the key character map for specific fallback actions.
   1780         // For example, map NUMPAD_1 to MOVE_HOME when NUMLOCK is not pressed.
   1781         return kcm.getFallbackAction(keyCode, metaState, outFallbackAction);
   1782     }
   1783 
   1784     /**
   1785      * A home key -> launch home action was detected.  Take the appropriate action
   1786      * given the situation with the keyguard.
   1787      */
   1788     void launchHomeFromHotKey() {
   1789         if (mKeyguardMediator.isShowingAndNotHidden()) {
   1790             // don't launch home if keyguard showing
   1791         } else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {
   1792             // when in keyguard restricted mode, must first verify unlock
   1793             // before launching home
   1794             mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() {
   1795                 public void onKeyguardExitResult(boolean success) {
   1796                     if (success) {
   1797                         try {
   1798                             ActivityManagerNative.getDefault().stopAppSwitches();
   1799                         } catch (RemoteException e) {
   1800                         }
   1801                         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
   1802                         startDockOrHome();
   1803                     }
   1804                 }
   1805             });
   1806         } else {
   1807             // no keyguard stuff to worry about, just launch home!
   1808             try {
   1809                 ActivityManagerNative.getDefault().stopAppSwitches();
   1810             } catch (RemoteException e) {
   1811             }
   1812             sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
   1813             startDockOrHome();
   1814         }
   1815     }
   1816 
   1817     /**
   1818      * A delayed callback use to determine when it is okay to re-allow applications
   1819      * to use certain system UI flags.  This is used to prevent applications from
   1820      * spamming system UI changes that prevent the navigation bar from being shown.
   1821      */
   1822     final Runnable mAllowSystemUiDelay = new Runnable() {
   1823         @Override public void run() {
   1824         }
   1825     };
   1826 
   1827     /**
   1828      * Input handler used while nav bar is hidden.  Captures any touch on the screen,
   1829      * to determine when the nav bar should be shown and prevent applications from
   1830      * receiving those touches.
   1831      */
   1832     final InputHandler mHideNavInputHandler = new BaseInputHandler() {
   1833         @Override
   1834         public void handleMotion(MotionEvent event, InputQueue.FinishedCallback finishedCallback) {
   1835             boolean handled = false;
   1836             try {
   1837                 if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
   1838                     if (event.getAction() == MotionEvent.ACTION_DOWN) {
   1839                         // When the user taps down, we re-show the nav bar.
   1840                         boolean changed = false;
   1841                         synchronized (mLock) {
   1842                             // Any user activity always causes us to show the navigation controls,
   1843                             // if they had been hidden.
   1844                             int newVal = mResettingSystemUiFlags
   1845                                     | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
   1846                             if (mResettingSystemUiFlags != newVal) {
   1847                                 mResettingSystemUiFlags = newVal;
   1848                                 changed = true;
   1849                             }
   1850                             // We don't allow the system's nav bar to be hidden
   1851                             // again for 1 second, to prevent applications from
   1852                             // spamming us and keeping it from being shown.
   1853                             newVal = mForceClearedSystemUiFlags
   1854                                     | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
   1855                             if (mForceClearedSystemUiFlags != newVal) {
   1856                                 mForceClearedSystemUiFlags = newVal;
   1857                                 changed = true;
   1858                                 mHandler.postDelayed(new Runnable() {
   1859                                     @Override public void run() {
   1860                                         synchronized (mLock) {
   1861                                             mForceClearedSystemUiFlags &=
   1862                                                     ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
   1863                                         }
   1864                                         mWindowManagerFuncs.reevaluateStatusBarVisibility();
   1865                                     }
   1866                                 }, 1000);
   1867                             }
   1868                         }
   1869                         if (changed) {
   1870                             mWindowManagerFuncs.reevaluateStatusBarVisibility();
   1871                         }
   1872                     }
   1873                 }
   1874             } finally {
   1875                 finishedCallback.finished(handled);
   1876             }
   1877         }
   1878     };
   1879 
   1880     @Override
   1881     public int adjustSystemUiVisibilityLw(int visibility) {
   1882         // Reset any bits in mForceClearingStatusBarVisibility that
   1883         // are now clear.
   1884         mResettingSystemUiFlags &= visibility;
   1885         // Clear any bits in the new visibility that are currently being
   1886         // force cleared, before reporting it.
   1887         return visibility & ~mResettingSystemUiFlags
   1888                 & ~mForceClearedSystemUiFlags;
   1889     }
   1890 
   1891     public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) {
   1892         final int fl = attrs.flags;
   1893 
   1894         if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
   1895                 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
   1896             contentInset.set(mCurLeft, mCurTop,
   1897                     (mRestrictedScreenLeft+mRestrictedScreenWidth) - mCurRight,
   1898                     (mRestrictedScreenTop+mRestrictedScreenHeight) - mCurBottom);
   1899         } else {
   1900             contentInset.setEmpty();
   1901         }
   1902     }
   1903 
   1904     /** {@inheritDoc} */
   1905     public void beginLayoutLw(int displayWidth, int displayHeight, int displayRotation) {
   1906         mUnrestrictedScreenLeft = mUnrestrictedScreenTop = 0;
   1907         mUnrestrictedScreenWidth = displayWidth;
   1908         mUnrestrictedScreenHeight = displayHeight;
   1909         mRestrictedScreenLeft = mRestrictedScreenTop = 0;
   1910         mRestrictedScreenWidth = displayWidth;
   1911         mRestrictedScreenHeight = displayHeight;
   1912         mDockLeft = mContentLeft = mCurLeft = 0;
   1913         mDockTop = mContentTop = mCurTop = 0;
   1914         mDockRight = mContentRight = mCurRight = displayWidth;
   1915         mDockBottom = mContentBottom = mCurBottom = displayHeight;
   1916         mDockLayer = 0x10000000;
   1917 
   1918         // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
   1919         final Rect pf = mTmpParentFrame;
   1920         final Rect df = mTmpDisplayFrame;
   1921         final Rect vf = mTmpVisibleFrame;
   1922         pf.left = df.left = vf.left = mDockLeft;
   1923         pf.top = df.top = vf.top = mDockTop;
   1924         pf.right = df.right = vf.right = mDockRight;
   1925         pf.bottom = df.bottom = vf.bottom = mDockBottom;
   1926 
   1927         final boolean navVisible = (mNavigationBar == null || mNavigationBar.isVisibleLw()) &&
   1928                 (mLastSystemUiFlags&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
   1929 
   1930         // When the navigation bar isn't visible, we put up a fake
   1931         // input window to catch all touch events.  This way we can
   1932         // detect when the user presses anywhere to bring back the nav
   1933         // bar and ensure the application doesn't see the event.
   1934         if (navVisible) {
   1935             if (mHideNavFakeWindow != null) {
   1936                 mHideNavFakeWindow.dismiss();
   1937                 mHideNavFakeWindow = null;
   1938             }
   1939         } else if (mHideNavFakeWindow == null) {
   1940             mHideNavFakeWindow = mWindowManagerFuncs.addFakeWindow(
   1941                     mHandler.getLooper(), mHideNavInputHandler,
   1942                     "hidden nav", WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER,
   1943                     0, false, false, true);
   1944         }
   1945 
   1946         // decide where the status bar goes ahead of time
   1947         if (mStatusBar != null) {
   1948             if (mNavigationBar != null) {
   1949                 // Force the navigation bar to its appropriate place and
   1950                 // size.  We need to do this directly, instead of relying on
   1951                 // it to bubble up from the nav bar, because this needs to
   1952                 // change atomically with screen rotations.
   1953                 if (displayWidth < displayHeight) {
   1954                     // Portrait screen; nav bar goes on bottom.
   1955                     mTmpNavigationFrame.set(0, displayHeight-mNavigationBarHeight,
   1956                             displayWidth, displayHeight);
   1957                     if (navVisible) {
   1958                         mDockBottom = mTmpNavigationFrame.top;
   1959                         mRestrictedScreenHeight = mDockBottom - mDockTop;
   1960                     } else {
   1961                         // We currently want to hide the navigation UI.  Do this by just
   1962                         // moving it off the screen, so it can still receive input events
   1963                         // to know when to be re-shown.
   1964                         mTmpNavigationFrame.offset(0, mNavigationBarHeight);
   1965                     }
   1966                 } else {
   1967                     // Landscape screen; nav bar goes to the right.
   1968                     mTmpNavigationFrame.set(displayWidth-mNavigationBarWidth, 0,
   1969                             displayWidth, displayHeight);
   1970                     if (navVisible) {
   1971                         mDockRight = mTmpNavigationFrame.left;
   1972                         mRestrictedScreenWidth = mDockRight - mDockLeft;
   1973                     } else {
   1974                         // We currently want to hide the navigation UI.  Do this by just
   1975                         // moving it off the screen, so it can still receive input events
   1976                         // to know when to be re-shown.
   1977                         mTmpNavigationFrame.offset(mNavigationBarWidth, 0);
   1978                     }
   1979                 }
   1980                 // And compute the final frame.
   1981                 mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
   1982                         mTmpNavigationFrame, mTmpNavigationFrame);
   1983                 if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
   1984             }
   1985             if (DEBUG_LAYOUT) Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
   1986                     mDockLeft, mDockTop, mDockRight, mDockBottom));
   1987 
   1988             // apply navigation bar insets
   1989             pf.left = df.left = vf.left = mDockLeft;
   1990             pf.top = df.top = vf.top = mDockTop;
   1991             pf.right = df.right = vf.right = mDockRight;
   1992             pf.bottom = df.bottom = vf.bottom = mDockBottom;
   1993 
   1994             mStatusBar.computeFrameLw(pf, df, vf, vf);
   1995 
   1996             if (mStatusBar.isVisibleLw()) {
   1997                 // If the status bar is hidden, we don't want to cause
   1998                 // windows behind it to scroll.
   1999                 final Rect r = mStatusBar.getFrameLw();
   2000                 if (mStatusBarCanHide) {
   2001                     // Status bar may go away, so the screen area it occupies
   2002                     // is available to apps but just covering them when the
   2003                     // status bar is visible.
   2004                     if (mDockTop == r.top) mDockTop = r.bottom;
   2005                     else if (mDockBottom == r.bottom) mDockBottom = r.top;
   2006 
   2007                     mContentTop = mCurTop = mDockTop;
   2008                     mContentBottom = mCurBottom = mDockBottom;
   2009                     mContentLeft = mCurLeft = mDockLeft;
   2010                     mContentRight = mCurRight = mDockRight;
   2011 
   2012                     if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: " +
   2013                         String.format(
   2014                             "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
   2015                             mDockLeft, mDockTop, mDockRight, mDockBottom,
   2016                             mContentLeft, mContentTop, mContentRight, mContentBottom,
   2017                             mCurLeft, mCurTop, mCurRight, mCurBottom));
   2018                 } else {
   2019                     // Status bar can't go away; the part of the screen it
   2020                     // covers does not exist for anything behind it.
   2021                     if (mRestrictedScreenTop == r.top) {
   2022                         mRestrictedScreenTop = r.bottom;
   2023                         mRestrictedScreenHeight -= (r.bottom-r.top);
   2024                     } else if ((mRestrictedScreenHeight-mRestrictedScreenTop) == r.bottom) {
   2025                         mRestrictedScreenHeight -= (r.bottom-r.top);
   2026                     }
   2027 
   2028                     mContentTop = mCurTop = mDockTop = mRestrictedScreenTop;
   2029                     mContentBottom = mCurBottom = mDockBottom
   2030                             = mRestrictedScreenTop + mRestrictedScreenHeight;
   2031                     if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: restricted screen area: ("
   2032                             + mRestrictedScreenLeft + ","
   2033                             + mRestrictedScreenTop + ","
   2034                             + (mRestrictedScreenLeft + mRestrictedScreenWidth) + ","
   2035                             + (mRestrictedScreenTop + mRestrictedScreenHeight) + ")");
   2036                 }
   2037             }
   2038         }
   2039     }
   2040 
   2041     void setAttachedWindowFrames(WindowState win, int fl, int adjust,
   2042             WindowState attached, boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf) {
   2043         if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
   2044             // Here's a special case: if this attached window is a panel that is
   2045             // above the dock window, and the window it is attached to is below
   2046             // the dock window, then the frames we computed for the window it is
   2047             // attached to can not be used because the dock is effectively part
   2048             // of the underlying window and the attached window is floating on top
   2049             // of the whole thing.  So, we ignore the attached window and explicitly
   2050             // compute the frames that would be appropriate without the dock.
   2051             df.left = cf.left = vf.left = mDockLeft;
   2052             df.top = cf.top = vf.top = mDockTop;
   2053             df.right = cf.right = vf.right = mDockRight;
   2054             df.bottom = cf.bottom = vf.bottom = mDockBottom;
   2055         } else {
   2056             // The effective display frame of the attached window depends on
   2057             // whether it is taking care of insetting its content.  If not,
   2058             // we need to use the parent's content frame so that the entire
   2059             // window is positioned within that content.  Otherwise we can use
   2060             // the display frame and let the attached window take care of
   2061             // positioning its content appropriately.
   2062             if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
   2063                 cf.set(attached.getDisplayFrameLw());
   2064             } else {
   2065                 // If the window is resizing, then we want to base the content
   2066                 // frame on our attached content frame to resize...  however,
   2067                 // things can be tricky if the attached window is NOT in resize
   2068                 // mode, in which case its content frame will be larger.
   2069                 // Ungh.  So to deal with that, make sure the content frame
   2070                 // we end up using is not covering the IM dock.
   2071                 cf.set(attached.getContentFrameLw());
   2072                 if (attached.getSurfaceLayer() < mDockLayer) {
   2073                     if (cf.left < mContentLeft) cf.left = mContentLeft;
   2074                     if (cf.top < mContentTop) cf.top = mContentTop;
   2075                     if (cf.right > mContentRight) cf.right = mContentRight;
   2076                     if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
   2077                 }
   2078             }
   2079             df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
   2080             vf.set(attached.getVisibleFrameLw());
   2081         }
   2082         // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
   2083         // window should be positioned relative to its parent or the entire
   2084         // screen.
   2085         pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
   2086                 ? attached.getFrameLw() : df);
   2087     }
   2088 
   2089     /** {@inheritDoc} */
   2090     public void layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs,
   2091             WindowState attached) {
   2092         // we've already done the status bar
   2093         if (win == mStatusBar || win == mNavigationBar) {
   2094             return;
   2095         }
   2096 
   2097         final int fl = attrs.flags;
   2098         final int sim = attrs.softInputMode;
   2099 
   2100         final Rect pf = mTmpParentFrame;
   2101         final Rect df = mTmpDisplayFrame;
   2102         final Rect cf = mTmpContentFrame;
   2103         final Rect vf = mTmpVisibleFrame;
   2104 
   2105         final boolean hasNavBar = (mHasNavigationBar
   2106                 && mNavigationBar != null && mNavigationBar.isVisibleLw());
   2107 
   2108         if (attrs.type == TYPE_INPUT_METHOD) {
   2109             pf.left = df.left = cf.left = vf.left = mDockLeft;
   2110             pf.top = df.top = cf.top = vf.top = mDockTop;
   2111             pf.right = df.right = cf.right = vf.right = mDockRight;
   2112             pf.bottom = df.bottom = cf.bottom = vf.bottom = mDockBottom;
   2113             // IM dock windows always go to the bottom of the screen.
   2114             attrs.gravity = Gravity.BOTTOM;
   2115             mDockLayer = win.getSurfaceLayer();
   2116         } else {
   2117             final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
   2118 
   2119             if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
   2120                     == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
   2121                 if (DEBUG_LAYOUT)
   2122                     Log.v(TAG, "layoutWindowLw(" + attrs.getTitle()
   2123                             + "): IN_SCREEN, INSET_DECOR, !FULLSCREEN");
   2124                 // This is the case for a normal activity window: we want it
   2125                 // to cover all of the screen space, and it can take care of
   2126                 // moving its contents to account for screen decorations that
   2127                 // intrude into that space.
   2128                 if (attached != null) {
   2129                     // If this window is attached to another, our display
   2130                     // frame is the same as the one we are attached to.
   2131                     setAttachedWindowFrames(win, fl, sim, attached, true, pf, df, cf, vf);
   2132                 } else {
   2133                     if (attrs.type == TYPE_STATUS_BAR_PANEL
   2134                             || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
   2135                         // Status bar panels are the only windows who can go on top of
   2136                         // the status bar.  They are protected by the STATUS_BAR_SERVICE
   2137                         // permission, so they have the same privileges as the status
   2138                         // bar itself.
   2139                         //
   2140                         // However, they should still dodge the navigation bar if it exists.
   2141 
   2142                         pf.left = df.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
   2143                         pf.top = df.top = mUnrestrictedScreenTop;
   2144                         pf.right = df.right = hasNavBar
   2145                                             ? mRestrictedScreenLeft+mRestrictedScreenWidth
   2146                                             : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
   2147                         pf.bottom = df.bottom = hasNavBar
   2148                                               ? mRestrictedScreenTop+mRestrictedScreenHeight
   2149                                               : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
   2150 
   2151                         if (DEBUG_LAYOUT) {
   2152                             Log.v(TAG, String.format(
   2153                                         "Laying out status bar window: (%d,%d - %d,%d)",
   2154                                         pf.left, pf.top, pf.right, pf.bottom));
   2155                         }
   2156                     } else {
   2157                         pf.left = df.left = mRestrictedScreenLeft;
   2158                         pf.top = df.top = mRestrictedScreenTop;
   2159                         pf.right = df.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
   2160                         pf.bottom = df.bottom = mRestrictedScreenTop+mRestrictedScreenHeight;
   2161                     }
   2162                     if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
   2163                         cf.left = mDockLeft;
   2164                         cf.top = mDockTop;
   2165                         cf.right = mDockRight;
   2166                         cf.bottom = mDockBottom;
   2167                     } else {
   2168                         cf.left = mContentLeft;
   2169                         cf.top = mContentTop;
   2170                         cf.right = mContentRight;
   2171                         cf.bottom = mContentBottom;
   2172                     }
   2173                     if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
   2174                         vf.left = mCurLeft;
   2175                         vf.top = mCurTop;
   2176                         vf.right = mCurRight;
   2177                         vf.bottom = mCurBottom;
   2178                     } else {
   2179                         vf.set(cf);
   2180                     }
   2181                 }
   2182             } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0) {
   2183                 if (DEBUG_LAYOUT)
   2184                     Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): IN_SCREEN");
   2185                 // A window that has requested to fill the entire screen just
   2186                 // gets everything, period.
   2187                 if (attrs.type == TYPE_STATUS_BAR_PANEL
   2188                         || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
   2189                     pf.left = df.left = cf.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
   2190                     pf.top = df.top = cf.top = mUnrestrictedScreenTop;
   2191                     pf.right = df.right = cf.right = hasNavBar
   2192                                         ? mRestrictedScreenLeft+mRestrictedScreenWidth
   2193                                         : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
   2194                     pf.bottom = df.bottom = cf.bottom = hasNavBar
   2195                                           ? mRestrictedScreenTop+mRestrictedScreenHeight
   2196                                           : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
   2197 
   2198                     if (DEBUG_LAYOUT) {
   2199                         Log.v(TAG, String.format(
   2200                                     "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
   2201                                     pf.left, pf.top, pf.right, pf.bottom));
   2202                     }
   2203                 } else if (attrs.type == TYPE_NAVIGATION_BAR) {
   2204                     // The navigation bar has Real Ultimate Power.
   2205                     pf.left = df.left = mUnrestrictedScreenLeft;
   2206                     pf.top = df.top = mUnrestrictedScreenTop;
   2207                     pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
   2208                     pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
   2209                     if (DEBUG_LAYOUT) {
   2210                         Log.v(TAG, String.format(
   2211                                     "Laying out navigation bar window: (%d,%d - %d,%d)",
   2212                                     pf.left, pf.top, pf.right, pf.bottom));
   2213                     }
   2214                 } else if (attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
   2215                         && ((fl & FLAG_FULLSCREEN) != 0)) {
   2216                     // Fullscreen secure system overlays get what they ask for.
   2217                     pf.left = df.left = mUnrestrictedScreenLeft;
   2218                     pf.top = df.top = mUnrestrictedScreenTop;
   2219                     pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
   2220                     pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
   2221                 } else {
   2222                     pf.left = df.left = cf.left = mRestrictedScreenLeft;
   2223                     pf.top = df.top = cf.top = mRestrictedScreenTop;
   2224                     pf.right = df.right = cf.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
   2225                     pf.bottom = df.bottom = cf.bottom
   2226                             = mRestrictedScreenTop+mRestrictedScreenHeight;
   2227                 }
   2228                 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
   2229                     vf.left = mCurLeft;
   2230                     vf.top = mCurTop;
   2231                     vf.right = mCurRight;
   2232                     vf.bottom = mCurBottom;
   2233                 } else {
   2234                     vf.set(cf);
   2235                 }
   2236             } else if (attached != null) {
   2237                 if (DEBUG_LAYOUT)
   2238                     Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): attached to " + attached);
   2239                 // A child window should be placed inside of the same visible
   2240                 // frame that its parent had.
   2241                 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, cf, vf);
   2242             } else {
   2243                 if (DEBUG_LAYOUT)
   2244                     Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): normal window");
   2245                 // Otherwise, a normal window must be placed inside the content
   2246                 // of all screen decorations.
   2247                 if (attrs.type == TYPE_STATUS_BAR_PANEL) {
   2248                     // Status bar panels are the only windows who can go on top of
   2249                     // the status bar.  They are protected by the STATUS_BAR_SERVICE
   2250                     // permission, so they have the same privileges as the status
   2251                     // bar itself.
   2252                     pf.left = df.left = cf.left = mRestrictedScreenLeft;
   2253                     pf.top = df.top = cf.top = mRestrictedScreenTop;
   2254                     pf.right = df.right = cf.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
   2255                     pf.bottom = df.bottom = cf.bottom
   2256                             = mRestrictedScreenTop+mRestrictedScreenHeight;
   2257                 } else {
   2258                     pf.left = mContentLeft;
   2259                     pf.top = mContentTop;
   2260                     pf.right = mContentRight;
   2261                     pf.bottom = mContentBottom;
   2262                     if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
   2263                         df.left = cf.left = mDockLeft;
   2264                         df.top = cf.top = mDockTop;
   2265                         df.right = cf.right = mDockRight;
   2266                         df.bottom = cf.bottom = mDockBottom;
   2267                     } else {
   2268                         df.left = cf.left = mContentLeft;
   2269                         df.top = cf.top = mContentTop;
   2270                         df.right = cf.right = mContentRight;
   2271                         df.bottom = cf.bottom = mContentBottom;
   2272                     }
   2273                     if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
   2274                         vf.left = mCurLeft;
   2275                         vf.top = mCurTop;
   2276                         vf.right = mCurRight;
   2277                         vf.bottom = mCurBottom;
   2278                     } else {
   2279                         vf.set(cf);
   2280                     }
   2281                 }
   2282             }
   2283         }
   2284 
   2285         if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0) {
   2286             df.left = df.top = cf.left = cf.top = vf.left = vf.top = -10000;
   2287             df.right = df.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
   2288         }
   2289 
   2290         if (DEBUG_LAYOUT) Log.v(TAG, "Compute frame " + attrs.getTitle()
   2291                 + ": sim=#" + Integer.toHexString(sim)
   2292                 + " attach=" + attached + " type=" + attrs.type
   2293                 + String.format(" flags=0x%08x", fl)
   2294                 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
   2295                 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString());
   2296 
   2297         win.computeFrameLw(pf, df, cf, vf);
   2298 
   2299         // Dock windows carve out the bottom of the screen, so normal windows
   2300         // can't appear underneath them.
   2301         if (attrs.type == TYPE_INPUT_METHOD && !win.getGivenInsetsPendingLw()) {
   2302             int top = win.getContentFrameLw().top;
   2303             top += win.getGivenContentInsetsLw().top;
   2304             if (mContentBottom > top) {
   2305                 mContentBottom = top;
   2306             }
   2307             top = win.getVisibleFrameLw().top;
   2308             top += win.getGivenVisibleInsetsLw().top;
   2309             if (mCurBottom > top) {
   2310                 mCurBottom = top;
   2311             }
   2312             if (DEBUG_LAYOUT) Log.v(TAG, "Input method: mDockBottom="
   2313                     + mDockBottom + " mContentBottom="
   2314                     + mContentBottom + " mCurBottom=" + mCurBottom);
   2315         }
   2316     }
   2317 
   2318     /** {@inheritDoc} */
   2319     public int finishLayoutLw() {
   2320         return 0;
   2321     }
   2322 
   2323     /** {@inheritDoc} */
   2324     public void beginAnimationLw(int displayWidth, int displayHeight) {
   2325         mTopFullscreenOpaqueWindowState = null;
   2326         mForceStatusBar = false;
   2327 
   2328         mHideLockScreen = false;
   2329         mAllowLockscreenWhenOn = false;
   2330         mDismissKeyguard = false;
   2331     }
   2332 
   2333     /** {@inheritDoc} */
   2334     public void animatingWindowLw(WindowState win,
   2335                                 WindowManager.LayoutParams attrs) {
   2336         if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
   2337                 + win.isVisibleOrBehindKeyguardLw());
   2338         if (mTopFullscreenOpaqueWindowState == null &&
   2339                 win.isVisibleOrBehindKeyguardLw()) {
   2340             if ((attrs.flags & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
   2341                 mForceStatusBar = true;
   2342             }
   2343             if (attrs.type >= FIRST_APPLICATION_WINDOW
   2344                     && attrs.type <= LAST_APPLICATION_WINDOW
   2345                     && attrs.x == 0 && attrs.y == 0
   2346                     && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
   2347                     && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
   2348                 if (DEBUG_LAYOUT) Log.v(TAG, "Fullscreen window: " + win);
   2349                 mTopFullscreenOpaqueWindowState = win;
   2350                 if ((attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
   2351                     if (localLOGV) Log.v(TAG, "Setting mHideLockScreen to true by win " + win);
   2352                     mHideLockScreen = true;
   2353                 }
   2354                 if ((attrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
   2355                     if (localLOGV) Log.v(TAG, "Setting mDismissKeyguard to true by win " + win);
   2356                     mDismissKeyguard = true;
   2357                 }
   2358                 if ((attrs.flags & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
   2359                     mAllowLockscreenWhenOn = true;
   2360                 }
   2361             }
   2362         }
   2363     }
   2364 
   2365     /** {@inheritDoc} */
   2366     public int finishAnimationLw() {
   2367         int changes = 0;
   2368         boolean topIsFullscreen = false;
   2369 
   2370         final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
   2371                 ? mTopFullscreenOpaqueWindowState.getAttrs()
   2372                 : null;
   2373 
   2374         if (mStatusBar != null) {
   2375             if (DEBUG_LAYOUT) Log.i(TAG, "force=" + mForceStatusBar
   2376                     + " top=" + mTopFullscreenOpaqueWindowState);
   2377             if (mForceStatusBar) {
   2378                 if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar: forced");
   2379                 if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
   2380             } else if (mTopFullscreenOpaqueWindowState != null) {
   2381                 if (localLOGV) {
   2382                     Log.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
   2383                             + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw());
   2384                     Log.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
   2385                             + " lp.flags=0x" + Integer.toHexString(lp.flags));
   2386                 }
   2387                 topIsFullscreen = (lp.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
   2388                 // The subtle difference between the window for mTopFullscreenOpaqueWindowState
   2389                 // and mTopIsFullscreen is that that mTopIsFullscreen is set only if the window
   2390                 // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
   2391                 // case though.
   2392                 if (topIsFullscreen) {
   2393                     if (mStatusBarCanHide) {
   2394                         if (DEBUG_LAYOUT) Log.v(TAG, "Hiding status bar");
   2395                         if (mStatusBar.hideLw(true)) {
   2396                             changes |= FINISH_LAYOUT_REDO_LAYOUT;
   2397 
   2398                             mHandler.post(new Runnable() { public void run() {
   2399                                 if (mStatusBarService != null) {
   2400                                     try {
   2401                                         mStatusBarService.collapse();
   2402                                     } catch (RemoteException ex) {}
   2403                                 }
   2404                             }});
   2405                         }
   2406                     } else if (DEBUG_LAYOUT) {
   2407                         Log.v(TAG, "Preventing status bar from hiding by policy");
   2408                     }
   2409                 } else {
   2410                     if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar: top is not fullscreen");
   2411                     if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
   2412                 }
   2413             }
   2414         }
   2415 
   2416         mTopIsFullscreen = topIsFullscreen;
   2417 
   2418         // Hide the key guard if a visible window explicitly specifies that it wants to be displayed
   2419         // when the screen is locked
   2420         if (mKeyguard != null) {
   2421             if (localLOGV) Log.v(TAG, "finishAnimationLw::mHideKeyguard="+mHideLockScreen);
   2422             if (mDismissKeyguard && !mKeyguardMediator.isSecure()) {
   2423                 if (mKeyguard.hideLw(true)) {
   2424                     changes |= FINISH_LAYOUT_REDO_LAYOUT
   2425                             | FINISH_LAYOUT_REDO_CONFIG
   2426                             | FINISH_LAYOUT_REDO_WALLPAPER;
   2427                 }
   2428                 if (mKeyguardMediator.isShowing()) {
   2429                     mHandler.post(new Runnable() {
   2430                         public void run() {
   2431                             mKeyguardMediator.keyguardDone(false, false);
   2432                         }
   2433                     });
   2434                 }
   2435             } else if (mHideLockScreen) {
   2436                 if (mKeyguard.hideLw(true)) {
   2437                     changes |= FINISH_LAYOUT_REDO_LAYOUT
   2438                             | FINISH_LAYOUT_REDO_CONFIG
   2439                             | FINISH_LAYOUT_REDO_WALLPAPER;
   2440                 }
   2441                 mKeyguardMediator.setHidden(true);
   2442             } else {
   2443                 if (mKeyguard.showLw(true)) {
   2444                     changes |= FINISH_LAYOUT_REDO_LAYOUT
   2445                             | FINISH_LAYOUT_REDO_CONFIG
   2446                             | FINISH_LAYOUT_REDO_WALLPAPER;
   2447                 }
   2448                 mKeyguardMediator.setHidden(false);
   2449             }
   2450         }
   2451 
   2452         if ((updateSystemUiVisibilityLw()&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0) {
   2453             // If the navigation bar has been hidden or shown, we need to do another
   2454             // layout pass to update that window.
   2455             changes |= FINISH_LAYOUT_REDO_LAYOUT;
   2456         }
   2457 
   2458         // update since mAllowLockscreenWhenOn might have changed
   2459         updateLockScreenTimeout();
   2460         return changes;
   2461     }
   2462 
   2463     public boolean allowAppAnimationsLw() {
   2464         if (mKeyguard != null && mKeyguard.isVisibleLw()) {
   2465             // If keyguard is currently visible, no reason to animate
   2466             // behind it.
   2467             return false;
   2468         }
   2469         if (false) {
   2470             // Don't do this on the tablet, since the system bar never completely
   2471             // covers the screen, and with all its transparency this will
   2472             // incorrectly think it does cover it when it doesn't.  We'll revisit
   2473             // this later when we re-do the phone status bar.
   2474             if (mStatusBar != null && mStatusBar.isVisibleLw()) {
   2475                 RectF rect = new RectF(mStatusBar.getShownFrameLw());
   2476                 for (int i=mStatusBarPanels.size()-1; i>=0; i--) {
   2477                     WindowState w = mStatusBarPanels.get(i);
   2478                     if (w.isVisibleLw()) {
   2479                         rect.union(w.getShownFrameLw());
   2480                     }
   2481                 }
   2482                 final int insetw = mRestrictedScreenWidth/10;
   2483                 final int inseth = mRestrictedScreenHeight/10;
   2484                 if (rect.contains(insetw, inseth, mRestrictedScreenWidth-insetw,
   2485                             mRestrictedScreenHeight-inseth)) {
   2486                     // All of the status bar windows put together cover the
   2487                     // screen, so the app can't be seen.  (Note this test doesn't
   2488                     // work if the rects of these windows are at off offsets or
   2489                     // sizes, causing gaps in the rect union we have computed.)
   2490                     return false;
   2491                 }
   2492             }
   2493         }
   2494         return true;
   2495     }
   2496 
   2497     public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
   2498         mFocusedWindow = newFocus;
   2499         if ((updateSystemUiVisibilityLw()&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0) {
   2500             // If the navigation bar has been hidden or shown, we need to do another
   2501             // layout pass to update that window.
   2502             return FINISH_LAYOUT_REDO_LAYOUT;
   2503         }
   2504         return 0;
   2505     }
   2506 
   2507     /** {@inheritDoc} */
   2508     public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
   2509         // lid changed state
   2510         mLidOpen = lidOpen ? LID_OPEN : LID_CLOSED;
   2511         updateKeyboardVisibility();
   2512 
   2513         boolean awakeNow = mKeyguardMediator.doLidChangeTq(lidOpen);
   2514         updateRotation(true);
   2515         if (awakeNow) {
   2516             // If the lid is opening and we don't have to keep the
   2517             // keyguard up, then we can turn on the screen
   2518             // immediately.
   2519             mKeyguardMediator.pokeWakelock();
   2520         } else if (keyguardIsShowingTq()) {
   2521             if (lidOpen) {
   2522                 // If we are opening the lid and not hiding the
   2523                 // keyguard, then we need to have it turn on the
   2524                 // screen once it is shown.
   2525                 mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(
   2526                         KeyEvent.KEYCODE_POWER, mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED);
   2527             }
   2528         } else {
   2529             // Light up the keyboard if we are sliding up.
   2530             if (lidOpen) {
   2531                 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
   2532                         LocalPowerManager.BUTTON_EVENT);
   2533             } else {
   2534                 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
   2535                         LocalPowerManager.OTHER_EVENT);
   2536             }
   2537         }
   2538     }
   2539 
   2540     void setHdmiPlugged(boolean plugged) {
   2541         if (mHdmiPlugged != plugged) {
   2542             mHdmiPlugged = plugged;
   2543             updateRotation(true);
   2544             Intent intent = new Intent(ACTION_HDMI_PLUGGED);
   2545             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
   2546             intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
   2547             mContext.sendStickyBroadcast(intent);
   2548         }
   2549     }
   2550 
   2551     void initializeHdmiState() {
   2552         boolean plugged = false;
   2553         // watch for HDMI plug messages if the hdmi switch exists
   2554         if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
   2555             mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
   2556 
   2557             final String filename = "/sys/class/switch/hdmi/state";
   2558             FileReader reader = null;
   2559             try {
   2560                 reader = new FileReader(filename);
   2561                 char[] buf = new char[15];
   2562                 int n = reader.read(buf);
   2563                 if (n > 1) {
   2564                     plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
   2565                 }
   2566             } catch (IOException ex) {
   2567                 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
   2568             } catch (NumberFormatException ex) {
   2569                 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
   2570             } finally {
   2571                 if (reader != null) {
   2572                     try {
   2573                         reader.close();
   2574                     } catch (IOException ex) {
   2575                     }
   2576                 }
   2577             }
   2578         }
   2579         // This dance forces the code in setHdmiPlugged to run.
   2580         // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
   2581         mHdmiPlugged = !plugged;
   2582         setHdmiPlugged(!mHdmiPlugged);
   2583     }
   2584 
   2585     /**
   2586      * @return Whether music is being played right now.
   2587      */
   2588     boolean isMusicActive() {
   2589         final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
   2590         if (am == null) {
   2591             Log.w(TAG, "isMusicActive: couldn't get AudioManager reference");
   2592             return false;
   2593         }
   2594         return am.isMusicActive();
   2595     }
   2596 
   2597     /**
   2598      * Tell the audio service to adjust the volume appropriate to the event.
   2599      * @param keycode
   2600      */
   2601     void handleVolumeKey(int stream, int keycode) {
   2602         IAudioService audioService = getAudioService();
   2603         if (audioService == null) {
   2604             return;
   2605         }
   2606         try {
   2607             // since audio is playing, we shouldn't have to hold a wake lock
   2608             // during the call, but we do it as a precaution for the rare possibility
   2609             // that the music stops right before we call this
   2610             // TODO: Actually handle MUTE.
   2611             mBroadcastWakeLock.acquire();
   2612             audioService.adjustStreamVolume(stream,
   2613                 keycode == KeyEvent.KEYCODE_VOLUME_UP
   2614                             ? AudioManager.ADJUST_RAISE
   2615                             : AudioManager.ADJUST_LOWER,
   2616                     0);
   2617         } catch (RemoteException e) {
   2618             Log.w(TAG, "IAudioService.adjustStreamVolume() threw RemoteException " + e);
   2619         } finally {
   2620             mBroadcastWakeLock.release();
   2621         }
   2622     }
   2623 
   2624     final Object mScreenshotLock = new Object();
   2625     ServiceConnection mScreenshotConnection = null;
   2626 
   2627     final Runnable mScreenshotTimeout = new Runnable() {
   2628         @Override public void run() {
   2629             synchronized (mScreenshotLock) {
   2630                 if (mScreenshotConnection != null) {
   2631                     mContext.unbindService(mScreenshotConnection);
   2632                     mScreenshotConnection = null;
   2633                 }
   2634             }
   2635         }
   2636     };
   2637 
   2638     // Assume this is called from the Handler thread.
   2639     private void takeScreenshot() {
   2640         synchronized (mScreenshotLock) {
   2641             if (mScreenshotConnection != null) {
   2642                 return;
   2643             }
   2644             ComponentName cn = new ComponentName("com.android.systemui",
   2645                     "com.android.systemui.screenshot.TakeScreenshotService");
   2646             Intent intent = new Intent();
   2647             intent.setComponent(cn);
   2648             ServiceConnection conn = new ServiceConnection() {
   2649                 @Override
   2650                 public void onServiceConnected(ComponentName name, IBinder service) {
   2651                     synchronized (mScreenshotLock) {
   2652                         if (mScreenshotConnection != this) {
   2653                             return;
   2654                         }
   2655                         Messenger messenger = new Messenger(service);
   2656                         Message msg = Message.obtain(null, 1);
   2657                         final ServiceConnection myConn = this;
   2658                         Handler h = new Handler(mHandler.getLooper()) {
   2659                             @Override
   2660                             public void handleMessage(Message msg) {
   2661                                 synchronized (mScreenshotLock) {
   2662                                     if (mScreenshotConnection == myConn) {
   2663                                         mContext.unbindService(mScreenshotConnection);
   2664                                         mScreenshotConnection = null;
   2665                                         mHandler.removeCallbacks(mScreenshotTimeout);
   2666                                     }
   2667                                 }
   2668                             }
   2669                         };
   2670                         msg.replyTo = new Messenger(h);
   2671                         msg.arg1 = msg.arg2 = 0;
   2672                         if (mStatusBar != null && mStatusBar.isVisibleLw())
   2673                             msg.arg1 = 1;
   2674                         if (mNavigationBar != null && mNavigationBar.isVisibleLw())
   2675                             msg.arg2 = 1;
   2676                         try {
   2677                             messenger.send(msg);
   2678                         } catch (RemoteException e) {
   2679                         }
   2680                     }
   2681                 }
   2682                 @Override
   2683                 public void onServiceDisconnected(ComponentName name) {}
   2684             };
   2685             if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
   2686                 mScreenshotConnection = conn;
   2687                 mHandler.postDelayed(mScreenshotTimeout, 10000);
   2688             }
   2689         }
   2690     }
   2691 
   2692     /** {@inheritDoc} */
   2693     @Override
   2694     public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
   2695         final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
   2696         final boolean canceled = event.isCanceled();
   2697         final int keyCode = event.getKeyCode();
   2698 
   2699         final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
   2700 
   2701         // If screen is off then we treat the case where the keyguard is open but hidden
   2702         // the same as if it were open and in front.
   2703         // This will prevent any keys other than the power button from waking the screen
   2704         // when the keyguard is hidden by another activity.
   2705         final boolean keyguardActive = (isScreenOn ?
   2706                                         mKeyguardMediator.isShowingAndNotHidden() :
   2707                                         mKeyguardMediator.isShowing());
   2708 
   2709         if (!mSystemBooted) {
   2710             // If we have not yet booted, don't let key events do anything.
   2711             return 0;
   2712         }
   2713 
   2714         if (false) {
   2715             Log.d(TAG, "interceptKeyTq keycode=" + keyCode
   2716                   + " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive);
   2717         }
   2718 
   2719         if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
   2720                 && event.getRepeatCount() == 0) {
   2721             performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
   2722         }
   2723 
   2724         // Basic policy based on screen state and keyguard.
   2725         // FIXME: This policy isn't quite correct.  We shouldn't care whether the screen
   2726         //        is on or off, really.  We should care about whether the device is in an
   2727         //        interactive state or is in suspend pretending to be "off".
   2728         //        The primary screen might be turned off due to proximity sensor or
   2729         //        because we are presenting media on an auxiliary screen or remotely controlling
   2730         //        the device some other way (which is why we have an exemption here for injected
   2731         //        events).
   2732         int result;
   2733         if (isScreenOn || isInjected) {
   2734             // When the screen is on or if the key is injected pass the key to the application.
   2735             result = ACTION_PASS_TO_USER;
   2736         } else {
   2737             // When the screen is off and the key is not injected, determine whether
   2738             // to wake the device but don't pass the key to the application.
   2739             result = 0;
   2740 
   2741             final boolean isWakeKey = (policyFlags
   2742                     & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
   2743             if (down && isWakeKey) {
   2744                 if (keyguardActive) {
   2745                     // If the keyguard is showing, let it decide what to do with the wake key.
   2746                     mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode,
   2747                             mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED);
   2748                 } else {
   2749                     // Otherwise, wake the device ourselves.
   2750                     result |= ACTION_POKE_USER_ACTIVITY;
   2751                 }
   2752             }
   2753         }
   2754 
   2755         // Handle special keys.
   2756         switch (keyCode) {
   2757             case KeyEvent.KEYCODE_VOLUME_DOWN:
   2758             case KeyEvent.KEYCODE_VOLUME_UP:
   2759             case KeyEvent.KEYCODE_VOLUME_MUTE: {
   2760                 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
   2761                     if (down) {
   2762                         if (isScreenOn && !mVolumeDownKeyTriggered
   2763                                 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
   2764                             mVolumeDownKeyTriggered = true;
   2765                             mVolumeDownKeyTime = event.getDownTime();
   2766                             mVolumeDownKeyConsumedByScreenshotChord = false;
   2767                             cancelPendingPowerKeyAction();
   2768                             interceptScreenshotChord();
   2769                         }
   2770                     } else {
   2771                         mVolumeDownKeyTriggered = false;
   2772                         cancelPendingScreenshotChordAction();
   2773                     }
   2774                 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
   2775                     if (down) {
   2776                         if (isScreenOn && !mVolumeUpKeyTriggered
   2777                                 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
   2778                             mVolumeUpKeyTriggered = true;
   2779                             cancelPendingPowerKeyAction();
   2780                             cancelPendingScreenshotChordAction();
   2781                         }
   2782                     } else {
   2783                         mVolumeUpKeyTriggered = false;
   2784                         cancelPendingScreenshotChordAction();
   2785                     }
   2786                 }
   2787                 if (down) {
   2788                     ITelephony telephonyService = getTelephonyService();
   2789                     if (telephonyService != null) {
   2790                         try {
   2791                             if (telephonyService.isRinging()) {
   2792                                 // If an incoming call is ringing, either VOLUME key means
   2793                                 // "silence ringer".  We handle these keys here, rather than
   2794                                 // in the InCallScreen, to make sure we'll respond to them
   2795                                 // even if the InCallScreen hasn't come to the foreground yet.
   2796                                 // Look for the DOWN event here, to agree with the "fallback"
   2797                                 // behavior in the InCallScreen.
   2798                                 Log.i(TAG, "interceptKeyBeforeQueueing:"
   2799                                       + " VOLUME key-down while ringing: Silence ringer!");
   2800 
   2801                                 // Silence the ringer.  (It's safe to call this
   2802                                 // even if the ringer has already been silenced.)
   2803                                 telephonyService.silenceRinger();
   2804 
   2805                                 // And *don't* pass this key thru to the current activity
   2806                                 // (which is probably the InCallScreen.)
   2807                                 result &= ~ACTION_PASS_TO_USER;
   2808                                 break;
   2809                             }
   2810                             if (telephonyService.isOffhook()
   2811                                     && (result & ACTION_PASS_TO_USER) == 0) {
   2812                                 // If we are in call but we decided not to pass the key to
   2813                                 // the application, handle the volume change here.
   2814                                 handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode);
   2815                                 break;
   2816                             }
   2817                         } catch (RemoteException ex) {
   2818                             Log.w(TAG, "ITelephony threw RemoteException", ex);
   2819                         }
   2820                     }
   2821 
   2822                     if (isMusicActive() && (result & ACTION_PASS_TO_USER) == 0) {
   2823                         // If music is playing but we decided not to pass the key to the
   2824                         // application, handle the volume change here.
   2825                         handleVolumeKey(AudioManager.STREAM_MUSIC, keyCode);
   2826                         break;
   2827                     }
   2828                 }
   2829                 break;
   2830             }
   2831 
   2832             case KeyEvent.KEYCODE_ENDCALL: {
   2833                 result &= ~ACTION_PASS_TO_USER;
   2834                 if (down) {
   2835                     ITelephony telephonyService = getTelephonyService();
   2836                     boolean hungUp = false;
   2837                     if (telephonyService != null) {
   2838                         try {
   2839                             hungUp = telephonyService.endCall();
   2840                         } catch (RemoteException ex) {
   2841                             Log.w(TAG, "ITelephony threw RemoteException", ex);
   2842                         }
   2843                     }
   2844                     interceptPowerKeyDown(!isScreenOn || hungUp);
   2845                 } else {
   2846                     if (interceptPowerKeyUp(canceled)) {
   2847                         if ((mEndcallBehavior
   2848                                 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
   2849                             if (goHome()) {
   2850                                 break;
   2851                             }
   2852                         }
   2853                         if ((mEndcallBehavior
   2854                                 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
   2855                             result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
   2856                         }
   2857                     }
   2858                 }
   2859                 break;
   2860             }
   2861 
   2862             case KeyEvent.KEYCODE_POWER: {
   2863                 result &= ~ACTION_PASS_TO_USER;
   2864                 if (down) {
   2865                     if (isScreenOn && !mPowerKeyTriggered
   2866                             && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
   2867                         mPowerKeyTriggered = true;
   2868                         mPowerKeyTime = event.getDownTime();
   2869                         interceptScreenshotChord();
   2870                     }
   2871 
   2872                     ITelephony telephonyService = getTelephonyService();
   2873                     boolean hungUp = false;
   2874                     if (telephonyService != null) {
   2875                         try {
   2876                             if (telephonyService.isRinging()) {
   2877                                 // Pressing Power while there's a ringing incoming
   2878                                 // call should silence the ringer.
   2879                                 telephonyService.silenceRinger();
   2880                             } else if ((mIncallPowerBehavior
   2881                                     & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
   2882                                     && telephonyService.isOffhook()) {
   2883                                 // Otherwise, if "Power button ends call" is enabled,
   2884                                 // the Power button will hang up any current active call.
   2885                                 hungUp = telephonyService.endCall();
   2886                             }
   2887                         } catch (RemoteException ex) {
   2888                             Log.w(TAG, "ITelephony threw RemoteException", ex);
   2889                         }
   2890                     }
   2891                     interceptPowerKeyDown(!isScreenOn || hungUp
   2892                             || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
   2893                 } else {
   2894                     mPowerKeyTriggered = false;
   2895                     cancelPendingScreenshotChordAction();
   2896                     if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
   2897                         result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
   2898                     }
   2899                     mPendingPowerKeyUpCanceled = false;
   2900                 }
   2901                 break;
   2902             }
   2903 
   2904             case KeyEvent.KEYCODE_MEDIA_PLAY:
   2905             case KeyEvent.KEYCODE_MEDIA_PAUSE:
   2906             case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
   2907                 if (down) {
   2908                     ITelephony telephonyService = getTelephonyService();
   2909                     if (telephonyService != null) {
   2910                         try {
   2911                             if (!telephonyService.isIdle()) {
   2912                                 // Suppress PLAY/PAUSE toggle when phone is ringing or in-call
   2913                                 // to avoid music playback.
   2914                                 break;
   2915                             }
   2916                         } catch (RemoteException ex) {
   2917                             Log.w(TAG, "ITelephony threw RemoteException", ex);
   2918                         }
   2919                     }
   2920                 }
   2921             case KeyEvent.KEYCODE_HEADSETHOOK:
   2922             case KeyEvent.KEYCODE_MUTE:
   2923             case KeyEvent.KEYCODE_MEDIA_STOP:
   2924             case KeyEvent.KEYCODE_MEDIA_NEXT:
   2925             case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
   2926             case KeyEvent.KEYCODE_MEDIA_REWIND:
   2927             case KeyEvent.KEYCODE_MEDIA_RECORD:
   2928             case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
   2929                 if ((result & ACTION_PASS_TO_USER) == 0) {
   2930                     // Only do this if we would otherwise not pass it to the user. In that
   2931                     // case, the PhoneWindow class will do the same thing, except it will
   2932                     // only do it if the showing app doesn't process the key on its own.
   2933                     mBroadcastWakeLock.acquire();
   2934                     mHandler.post(new PassHeadsetKey(new KeyEvent(event)));
   2935                 }
   2936                 break;
   2937             }
   2938 
   2939             case KeyEvent.KEYCODE_CALL: {
   2940                 if (down) {
   2941                     ITelephony telephonyService = getTelephonyService();
   2942                     if (telephonyService != null) {
   2943                         try {
   2944                             if (telephonyService.isRinging()) {
   2945                                 Log.i(TAG, "interceptKeyBeforeQueueing:"
   2946                                       + " CALL key-down while ringing: Answer the call!");
   2947                                 telephonyService.answerRingingCall();
   2948 
   2949                                 // And *don't* pass this key thru to the current activity
   2950                                 // (which is presumably the InCallScreen.)
   2951                                 result &= ~ACTION_PASS_TO_USER;
   2952                             }
   2953                         } catch (RemoteException ex) {
   2954                             Log.w(TAG, "ITelephony threw RemoteException", ex);
   2955                         }
   2956                     }
   2957                 }
   2958                 break;
   2959             }
   2960         }
   2961         return result;
   2962     }
   2963 
   2964     /** {@inheritDoc} */
   2965     @Override
   2966     public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
   2967         int result = 0;
   2968 
   2969         final boolean isWakeMotion = (policyFlags
   2970                 & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
   2971         if (isWakeMotion) {
   2972             if (mKeyguardMediator.isShowing()) {
   2973                 // If the keyguard is showing, let it decide what to do with the wake motion.
   2974                 mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq();
   2975             } else {
   2976                 // Otherwise, wake the device ourselves.
   2977                 result |= ACTION_POKE_USER_ACTIVITY;
   2978             }
   2979         }
   2980         return result;
   2981     }
   2982 
   2983     class PassHeadsetKey implements Runnable {
   2984         KeyEvent mKeyEvent;
   2985 
   2986         PassHeadsetKey(KeyEvent keyEvent) {
   2987             mKeyEvent = keyEvent;
   2988         }
   2989 
   2990         public void run() {
   2991             if (ActivityManagerNative.isSystemReady()) {
   2992                 Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
   2993                 intent.putExtra(Intent.EXTRA_KEY_EVENT, mKeyEvent);
   2994                 mContext.sendOrderedBroadcast(intent, null, mBroadcastDone,
   2995                         mHandler, Activity.RESULT_OK, null, null);
   2996             }
   2997         }
   2998     }
   2999 
   3000     BroadcastReceiver mBroadcastDone = new BroadcastReceiver() {
   3001         public void onReceive(Context context, Intent intent) {
   3002             mBroadcastWakeLock.release();
   3003         }
   3004     };
   3005 
   3006     BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
   3007         public void onReceive(Context context, Intent intent) {
   3008             if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
   3009                 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
   3010                         Intent.EXTRA_DOCK_STATE_UNDOCKED);
   3011             } else {
   3012                 try {
   3013                     IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
   3014                             ServiceManager.getService(Context.UI_MODE_SERVICE));
   3015                     mUiMode = uiModeService.getCurrentModeType();
   3016                 } catch (RemoteException e) {
   3017                 }
   3018             }
   3019             updateRotation(true);
   3020             updateOrientationListenerLp();
   3021         }
   3022     };
   3023 
   3024     /** {@inheritDoc} */
   3025     public void screenTurnedOff(int why) {
   3026         EventLog.writeEvent(70000, 0);
   3027         synchronized (mLock) {
   3028             mScreenOnEarly = false;
   3029             mScreenOnFully = false;
   3030         }
   3031         mKeyguardMediator.onScreenTurnedOff(why);
   3032         synchronized (mLock) {
   3033             updateOrientationListenerLp();
   3034             updateLockScreenTimeout();
   3035         }
   3036     }
   3037 
   3038     /** {@inheritDoc} */
   3039     public void screenTurningOn(final ScreenOnListener screenOnListener) {
   3040         EventLog.writeEvent(70000, 1);
   3041         if (false) {
   3042             RuntimeException here = new RuntimeException("here");
   3043             here.fillInStackTrace();
   3044             Slog.i(TAG, "Screen turning on...", here);
   3045         }
   3046         if (screenOnListener != null) {
   3047             mKeyguardMediator.onScreenTurnedOn(new KeyguardViewManager.ShowListener() {
   3048                 @Override public void onShown(IBinder windowToken) {
   3049                     if (windowToken != null) {
   3050                         try {
   3051                             mWindowManager.waitForWindowDrawn(windowToken,
   3052                                     new IRemoteCallback.Stub() {
   3053                                 @Override public void sendResult(Bundle data) {
   3054                                     Slog.i(TAG, "Lock screen displayed!");
   3055                                     screenOnListener.onScreenOn();
   3056                                     synchronized (mLock) {
   3057                                         mScreenOnFully = true;
   3058                                     }
   3059                                 }
   3060                             });
   3061                         } catch (RemoteException e) {
   3062                         }
   3063                     } else {
   3064                         Slog.i(TAG, "No lock screen!");
   3065                         screenOnListener.onScreenOn();
   3066                         synchronized (mLock) {
   3067                             mScreenOnFully = true;
   3068                         }
   3069                     }
   3070                 }
   3071             });
   3072         } else {
   3073             synchronized (mLock) {
   3074                 mScreenOnFully = true;
   3075             }
   3076         }
   3077         synchronized (mLock) {
   3078             mScreenOnEarly = true;
   3079             updateOrientationListenerLp();
   3080             updateLockScreenTimeout();
   3081         }
   3082     }
   3083 
   3084     /** {@inheritDoc} */
   3085     public boolean isScreenOnEarly() {
   3086         return mScreenOnEarly;
   3087     }
   3088 
   3089     /** {@inheritDoc} */
   3090     public boolean isScreenOnFully() {
   3091         return mScreenOnFully;
   3092     }
   3093 
   3094     /** {@inheritDoc} */
   3095     public void enableKeyguard(boolean enabled) {
   3096         mKeyguardMediator.setKeyguardEnabled(enabled);
   3097     }
   3098 
   3099     /** {@inheritDoc} */
   3100     public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
   3101         mKeyguardMediator.verifyUnlock(callback);
   3102     }
   3103 
   3104     private boolean keyguardIsShowingTq() {
   3105         return mKeyguardMediator.isShowingAndNotHidden();
   3106     }
   3107 
   3108 
   3109     /** {@inheritDoc} */
   3110     public boolean isKeyguardLocked() {
   3111         return keyguardOn();
   3112     }
   3113 
   3114     /** {@inheritDoc} */
   3115     public boolean isKeyguardSecure() {
   3116         return mKeyguardMediator.isSecure();
   3117     }
   3118 
   3119     /** {@inheritDoc} */
   3120     public boolean inKeyguardRestrictedKeyInputMode() {
   3121         return mKeyguardMediator.isInputRestricted();
   3122     }
   3123 
   3124     public void dismissKeyguardLw() {
   3125         if (!mKeyguardMediator.isSecure()) {
   3126             if (mKeyguardMediator.isShowing()) {
   3127                 mHandler.post(new Runnable() {
   3128                     public void run() {
   3129                         mKeyguardMediator.keyguardDone(false, true);
   3130                     }
   3131                 });
   3132             }
   3133         }
   3134     }
   3135 
   3136     void sendCloseSystemWindows() {
   3137         sendCloseSystemWindows(mContext, null);
   3138     }
   3139 
   3140     void sendCloseSystemWindows(String reason) {
   3141         sendCloseSystemWindows(mContext, reason);
   3142     }
   3143 
   3144     static void sendCloseSystemWindows(Context context, String reason) {
   3145         if (ActivityManagerNative.isSystemReady()) {
   3146             try {
   3147                 ActivityManagerNative.getDefault().closeSystemDialogs(reason);
   3148             } catch (RemoteException e) {
   3149             }
   3150         }
   3151     }
   3152 
   3153     @Override
   3154     public int rotationForOrientationLw(int orientation, int lastRotation) {
   3155         if (false) {
   3156             Slog.v(TAG, "rotationForOrientationLw(orient="
   3157                         + orientation + ", last=" + lastRotation
   3158                         + "); user=" + mUserRotation + " "
   3159                         + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
   3160                             ? "USER_ROTATION_LOCKED" : "")
   3161                         );
   3162         }
   3163 
   3164         synchronized (mLock) {
   3165             int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
   3166             if (sensorRotation < 0) {
   3167                 sensorRotation = lastRotation;
   3168             }
   3169 
   3170             final int preferredRotation;
   3171             if (mLidOpen == LID_OPEN && mLidOpenRotation >= 0) {
   3172                 // Ignore sensor when lid switch is open and rotation is forced.
   3173                 preferredRotation = mLidOpenRotation;
   3174             } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
   3175                     && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
   3176                 // Ignore sensor when in car dock unless explicitly enabled.
   3177                 // This case can override the behavior of NOSENSOR, and can also
   3178                 // enable 180 degree rotation while docked.
   3179                 preferredRotation = mCarDockEnablesAccelerometer
   3180                         ? sensorRotation : mCarDockRotation;
   3181             } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
   3182                     || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
   3183                     || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
   3184                     && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
   3185                 // Ignore sensor when in desk dock unless explicitly enabled.
   3186                 // This case can override the behavior of NOSENSOR, and can also
   3187                 // enable 180 degree rotation while docked.
   3188                 preferredRotation = mDeskDockEnablesAccelerometer
   3189                         ? sensorRotation : mDeskDockRotation;
   3190             } else if (mHdmiPlugged) {
   3191                 // Ignore sensor when plugged into HDMI.
   3192                 // Note that the dock orientation overrides the HDMI orientation.
   3193                 preferredRotation = mHdmiRotation;
   3194             } else if ((mAccelerometerDefault != 0 /* implies not rotation locked */
   3195                             && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
   3196                                     || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED))
   3197                     || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
   3198                     || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
   3199                     || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
   3200                     || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
   3201                 // Otherwise, use sensor only if requested by the application or enabled
   3202                 // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
   3203                 if (mAllowAllRotations < 0) {
   3204                     // Can't read this during init() because the context doesn't
   3205                     // have display metrics at that time so we cannot determine
   3206                     // tablet vs. phone then.
   3207                     mAllowAllRotations = mContext.getResources().getBoolean(
   3208                             com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
   3209                 }
   3210                 if (sensorRotation != Surface.ROTATION_180
   3211                         || mAllowAllRotations == 1
   3212                         || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR) {
   3213                     preferredRotation = sensorRotation;
   3214                 } else {
   3215                     preferredRotation = lastRotation;
   3216                 }
   3217             } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
   3218                 // Apply rotation lock.
   3219                 preferredRotation = mUserRotation;
   3220             } else {
   3221                 // No overriding preference.
   3222                 // We will do exactly what the application asked us to do.
   3223                 preferredRotation = -1;
   3224             }
   3225 
   3226             switch (orientation) {
   3227                 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
   3228                     // Return portrait unless overridden.
   3229                     if (isAnyPortrait(preferredRotation)) {
   3230                         return preferredRotation;
   3231                     }
   3232                     return mPortraitRotation;
   3233 
   3234                 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
   3235                     // Return landscape unless overridden.
   3236                     if (isLandscapeOrSeascape(preferredRotation)) {
   3237                         return preferredRotation;
   3238                     }
   3239                     return mLandscapeRotation;
   3240 
   3241                 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
   3242                     // Return reverse portrait unless overridden.
   3243                     if (isAnyPortrait(preferredRotation)) {
   3244                         return preferredRotation;
   3245                     }
   3246                     return mUpsideDownRotation;
   3247 
   3248                 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
   3249                     // Return seascape unless overridden.
   3250                     if (isLandscapeOrSeascape(preferredRotation)) {
   3251                         return preferredRotation;
   3252                     }
   3253                     return mSeascapeRotation;
   3254 
   3255                 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
   3256                     // Return either landscape rotation.
   3257                     if (isLandscapeOrSeascape(preferredRotation)) {
   3258                         return preferredRotation;
   3259                     }
   3260                     if (isLandscapeOrSeascape(lastRotation)) {
   3261                         return lastRotation;
   3262                     }
   3263                     return mLandscapeRotation;
   3264 
   3265                 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
   3266                     // Return either portrait rotation.
   3267                     if (isAnyPortrait(preferredRotation)) {
   3268                         return preferredRotation;
   3269                     }
   3270                     if (isAnyPortrait(lastRotation)) {
   3271                         return lastRotation;
   3272                     }
   3273                     return mPortraitRotation;
   3274 
   3275                 default:
   3276                     // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
   3277                     // just return the preferred orientation we already calculated.
   3278                     if (preferredRotation >= 0) {
   3279                         return preferredRotation;
   3280                     }
   3281                     return Surface.ROTATION_0;
   3282             }
   3283         }
   3284     }
   3285 
   3286     @Override
   3287     public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
   3288         switch (orientation) {
   3289             case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
   3290             case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
   3291             case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
   3292                 return isAnyPortrait(rotation);
   3293 
   3294             case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
   3295             case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
   3296             case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
   3297                 return isLandscapeOrSeascape(rotation);
   3298 
   3299             default:
   3300                 return true;
   3301         }
   3302     }
   3303 
   3304     @Override
   3305     public void setRotationLw(int rotation) {
   3306         mOrientationListener.setCurrentRotation(rotation);
   3307     }
   3308 
   3309     private boolean isLandscapeOrSeascape(int rotation) {
   3310         return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
   3311     }
   3312 
   3313     private boolean isAnyPortrait(int rotation) {
   3314         return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
   3315     }
   3316 
   3317 
   3318     // User rotation: to be used when all else fails in assigning an orientation to the device
   3319     public void setUserRotationMode(int mode, int rot) {
   3320         ContentResolver res = mContext.getContentResolver();
   3321 
   3322         // mUserRotationMode and mUserRotation will be assigned by the content observer
   3323         if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
   3324             Settings.System.putInt(res,
   3325                     Settings.System.USER_ROTATION,
   3326                     rot);
   3327             Settings.System.putInt(res,
   3328                     Settings.System.ACCELEROMETER_ROTATION,
   3329                     0);
   3330         } else {
   3331             Settings.System.putInt(res,
   3332                     Settings.System.ACCELEROMETER_ROTATION,
   3333                     1);
   3334         }
   3335     }
   3336 
   3337     public boolean detectSafeMode() {
   3338         try {
   3339             int menuState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_MENU);
   3340             int sState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_S);
   3341             int dpadState = mWindowManager.getDPadKeycodeState(KeyEvent.KEYCODE_DPAD_CENTER);
   3342             int trackballState = mWindowManager.getTrackballScancodeState(BTN_MOUSE);
   3343             int volumeDownState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_VOLUME_DOWN);
   3344             mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
   3345                     || volumeDownState > 0;
   3346             performHapticFeedbackLw(null, mSafeMode
   3347                     ? HapticFeedbackConstants.SAFE_MODE_ENABLED
   3348                     : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
   3349             if (mSafeMode) {
   3350                 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
   3351                         + " dpad=" + dpadState + " trackball=" + trackballState + ")");
   3352             } else {
   3353                 Log.i(TAG, "SAFE MODE not enabled");
   3354             }
   3355             return mSafeMode;
   3356         } catch (RemoteException e) {
   3357             // Doom! (it's also local)
   3358             throw new RuntimeException("window manager dead");
   3359         }
   3360     }
   3361 
   3362     static long[] getLongIntArray(Resources r, int resid) {
   3363         int[] ar = r.getIntArray(resid);
   3364         if (ar == null) {
   3365             return null;
   3366         }
   3367         long[] out = new long[ar.length];
   3368         for (int i=0; i<ar.length; i++) {
   3369             out[i] = ar[i];
   3370         }
   3371         return out;
   3372     }
   3373 
   3374     /** {@inheritDoc} */
   3375     public void systemReady() {
   3376         // tell the keyguard
   3377         mKeyguardMediator.onSystemReady();
   3378         android.os.SystemProperties.set("dev.bootcomplete", "1");
   3379         synchronized (mLock) {
   3380             updateOrientationListenerLp();
   3381             mSystemReady = true;
   3382             mHandler.post(new Runnable() {
   3383                 public void run() {
   3384                     updateSettings();
   3385                 }
   3386             });
   3387         }
   3388     }
   3389 
   3390     /** {@inheritDoc} */
   3391     public void systemBooted() {
   3392         synchronized (mLock) {
   3393             mSystemBooted = true;
   3394         }
   3395     }
   3396 
   3397     ProgressDialog mBootMsgDialog = null;
   3398 
   3399     /** {@inheritDoc} */
   3400     public void showBootMessage(final CharSequence msg, final boolean always) {
   3401         mHandler.post(new Runnable() {
   3402             @Override public void run() {
   3403                 if (mBootMsgDialog == null) {
   3404                     mBootMsgDialog = new ProgressDialog(mContext) {
   3405                         // This dialog will consume all events coming in to
   3406                         // it, to avoid it trying to do things too early in boot.
   3407                         @Override public boolean dispatchKeyEvent(KeyEvent event) {
   3408                             return true;
   3409                         }
   3410                         @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
   3411                             return true;
   3412                         }
   3413                         @Override public boolean dispatchTouchEvent(MotionEvent ev) {
   3414                             return true;
   3415                         }
   3416                         @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
   3417                             return true;
   3418                         }
   3419                         @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
   3420                             return true;
   3421                         }
   3422                         @Override public boolean dispatchPopulateAccessibilityEvent(
   3423                                 AccessibilityEvent event) {
   3424                             return true;
   3425                         }
   3426                     };
   3427                     mBootMsgDialog.setTitle(R.string.android_upgrading_title);
   3428                     mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
   3429                     mBootMsgDialog.setIndeterminate(true);
   3430                     mBootMsgDialog.getWindow().setType(
   3431                             WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
   3432                     mBootMsgDialog.getWindow().addFlags(
   3433                             WindowManager.LayoutParams.FLAG_DIM_BEHIND
   3434                             | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
   3435                     mBootMsgDialog.getWindow().setDimAmount(1);
   3436                     WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
   3437                     lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
   3438                     mBootMsgDialog.getWindow().setAttributes(lp);
   3439                     mBootMsgDialog.setCancelable(false);
   3440                     mBootMsgDialog.show();
   3441                 }
   3442                 mBootMsgDialog.setMessage(msg);
   3443             }
   3444         });
   3445     }
   3446 
   3447     /** {@inheritDoc} */
   3448     public void hideBootMessages() {
   3449         mHandler.post(new Runnable() {
   3450             @Override public void run() {
   3451                 if (mBootMsgDialog != null) {
   3452                     mBootMsgDialog.dismiss();
   3453                     mBootMsgDialog = null;
   3454                 }
   3455             }
   3456         });
   3457     }
   3458 
   3459     /** {@inheritDoc} */
   3460     public void userActivity() {
   3461         // ***************************************
   3462         // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
   3463         // ***************************************
   3464         // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
   3465         // WITH ITS LOCKS HELD.
   3466         //
   3467         // This code must be VERY careful about the locks
   3468         // it acquires.
   3469         // In fact, the current code acquires way too many,
   3470         // and probably has lurking deadlocks.
   3471 
   3472         synchronized (mScreenLockTimeout) {
   3473             if (mLockScreenTimerActive) {
   3474                 // reset the timer
   3475                 mHandler.removeCallbacks(mScreenLockTimeout);
   3476                 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
   3477             }
   3478         }
   3479     }
   3480 
   3481     Runnable mScreenLockTimeout = new Runnable() {
   3482         public void run() {
   3483             synchronized (this) {
   3484                 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
   3485                 mKeyguardMediator.doKeyguardTimeout();
   3486                 mLockScreenTimerActive = false;
   3487             }
   3488         }
   3489     };
   3490 
   3491     private void updateLockScreenTimeout() {
   3492         synchronized (mScreenLockTimeout) {
   3493             boolean enable = (mAllowLockscreenWhenOn && mScreenOnEarly && mKeyguardMediator.isSecure());
   3494             if (mLockScreenTimerActive != enable) {
   3495                 if (enable) {
   3496                     if (localLOGV) Log.v(TAG, "setting lockscreen timer");
   3497                     mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
   3498                 } else {
   3499                     if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
   3500                     mHandler.removeCallbacks(mScreenLockTimeout);
   3501                 }
   3502                 mLockScreenTimerActive = enable;
   3503             }
   3504         }
   3505     }
   3506 
   3507     /** {@inheritDoc} */
   3508     public void enableScreenAfterBoot() {
   3509         readLidState();
   3510         updateKeyboardVisibility();
   3511 
   3512         updateRotation(true);
   3513     }
   3514 
   3515     private void updateKeyboardVisibility() {
   3516         mPowerManager.setKeyboardVisibility(mLidOpen == LID_OPEN);
   3517     }
   3518 
   3519     void updateRotation(boolean alwaysSendConfiguration) {
   3520         try {
   3521             //set orientation on WindowManager
   3522             mWindowManager.updateRotation(alwaysSendConfiguration);
   3523         } catch (RemoteException e) {
   3524             // Ignore
   3525         }
   3526     }
   3527 
   3528     /**
   3529      * Return an Intent to launch the currently active dock app as home.  Returns
   3530      * null if the standard home should be launched, which is the case if any of the following is
   3531      * true:
   3532      * <ul>
   3533      *  <li>The device is not in either car mode or desk mode
   3534      *  <li>The device is in car mode but ENABLE_CAR_DOCK_HOME_CAPTURE is false
   3535      *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
   3536      *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
   3537      *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
   3538      * </ul>
   3539      * @return
   3540      */
   3541     Intent createHomeDockIntent() {
   3542         Intent intent = null;
   3543 
   3544         // What home does is based on the mode, not the dock state.  That
   3545         // is, when in car mode you should be taken to car home regardless
   3546         // of whether we are actually in a car dock.
   3547         if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
   3548             if (ENABLE_CAR_DOCK_HOME_CAPTURE) {
   3549                 intent = mCarDockIntent;
   3550             }
   3551         } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
   3552             if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
   3553                 intent = mDeskDockIntent;
   3554             }
   3555         }
   3556 
   3557         if (intent == null) {
   3558             return null;
   3559         }
   3560 
   3561         ActivityInfo ai = intent.resolveActivityInfo(
   3562                 mContext.getPackageManager(), PackageManager.GET_META_DATA);
   3563         if (ai == null) {
   3564             return null;
   3565         }
   3566 
   3567         if (ai.metaData != null && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
   3568             intent = new Intent(intent);
   3569             intent.setClassName(ai.packageName, ai.name);
   3570             return intent;
   3571         }
   3572 
   3573         return null;
   3574     }
   3575 
   3576     void startDockOrHome() {
   3577         Intent dock = createHomeDockIntent();
   3578         if (dock != null) {
   3579             try {
   3580                 mContext.startActivity(dock);
   3581                 return;
   3582             } catch (ActivityNotFoundException e) {
   3583             }
   3584         }
   3585         mContext.startActivity(mHomeIntent);
   3586     }
   3587 
   3588     /**
   3589      * goes to the home screen
   3590      * @return whether it did anything
   3591      */
   3592     boolean goHome() {
   3593         if (false) {
   3594             // This code always brings home to the front.
   3595             try {
   3596                 ActivityManagerNative.getDefault().stopAppSwitches();
   3597             } catch (RemoteException e) {
   3598             }
   3599             sendCloseSystemWindows();
   3600             startDockOrHome();
   3601         } else {
   3602             // This code brings home to the front or, if it is already
   3603             // at the front, puts the device to sleep.
   3604             try {
   3605                 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
   3606                     /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
   3607                     Log.d(TAG, "UTS-TEST-MODE");
   3608                 } else {
   3609                     ActivityManagerNative.getDefault().stopAppSwitches();
   3610                     sendCloseSystemWindows();
   3611                     Intent dock = createHomeDockIntent();
   3612                     if (dock != null) {
   3613                         int result = ActivityManagerNative.getDefault()
   3614                                 .startActivity(null, dock,
   3615                                         dock.resolveTypeIfNeeded(mContext.getContentResolver()),
   3616                                         null, 0, null, null, 0, true /* onlyIfNeeded*/, false,
   3617                                         null, null, false);
   3618                         if (result == IActivityManager.START_RETURN_INTENT_TO_CALLER) {
   3619                             return false;
   3620                         }
   3621                     }
   3622                 }
   3623                 int result = ActivityManagerNative.getDefault()
   3624                         .startActivity(null, mHomeIntent,
   3625                                 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
   3626                                 null, 0, null, null, 0, true /* onlyIfNeeded*/, false,
   3627                                 null, null, false);
   3628                 if (result == IActivityManager.START_RETURN_INTENT_TO_CALLER) {
   3629                     return false;
   3630                 }
   3631             } catch (RemoteException ex) {
   3632                 // bummer, the activity manager, which is in this process, is dead
   3633             }
   3634         }
   3635         return true;
   3636     }
   3637 
   3638     public void setCurrentOrientationLw(int newOrientation) {
   3639         synchronized (mLock) {
   3640             if (newOrientation != mCurrentAppOrientation) {
   3641                 mCurrentAppOrientation = newOrientation;
   3642                 updateOrientationListenerLp();
   3643             }
   3644         }
   3645     }
   3646 
   3647     public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
   3648         final boolean hapticsDisabled = Settings.System.getInt(mContext.getContentResolver(),
   3649                 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0;
   3650         if (!always && (hapticsDisabled || mKeyguardMediator.isShowingAndNotHidden())) {
   3651             return false;
   3652         }
   3653         long[] pattern = null;
   3654         switch (effectId) {
   3655             case HapticFeedbackConstants.LONG_PRESS:
   3656                 pattern = mLongPressVibePattern;
   3657                 break;
   3658             case HapticFeedbackConstants.VIRTUAL_KEY:
   3659                 pattern = mVirtualKeyVibePattern;
   3660                 break;
   3661             case HapticFeedbackConstants.KEYBOARD_TAP:
   3662                 pattern = mKeyboardTapVibePattern;
   3663                 break;
   3664             case HapticFeedbackConstants.SAFE_MODE_DISABLED:
   3665                 pattern = mSafeModeDisabledVibePattern;
   3666                 break;
   3667             case HapticFeedbackConstants.SAFE_MODE_ENABLED:
   3668                 pattern = mSafeModeEnabledVibePattern;
   3669                 break;
   3670             default:
   3671                 return false;
   3672         }
   3673         if (pattern.length == 1) {
   3674             // One-shot vibration
   3675             mVibrator.vibrate(pattern[0]);
   3676         } else {
   3677             // Pattern vibration
   3678             mVibrator.vibrate(pattern, -1);
   3679         }
   3680         return true;
   3681     }
   3682 
   3683     public void screenOnStartedLw() {
   3684     }
   3685 
   3686     public void screenOnStoppedLw() {
   3687         if (mPowerManager.isScreenOn()) {
   3688             if (!mKeyguardMediator.isShowingAndNotHidden()) {
   3689                 long curTime = SystemClock.uptimeMillis();
   3690                 mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT);
   3691             }
   3692         }
   3693     }
   3694 
   3695     public boolean allowKeyRepeat() {
   3696         // disable key repeat when screen is off
   3697         return mScreenOnEarly;
   3698     }
   3699 
   3700     private int updateSystemUiVisibilityLw() {
   3701         // If there is no window focused, there will be nobody to handle the events
   3702         // anyway, so just hang on in whatever state we're in until things settle down.
   3703         if (mFocusedWindow == null) {
   3704             return 0;
   3705         }
   3706         final int visibility = mFocusedWindow.getSystemUiVisibility()
   3707                 & ~mResettingSystemUiFlags
   3708                 & ~mForceClearedSystemUiFlags;
   3709         int diff = visibility ^ mLastSystemUiFlags;
   3710         final boolean needsMenu = mFocusedWindow.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
   3711         if (diff == 0 && mLastFocusNeedsMenu == needsMenu
   3712                 && mFocusedApp == mFocusedWindow.getAppToken()) {
   3713             return 0;
   3714         }
   3715         mLastSystemUiFlags = visibility;
   3716         mLastFocusNeedsMenu = needsMenu;
   3717         mFocusedApp = mFocusedWindow.getAppToken();
   3718         mHandler.post(new Runnable() {
   3719                 public void run() {
   3720                     if (mStatusBarService == null) {
   3721                         mStatusBarService = IStatusBarService.Stub.asInterface(
   3722                                 ServiceManager.getService("statusbar"));
   3723                     }
   3724                     if (mStatusBarService != null) {
   3725                         try {
   3726                             mStatusBarService.setSystemUiVisibility(visibility);
   3727                             mStatusBarService.topAppWindowChanged(needsMenu);
   3728                         } catch (RemoteException e) {
   3729                             // not much to be done
   3730                             mStatusBarService = null;
   3731                         }
   3732                     }
   3733                 }
   3734             });
   3735         return diff;
   3736     }
   3737 
   3738     // Use this instead of checking config_showNavigationBar so that it can be consistently
   3739     // overridden by qemu.hw.mainkeys in the emulator.
   3740     public boolean hasNavigationBar() {
   3741         return mHasNavigationBar;
   3742     }
   3743 
   3744     public void dump(String prefix, FileDescriptor fd, PrintWriter pw, String[] args) {
   3745         pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
   3746                 pw.print(" mSystemReady="); pw.print(mSystemReady);
   3747                 pw.print(" mSystemBooted="); pw.println(mSystemBooted);
   3748         pw.print(prefix); pw.print("mLidOpen="); pw.print(mLidOpen);
   3749                 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
   3750                 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
   3751         if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
   3752                 || mForceClearedSystemUiFlags != 0) {
   3753             pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
   3754                     pw.print(Integer.toHexString(mLastSystemUiFlags));
   3755                     pw.print(" mResettingSystemUiFlags=0x");
   3756                     pw.print(Integer.toHexString(mResettingSystemUiFlags));
   3757                     pw.print(" mForceClearedSystemUiFlags=0x");
   3758                     pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
   3759         }
   3760         if (mLastFocusNeedsMenu) {
   3761             pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
   3762                     pw.println(mLastFocusNeedsMenu);
   3763         }
   3764         pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
   3765                 pw.print(" mDockMode="); pw.print(mDockMode);
   3766                 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
   3767                 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
   3768         pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
   3769                 pw.print(" mUserRotation="); pw.print(mUserRotation);
   3770                 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
   3771         pw.print(prefix); pw.print("mAccelerometerDefault="); pw.print(mAccelerometerDefault);
   3772                 pw.print(" mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
   3773         pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
   3774                 pw.print(mCarDockEnablesAccelerometer);
   3775                 pw.print(" mDeskDockEnablesAccelerometer=");
   3776                 pw.println(mDeskDockEnablesAccelerometer);
   3777         pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
   3778                 pw.print(mLidKeyboardAccessibility);
   3779                 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
   3780                 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
   3781         pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
   3782                 pw.print(" mScreenOnFully="); pw.print(mScreenOnFully);
   3783                 pw.print(" mOrientationSensorEnabled="); pw.print(mOrientationSensorEnabled);
   3784                 pw.print(" mHasSoftInput="); pw.println(mHasSoftInput);
   3785         pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
   3786                 pw.print(","); pw.print(mUnrestrictedScreenTop);
   3787                 pw.print(") "); pw.print(mUnrestrictedScreenWidth);
   3788                 pw.print("x"); pw.println(mUnrestrictedScreenHeight);
   3789         pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
   3790                 pw.print(","); pw.print(mRestrictedScreenTop);
   3791                 pw.print(") "); pw.print(mRestrictedScreenWidth);
   3792                 pw.print("x"); pw.println(mRestrictedScreenHeight);
   3793         pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
   3794                 pw.print(","); pw.print(mCurTop);
   3795                 pw.print(")-("); pw.print(mCurRight);
   3796                 pw.print(","); pw.print(mCurBottom); pw.println(")");
   3797         pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
   3798                 pw.print(","); pw.print(mContentTop);
   3799                 pw.print(")-("); pw.print(mContentRight);
   3800                 pw.print(","); pw.print(mContentBottom); pw.println(")");
   3801         pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
   3802                 pw.print(","); pw.print(mDockTop);
   3803                 pw.print(")-("); pw.print(mDockRight);
   3804                 pw.print(","); pw.print(mDockBottom); pw.println(")");
   3805         pw.print(prefix); pw.print("mDockLayer="); pw.println(mDockLayer);
   3806         pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
   3807                 pw.println(mTopFullscreenOpaqueWindowState);
   3808         pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
   3809                 pw.print(" mForceStatusBar="); pw.print(mForceStatusBar);
   3810                 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
   3811         pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
   3812                 pw.print(" mHomePressed="); pw.println(mHomePressed);
   3813         pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
   3814                 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
   3815                 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
   3816         pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
   3817                 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
   3818                 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
   3819         pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
   3820                 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
   3821         pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
   3822                 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
   3823     }
   3824 }
   3825