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