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