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