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