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