PhoneWindowManager.java revision 8e8b415bbdd2f30b1fcfdf799e70f076d4de81b0
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    static final int STATUS_BAR_LAYER = 8;
170    static final int STATUS_BAR_PANEL_LAYER = 9;
171    // SIM errors and unlock.  Not sure if this really should be in a high layer.
172    static final int PRIORITY_PHONE_LAYER = 10;
173    // like the ANR / app crashed dialogs
174    static final int SYSTEM_ALERT_LAYER = 11;
175    // system-level error dialogs
176    static final int SYSTEM_ERROR_LAYER = 12;
177    // on-screen keyboards and other such input method user interfaces go here.
178    static final int INPUT_METHOD_LAYER = 13;
179    // on-screen keyboards and other such input method user interfaces go here.
180    static final int INPUT_METHOD_DIALOG_LAYER = 14;
181    // the keyguard; nothing on top of these can take focus, since they are
182    // responsible for power management when displayed.
183    static final int KEYGUARD_LAYER = 15;
184    static final int KEYGUARD_DIALOG_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 the power key down was already triggered, take the screenshot
2448                    if (mPowerDownTriggered) {
2449                        // Dismiss the power-key longpress
2450                        mHandler.removeCallbacks(mPowerLongPress);
2451                        mPowerKeyHandled = true;
2452
2453                        // Take the screenshot
2454                        takeScreenshot();
2455
2456                        // Prevent the event from being passed through to the current activity
2457                        result &= ~ACTION_PASS_TO_USER;
2458                        break;
2459                    }
2460                    mVolumeDownTriggered = true;
2461                } else {
2462                    mVolumeDownTriggered = false;
2463                }
2464            case KeyEvent.KEYCODE_VOLUME_UP:
2465            case KeyEvent.KEYCODE_VOLUME_MUTE: {
2466                if (down) {
2467                    ITelephony telephonyService = getTelephonyService();
2468                    if (telephonyService != null) {
2469                        try {
2470                            if (telephonyService.isRinging()) {
2471                                // If an incoming call is ringing, either VOLUME key means
2472                                // "silence ringer".  We handle these keys here, rather than
2473                                // in the InCallScreen, to make sure we'll respond to them
2474                                // even if the InCallScreen hasn't come to the foreground yet.
2475                                // Look for the DOWN event here, to agree with the "fallback"
2476                                // behavior in the InCallScreen.
2477                                Log.i(TAG, "interceptKeyBeforeQueueing:"
2478                                      + " VOLUME key-down while ringing: Silence ringer!");
2479
2480                                // Silence the ringer.  (It's safe to call this
2481                                // even if the ringer has already been silenced.)
2482                                telephonyService.silenceRinger();
2483
2484                                // And *don't* pass this key thru to the current activity
2485                                // (which is probably the InCallScreen.)
2486                                result &= ~ACTION_PASS_TO_USER;
2487                                break;
2488                            }
2489                            if (telephonyService.isOffhook()
2490                                    && (result & ACTION_PASS_TO_USER) == 0) {
2491                                // If we are in call but we decided not to pass the key to
2492                                // the application, handle the volume change here.
2493                                handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode);
2494                                break;
2495                            }
2496                        } catch (RemoteException ex) {
2497                            Log.w(TAG, "ITelephony threw RemoteException", ex);
2498                        }
2499                    }
2500
2501                    if (isMusicActive() && (result & ACTION_PASS_TO_USER) == 0) {
2502                        // If music is playing but we decided not to pass the key to the
2503                        // application, handle the volume change here.
2504                        handleVolumeKey(AudioManager.STREAM_MUSIC, keyCode);
2505                        break;
2506                    }
2507                }
2508                break;
2509            }
2510
2511            case KeyEvent.KEYCODE_ENDCALL: {
2512                result &= ~ACTION_PASS_TO_USER;
2513                if (down) {
2514                    ITelephony telephonyService = getTelephonyService();
2515                    boolean hungUp = false;
2516                    if (telephonyService != null) {
2517                        try {
2518                            hungUp = telephonyService.endCall();
2519                        } catch (RemoteException ex) {
2520                            Log.w(TAG, "ITelephony threw RemoteException", ex);
2521                        }
2522                    }
2523                    interceptPowerKeyDown(!isScreenOn || hungUp);
2524                } else {
2525                    if (interceptPowerKeyUp(canceled)) {
2526                        if ((mEndcallBehavior
2527                                & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
2528                            if (goHome()) {
2529                                break;
2530                            }
2531                        }
2532                        if ((mEndcallBehavior
2533                                & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
2534                            result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
2535                        }
2536                    }
2537                }
2538                break;
2539            }
2540
2541            case KeyEvent.KEYCODE_POWER: {
2542                result &= ~ACTION_PASS_TO_USER;
2543                if (down) {
2544                    // If the volume down key has been triggered, then just take the screenshot
2545                    if (mVolumeDownTriggered) {
2546                        // Take the screenshot
2547                        takeScreenshot();
2548                        mPowerKeyHandled = true;
2549
2550                        // Prevent the event from being passed through to the current activity
2551                        break;
2552                    }
2553                    mPowerDownTriggered = true;
2554
2555
2556                    ITelephony telephonyService = getTelephonyService();
2557                    boolean hungUp = false;
2558                    if (telephonyService != null) {
2559                        try {
2560                            if (telephonyService.isRinging()) {
2561                                // Pressing Power while there's a ringing incoming
2562                                // call should silence the ringer.
2563                                telephonyService.silenceRinger();
2564                            } else if ((mIncallPowerBehavior
2565                                    & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
2566                                    && telephonyService.isOffhook()) {
2567                                // Otherwise, if "Power button ends call" is enabled,
2568                                // the Power button will hang up any current active call.
2569                                hungUp = telephonyService.endCall();
2570                            }
2571                        } catch (RemoteException ex) {
2572                            Log.w(TAG, "ITelephony threw RemoteException", ex);
2573                        }
2574                    }
2575                    interceptPowerKeyDown(!isScreenOn || hungUp);
2576                } else {
2577                    mPowerDownTriggered = false;
2578                    if (interceptPowerKeyUp(canceled)) {
2579                        result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
2580                    }
2581                }
2582                break;
2583            }
2584
2585            case KeyEvent.KEYCODE_MEDIA_PLAY:
2586            case KeyEvent.KEYCODE_MEDIA_PAUSE:
2587            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
2588                if (down) {
2589                    ITelephony telephonyService = getTelephonyService();
2590                    if (telephonyService != null) {
2591                        try {
2592                            if (!telephonyService.isIdle()) {
2593                                // Suppress PLAY/PAUSE toggle when phone is ringing or in-call
2594                                // to avoid music playback.
2595                                break;
2596                            }
2597                        } catch (RemoteException ex) {
2598                            Log.w(TAG, "ITelephony threw RemoteException", ex);
2599                        }
2600                    }
2601                }
2602            case KeyEvent.KEYCODE_HEADSETHOOK:
2603            case KeyEvent.KEYCODE_MUTE:
2604            case KeyEvent.KEYCODE_MEDIA_STOP:
2605            case KeyEvent.KEYCODE_MEDIA_NEXT:
2606            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
2607            case KeyEvent.KEYCODE_MEDIA_REWIND:
2608            case KeyEvent.KEYCODE_MEDIA_RECORD:
2609            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
2610                if ((result & ACTION_PASS_TO_USER) == 0) {
2611                    // Only do this if we would otherwise not pass it to the user. In that
2612                    // case, the PhoneWindow class will do the same thing, except it will
2613                    // only do it if the showing app doesn't process the key on its own.
2614                    mBroadcastWakeLock.acquire();
2615                    mHandler.post(new PassHeadsetKey(new KeyEvent(event)));
2616                }
2617                break;
2618            }
2619
2620            case KeyEvent.KEYCODE_CALL: {
2621                if (down) {
2622                    ITelephony telephonyService = getTelephonyService();
2623                    if (telephonyService != null) {
2624                        try {
2625                            if (telephonyService.isRinging()) {
2626                                Log.i(TAG, "interceptKeyBeforeQueueing:"
2627                                      + " CALL key-down while ringing: Answer the call!");
2628                                telephonyService.answerRingingCall();
2629
2630                                // And *don't* pass this key thru to the current activity
2631                                // (which is presumably the InCallScreen.)
2632                                result &= ~ACTION_PASS_TO_USER;
2633                            }
2634                        } catch (RemoteException ex) {
2635                            Log.w(TAG, "ITelephony threw RemoteException", ex);
2636                        }
2637                    }
2638                }
2639                break;
2640            }
2641        }
2642        return result;
2643    }
2644
2645    /** {@inheritDoc} */
2646    @Override
2647    public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
2648        int result = 0;
2649
2650        final boolean isWakeMotion = (policyFlags
2651                & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
2652        if (isWakeMotion) {
2653            if (mKeyguardMediator.isShowing()) {
2654                // If the keyguard is showing, let it decide what to do with the wake motion.
2655                mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq();
2656            } else {
2657                // Otherwise, wake the device ourselves.
2658                result |= ACTION_POKE_USER_ACTIVITY;
2659            }
2660        }
2661        return result;
2662    }
2663
2664    class PassHeadsetKey implements Runnable {
2665        KeyEvent mKeyEvent;
2666
2667        PassHeadsetKey(KeyEvent keyEvent) {
2668            mKeyEvent = keyEvent;
2669        }
2670
2671        public void run() {
2672            if (ActivityManagerNative.isSystemReady()) {
2673                Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
2674                intent.putExtra(Intent.EXTRA_KEY_EVENT, mKeyEvent);
2675                mContext.sendOrderedBroadcast(intent, null, mBroadcastDone,
2676                        mHandler, Activity.RESULT_OK, null, null);
2677            }
2678        }
2679    }
2680
2681    BroadcastReceiver mBroadcastDone = new BroadcastReceiver() {
2682        public void onReceive(Context context, Intent intent) {
2683            mBroadcastWakeLock.release();
2684        }
2685    };
2686
2687    BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
2688        public void onReceive(Context context, Intent intent) {
2689            if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
2690                mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
2691                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
2692            } else {
2693                try {
2694                    IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
2695                            ServiceManager.getService(Context.UI_MODE_SERVICE));
2696                    mUiMode = uiModeService.getCurrentModeType();
2697                } catch (RemoteException e) {
2698                }
2699            }
2700            updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
2701            updateOrientationListenerLp();
2702        }
2703    };
2704
2705    /** {@inheritDoc} */
2706    public void screenTurnedOff(int why) {
2707        EventLog.writeEvent(70000, 0);
2708        mKeyguardMediator.onScreenTurnedOff(why);
2709        synchronized (mLock) {
2710            mScreenOn = false;
2711            updateOrientationListenerLp();
2712            updateLockScreenTimeout();
2713            updateScreenSaverTimeoutLocked();
2714        }
2715    }
2716
2717    /** {@inheritDoc} */
2718    public void screenTurnedOn() {
2719        EventLog.writeEvent(70000, 1);
2720        mKeyguardMediator.onScreenTurnedOn();
2721        synchronized (mLock) {
2722            mScreenOn = true;
2723            updateOrientationListenerLp();
2724            updateLockScreenTimeout();
2725            updateScreenSaverTimeoutLocked();
2726        }
2727    }
2728
2729    /** {@inheritDoc} */
2730    public boolean isScreenOn() {
2731        return mScreenOn;
2732    }
2733
2734    /** {@inheritDoc} */
2735    public void enableKeyguard(boolean enabled) {
2736        mKeyguardMediator.setKeyguardEnabled(enabled);
2737    }
2738
2739    /** {@inheritDoc} */
2740    public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
2741        mKeyguardMediator.verifyUnlock(callback);
2742    }
2743
2744    private boolean keyguardIsShowingTq() {
2745        return mKeyguardMediator.isShowingAndNotHidden();
2746    }
2747
2748
2749    /** {@inheritDoc} */
2750    public boolean isKeyguardLocked() {
2751        return keyguardOn();
2752    }
2753
2754    /** {@inheritDoc} */
2755    public boolean isKeyguardSecure() {
2756        return mKeyguardMediator.isSecure();
2757    }
2758
2759    /** {@inheritDoc} */
2760    public boolean inKeyguardRestrictedKeyInputMode() {
2761        return mKeyguardMediator.isInputRestricted();
2762    }
2763
2764    void sendCloseSystemWindows() {
2765        sendCloseSystemWindows(mContext, null);
2766    }
2767
2768    void sendCloseSystemWindows(String reason) {
2769        sendCloseSystemWindows(mContext, reason);
2770    }
2771
2772    static void sendCloseSystemWindows(Context context, String reason) {
2773        if (ActivityManagerNative.isSystemReady()) {
2774            try {
2775                ActivityManagerNative.getDefault().closeSystemDialogs(reason);
2776            } catch (RemoteException e) {
2777            }
2778        }
2779    }
2780
2781    public int rotationForOrientationLw(int orientation, int lastRotation,
2782            boolean displayEnabled) {
2783
2784        if (false) {
2785            Slog.v(TAG, "rotationForOrientationLw(orient="
2786                        + orientation + ", last=" + lastRotation
2787                        + "); user=" + mUserRotation + " "
2788                        + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
2789                            ? "USER_ROTATION_LOCKED" : "")
2790                        );
2791        }
2792
2793        synchronized (mLock) {
2794            switch (orientation) {
2795                case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
2796                    //always return portrait if orientation set to portrait
2797                    return mPortraitRotation;
2798                case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
2799                    //always return landscape if orientation set to landscape
2800                    return mLandscapeRotation;
2801                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
2802                    //always return portrait if orientation set to portrait
2803                    return mUpsideDownRotation;
2804                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
2805                    //always return seascape if orientation set to reverse landscape
2806                    return mSeascapeRotation;
2807                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
2808                    //return either landscape rotation based on the sensor
2809                    return getCurrentLandscapeRotation(lastRotation);
2810                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
2811                    return getCurrentPortraitRotation(lastRotation);
2812            }
2813
2814            // case for nosensor meaning ignore sensor and consider only lid
2815            // or orientation sensor disabled
2816            //or case.unspecified
2817            if (mHdmiPlugged) {
2818                return Surface.ROTATION_0;
2819            } else if (mLidOpen == LID_OPEN) {
2820                return mLidOpenRotation;
2821            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) {
2822                return mCarDockRotation;
2823            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) {
2824                return mDeskDockRotation;
2825            } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
2826                return mUserRotation;
2827            } else {
2828                if (useSensorForOrientationLp(orientation)) {
2829                    // Disable 180 degree rotation unless allowed by default for the device
2830                    // or explicitly requested by the application.
2831                    int rotation = mOrientationListener.getCurrentRotation(lastRotation);
2832                    if (rotation == Surface.ROTATION_180
2833                            && !mAllowAllRotations
2834                            && orientation != ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR) {
2835                        return lastRotation;
2836                    }
2837                    return rotation;
2838                }
2839                return Surface.ROTATION_0;
2840            }
2841        }
2842    }
2843
2844    public int getLockedRotationLw() {
2845        synchronized (mLock) {
2846            if (false) {
2847                // Not yet working.
2848                if (mHdmiPlugged) {
2849                    return Surface.ROTATION_0;
2850                } else if (mLidOpen == LID_OPEN) {
2851                    return mLidOpenRotation;
2852                } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) {
2853                    return mCarDockRotation;
2854                } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) {
2855                    return mDeskDockRotation;
2856                } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
2857                    return mUserRotation;
2858                }
2859            }
2860            return -1;
2861        }
2862    }
2863
2864    private int getCurrentLandscapeRotation(int lastRotation) {
2865        // if the user has locked rotation, we ignore the sensor
2866        if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
2867            if (isLandscapeOrSeascape(mUserRotation)) {
2868                return mUserRotation;
2869            } else {
2870                // it seems odd to obey the sensor at all if rotation lock is enabled
2871                return mLandscapeRotation;
2872            }
2873        }
2874
2875        int sensorRotation = mOrientationListener.getCurrentRotation(lastRotation);
2876        if (isLandscapeOrSeascape(sensorRotation)) {
2877            return sensorRotation;
2878        }
2879        // try to preserve the old rotation if it was landscape
2880        if (isLandscapeOrSeascape(lastRotation)) {
2881            return lastRotation;
2882        }
2883        // default to one of the primary landscape rotation
2884        return mLandscapeRotation;
2885    }
2886
2887    private boolean isLandscapeOrSeascape(int sensorRotation) {
2888        return sensorRotation == mLandscapeRotation || sensorRotation == mSeascapeRotation;
2889    }
2890
2891    private int getCurrentPortraitRotation(int lastRotation) {
2892        // if the user has locked rotation, we ignore the sensor
2893        if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
2894            if (isAnyPortrait(mUserRotation)) {
2895                return mUserRotation;
2896            } else {
2897                // it seems odd to obey the sensor at all if rotation lock is enabled
2898                return mPortraitRotation;
2899            }
2900        }
2901
2902        int sensorRotation = mOrientationListener.getCurrentRotation(lastRotation);
2903        if (isAnyPortrait(sensorRotation)) {
2904            return sensorRotation;
2905        }
2906        // try to preserve the old rotation if it was portrait
2907        if (isAnyPortrait(lastRotation)) {
2908            return lastRotation;
2909        }
2910        // default to one of the primary portrait rotations
2911        return mPortraitRotation;
2912    }
2913
2914    private boolean isAnyPortrait(int sensorRotation) {
2915        return sensorRotation == mPortraitRotation || sensorRotation == mUpsideDownRotation;
2916    }
2917
2918
2919    // User rotation: to be used when all else fails in assigning an orientation to the device
2920    public void setUserRotationMode(int mode, int rot) {
2921        ContentResolver res = mContext.getContentResolver();
2922
2923        // mUserRotationMode and mUserRotation will be assigned by the content observer
2924        if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
2925            Settings.System.putInt(res,
2926                    Settings.System.USER_ROTATION,
2927                    rot);
2928            Settings.System.putInt(res,
2929                    Settings.System.ACCELEROMETER_ROTATION,
2930                    0);
2931        } else {
2932            Settings.System.putInt(res,
2933                    Settings.System.ACCELEROMETER_ROTATION,
2934                    1);
2935        }
2936    }
2937
2938    public boolean detectSafeMode() {
2939        try {
2940            int menuState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_MENU);
2941            int sState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_S);
2942            int dpadState = mWindowManager.getDPadKeycodeState(KeyEvent.KEYCODE_DPAD_CENTER);
2943            int trackballState = mWindowManager.getTrackballScancodeState(BTN_MOUSE);
2944            int volumeDownState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_VOLUME_DOWN);
2945            mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
2946                    || volumeDownState > 0;
2947            performHapticFeedbackLw(null, mSafeMode
2948                    ? HapticFeedbackConstants.SAFE_MODE_ENABLED
2949                    : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
2950            if (mSafeMode) {
2951                Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
2952                        + " dpad=" + dpadState + " trackball=" + trackballState + ")");
2953            } else {
2954                Log.i(TAG, "SAFE MODE not enabled");
2955            }
2956            return mSafeMode;
2957        } catch (RemoteException e) {
2958            // Doom! (it's also local)
2959            throw new RuntimeException("window manager dead");
2960        }
2961    }
2962
2963    static long[] getLongIntArray(Resources r, int resid) {
2964        int[] ar = r.getIntArray(resid);
2965        if (ar == null) {
2966            return null;
2967        }
2968        long[] out = new long[ar.length];
2969        for (int i=0; i<ar.length; i++) {
2970            out[i] = ar[i];
2971        }
2972        return out;
2973    }
2974
2975    /** {@inheritDoc} */
2976    public void systemReady() {
2977        // tell the keyguard
2978        mKeyguardMediator.onSystemReady();
2979        android.os.SystemProperties.set("dev.bootcomplete", "1");
2980        synchronized (mLock) {
2981            updateOrientationListenerLp();
2982            mSystemReady = true;
2983            mHandler.post(new Runnable() {
2984                public void run() {
2985                    updateSettings();
2986                }
2987            });
2988        }
2989    }
2990
2991    /** {@inheritDoc} */
2992    public void userActivity() {
2993        synchronized (mScreenLockTimeout) {
2994            if (mLockScreenTimerActive) {
2995                // reset the timer
2996                mHandler.removeCallbacks(mScreenLockTimeout);
2997                mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
2998            }
2999        }
3000
3001        if (mStatusBarService != null) {
3002            try {
3003                mStatusBarService.userActivity();
3004            } catch (RemoteException ex) {}
3005        }
3006
3007        synchronized (mLock) {
3008            updateScreenSaverTimeoutLocked();
3009        }
3010    }
3011
3012    Runnable mScreenSaverActivator = new Runnable() {
3013        public void run() {
3014            synchronized (this) {
3015                if (!(mScreenSaverEnabled && mScreenOn)) {
3016                    Log.w(TAG, "mScreenSaverActivator ran, but the screensaver should not be showing. Who's driving this thing?");
3017                    return;
3018                }
3019
3020                if (localLOGV) Log.v(TAG, "mScreenSaverActivator entering dreamland");
3021                try {
3022                    String component = Settings.System.getString(
3023                            mContext.getContentResolver(), Settings.Secure.DREAM_COMPONENT);
3024                    if (component != null) {
3025                        ComponentName cn = ComponentName.unflattenFromString(component);
3026                        Intent intent = new Intent(Intent.ACTION_MAIN)
3027                            .setComponent(cn)
3028                            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
3029                                | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
3030                                | Intent.FLAG_ACTIVITY_NO_USER_ACTION
3031                                | Intent.FLAG_ACTIVITY_SINGLE_TOP);
3032                        mContext.startActivity(intent);
3033                    } else {
3034                        Log.e(TAG, "Couldn't start screen saver: none selected");
3035                    }
3036                } catch (android.content.ActivityNotFoundException exc) {
3037                    // no screensaver? give up
3038                    Log.e(TAG, "Couldn't start screen saver: none installed");
3039                }
3040            }
3041        }
3042    };
3043
3044    // Must call while holding mLock
3045    private void updateScreenSaverTimeoutLocked() {
3046        synchronized (mScreenSaverActivator) {
3047            mHandler.removeCallbacks(mScreenSaverActivator);
3048            if (mScreenSaverEnabled && mScreenOn && mScreenSaverTimeout > 0) {
3049                if (localLOGV)
3050                    Log.v(TAG, "scheduling screensaver for " + mScreenSaverTimeout + "ms from now");
3051                mHandler.postDelayed(mScreenSaverActivator, mScreenSaverTimeout);
3052            } else {
3053                if (localLOGV) {
3054                    if (mScreenSaverTimeout == 0)
3055                        Log.v(TAG, "screen saver disabled by user");
3056                    else if (!mScreenOn)
3057                        Log.v(TAG, "screen saver disabled while screen off");
3058                    else
3059                        Log.v(TAG, "screen saver disabled by wakelock");
3060                }
3061            }
3062        }
3063    }
3064
3065    Runnable mScreenLockTimeout = new Runnable() {
3066        public void run() {
3067            synchronized (this) {
3068                if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
3069                mKeyguardMediator.doKeyguardTimeout();
3070                mLockScreenTimerActive = false;
3071            }
3072        }
3073    };
3074
3075    private void updateLockScreenTimeout() {
3076        synchronized (mScreenLockTimeout) {
3077            boolean enable = (mAllowLockscreenWhenOn && mScreenOn && mKeyguardMediator.isSecure());
3078            if (mLockScreenTimerActive != enable) {
3079                if (enable) {
3080                    if (localLOGV) Log.v(TAG, "setting lockscreen timer");
3081                    mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
3082                } else {
3083                    if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
3084                    mHandler.removeCallbacks(mScreenLockTimeout);
3085                }
3086                mLockScreenTimerActive = enable;
3087            }
3088        }
3089    }
3090
3091    /** {@inheritDoc} */
3092    public void enableScreenAfterBoot() {
3093        readLidState();
3094        updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
3095    }
3096
3097    void updateRotation(int animFlags) {
3098        mPowerManager.setKeyboardVisibility(mLidOpen == LID_OPEN);
3099        int rotation = Surface.ROTATION_0;
3100        if (mHdmiPlugged) {
3101            rotation = Surface.ROTATION_0;
3102        } else if (mLidOpen == LID_OPEN) {
3103            rotation = mLidOpenRotation;
3104        } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) {
3105            rotation = mCarDockRotation;
3106        } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) {
3107            rotation = mDeskDockRotation;
3108        }
3109        //if lid is closed orientation will be portrait
3110        try {
3111            //set orientation on WindowManager
3112            mWindowManager.setRotation(rotation, true,
3113                    mFancyRotationAnimation | animFlags);
3114        } catch (RemoteException e) {
3115            // Ignore
3116        }
3117    }
3118
3119    /**
3120     * Return an Intent to launch the currently active dock as home.  Returns
3121     * null if the standard home should be launched.
3122     * @return
3123     */
3124    Intent createHomeDockIntent() {
3125        Intent intent;
3126
3127        // What home does is based on the mode, not the dock state.  That
3128        // is, when in car mode you should be taken to car home regardless
3129        // of whether we are actually in a car dock.
3130        if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
3131            intent = mCarDockIntent;
3132        } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
3133            intent = mDeskDockIntent;
3134        } else {
3135            return null;
3136        }
3137
3138        ActivityInfo ai = intent.resolveActivityInfo(
3139                mContext.getPackageManager(), PackageManager.GET_META_DATA);
3140        if (ai == null) {
3141            return null;
3142        }
3143
3144        if (ai.metaData != null && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
3145            intent = new Intent(intent);
3146            intent.setClassName(ai.packageName, ai.name);
3147            return intent;
3148        }
3149
3150        return null;
3151    }
3152
3153    void startDockOrHome() {
3154        Intent dock = createHomeDockIntent();
3155        if (dock != null) {
3156            try {
3157                mContext.startActivity(dock);
3158                return;
3159            } catch (ActivityNotFoundException e) {
3160            }
3161        }
3162        mContext.startActivity(mHomeIntent);
3163    }
3164
3165    /**
3166     * goes to the home screen
3167     * @return whether it did anything
3168     */
3169    boolean goHome() {
3170        if (false) {
3171            // This code always brings home to the front.
3172            try {
3173                ActivityManagerNative.getDefault().stopAppSwitches();
3174            } catch (RemoteException e) {
3175            }
3176            sendCloseSystemWindows();
3177            startDockOrHome();
3178        } else {
3179            // This code brings home to the front or, if it is already
3180            // at the front, puts the device to sleep.
3181            try {
3182                if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
3183                    /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
3184                    Log.d(TAG, "UTS-TEST-MODE");
3185                } else {
3186                    ActivityManagerNative.getDefault().stopAppSwitches();
3187                    sendCloseSystemWindows();
3188                    Intent dock = createHomeDockIntent();
3189                    if (dock != null) {
3190                        int result = ActivityManagerNative.getDefault()
3191                                .startActivity(null, dock,
3192                                        dock.resolveTypeIfNeeded(mContext.getContentResolver()),
3193                                        null, 0, null, null, 0, true /* onlyIfNeeded*/, false);
3194                        if (result == IActivityManager.START_RETURN_INTENT_TO_CALLER) {
3195                            return false;
3196                        }
3197                    }
3198                }
3199                int result = ActivityManagerNative.getDefault()
3200                        .startActivity(null, mHomeIntent,
3201                                mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
3202                                null, 0, null, null, 0, true /* onlyIfNeeded*/, false);
3203                if (result == IActivityManager.START_RETURN_INTENT_TO_CALLER) {
3204                    return false;
3205                }
3206            } catch (RemoteException ex) {
3207                // bummer, the activity manager, which is in this process, is dead
3208            }
3209        }
3210        return true;
3211    }
3212
3213    public void setCurrentOrientationLw(int newOrientation) {
3214        synchronized (mLock) {
3215            if (newOrientation != mCurrentAppOrientation) {
3216                mCurrentAppOrientation = newOrientation;
3217                updateOrientationListenerLp();
3218            }
3219        }
3220    }
3221
3222    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
3223        final boolean hapticsDisabled = Settings.System.getInt(mContext.getContentResolver(),
3224                Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0;
3225        if (!always && (hapticsDisabled || mKeyguardMediator.isShowingAndNotHidden())) {
3226            return false;
3227        }
3228        long[] pattern = null;
3229        switch (effectId) {
3230            case HapticFeedbackConstants.LONG_PRESS:
3231                pattern = mLongPressVibePattern;
3232                break;
3233            case HapticFeedbackConstants.VIRTUAL_KEY:
3234                pattern = mVirtualKeyVibePattern;
3235                break;
3236            case HapticFeedbackConstants.KEYBOARD_TAP:
3237                pattern = mKeyboardTapVibePattern;
3238                break;
3239            case HapticFeedbackConstants.SAFE_MODE_DISABLED:
3240                pattern = mSafeModeDisabledVibePattern;
3241                break;
3242            case HapticFeedbackConstants.SAFE_MODE_ENABLED:
3243                pattern = mSafeModeEnabledVibePattern;
3244                break;
3245            default:
3246                return false;
3247        }
3248        if (pattern.length == 1) {
3249            // One-shot vibration
3250            mVibrator.vibrate(pattern[0]);
3251        } else {
3252            // Pattern vibration
3253            mVibrator.vibrate(pattern, -1);
3254        }
3255        return true;
3256    }
3257
3258    public void screenOnStartedLw() {
3259        // The window manager has just grabbed a wake lock. This is our cue to disable the screen
3260        // saver.
3261        synchronized (mLock) {
3262            mScreenSaverEnabled = false;
3263        }
3264    }
3265
3266    public void screenOnStoppedLw() {
3267        if (mPowerManager.isScreenOn()) {
3268            if (!mKeyguardMediator.isShowingAndNotHidden()) {
3269                long curTime = SystemClock.uptimeMillis();
3270                mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT);
3271            }
3272
3273            synchronized (mLock) {
3274                // even if the keyguard is up, now that all the wakelocks have been released, we
3275                // should re-enable the screen saver
3276                mScreenSaverEnabled = true;
3277                updateScreenSaverTimeoutLocked();
3278            }
3279        }
3280    }
3281
3282    public boolean allowKeyRepeat() {
3283        // disable key repeat when screen is off
3284        return mScreenOn;
3285    }
3286
3287    private void updateSystemUiVisibility() {
3288        // If there is no window focused, there will be nobody to handle the events
3289        // anyway, so just hang on in whatever state we're in until things settle down.
3290        if (mFocusedWindow != null) {
3291            final WindowManager.LayoutParams params = mFocusedWindow.getAttrs();
3292            final int visibility = params.systemUiVisibility | params.subtreeSystemUiVisibility;
3293            mHandler.post(new Runnable() {
3294                    public void run() {
3295                        if (mStatusBarService == null) {
3296                            mStatusBarService = IStatusBarService.Stub.asInterface(
3297                                    ServiceManager.getService("statusbar"));
3298                        }
3299                        if (mStatusBarService != null) {
3300                            // need to assume status bar privileges to invoke lights on
3301                            long origId = Binder.clearCallingIdentity();
3302                            try {
3303                                mStatusBarService.setSystemUiVisibility(visibility);
3304                            } catch (RemoteException e) {
3305                                // not much to be done
3306                                mStatusBarService = null;
3307                            } finally {
3308                                Binder.restoreCallingIdentity(origId);
3309                            }
3310                        }
3311                    }
3312                });
3313        }
3314    }
3315
3316    public void dump(String prefix, FileDescriptor fd, PrintWriter pw, String[] args) {
3317        pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
3318                pw.print(" mSystemRead="); pw.println(mSystemReady);
3319        pw.print(prefix); pw.print("mLidOpen="); pw.print(mLidOpen);
3320                pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
3321                pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
3322        pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
3323                pw.print(" mDockMode="); pw.print(mDockMode);
3324                pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
3325                pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
3326        pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
3327                pw.print(" mUserRotation="); pw.print(mUserRotation);
3328                pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
3329        pw.print(prefix); pw.print("mAccelerometerDefault="); pw.print(mAccelerometerDefault);
3330                pw.print(" mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
3331        pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
3332                pw.print(mCarDockEnablesAccelerometer);
3333                pw.print(" mDeskDockEnablesAccelerometer=");
3334                pw.println(mDeskDockEnablesAccelerometer);
3335        pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
3336                pw.print(mLidKeyboardAccessibility);
3337                pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
3338                pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
3339        pw.print(prefix); pw.print("mScreenOn="); pw.print(mScreenOn);
3340                pw.print(" mOrientationSensorEnabled="); pw.print(mOrientationSensorEnabled);
3341                pw.print(" mHasSoftInput="); pw.println(mHasSoftInput);
3342        pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
3343                pw.print(","); pw.print(mUnrestrictedScreenTop);
3344                pw.print(") "); pw.print(mUnrestrictedScreenWidth);
3345                pw.print("x"); pw.println(mUnrestrictedScreenHeight);
3346        pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
3347                pw.print(","); pw.print(mRestrictedScreenTop);
3348                pw.print(") "); pw.print(mRestrictedScreenWidth);
3349                pw.print("x"); pw.println(mRestrictedScreenHeight);
3350        pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
3351                pw.print(","); pw.print(mCurTop);
3352                pw.print(")-("); pw.print(mCurRight);
3353                pw.print(","); pw.print(mCurBottom); pw.println(")");
3354        pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
3355                pw.print(","); pw.print(mContentTop);
3356                pw.print(")-("); pw.print(mContentRight);
3357                pw.print(","); pw.print(mContentBottom); pw.println(")");
3358        pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
3359                pw.print(","); pw.print(mDockTop);
3360                pw.print(")-("); pw.print(mDockRight);
3361                pw.print(","); pw.print(mDockBottom); pw.println(")");
3362        pw.print(prefix); pw.print("mDockLayer="); pw.println(mDockLayer);
3363        pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
3364                pw.println(mTopFullscreenOpaqueWindowState);
3365        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
3366                pw.print(" mForceStatusBar="); pw.print(mForceStatusBar);
3367                pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
3368        pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
3369                pw.print(" mHomePressed="); pw.println(mHomePressed);
3370        pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
3371                pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
3372                pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
3373        pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
3374                pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
3375                pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
3376        pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
3377                pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
3378        pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
3379                pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
3380    }
3381}
3382