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