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