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