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