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