PhoneWindowManager.java revision 3595be4d19caaa7ddfbff0b979d135aaf5ac20b1
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.server.policy;
18
19import android.app.ActivityManager;
20import android.app.ActivityManagerNative;
21import android.app.AppOpsManager;
22import android.app.IUiModeManager;
23import android.app.ProgressDialog;
24import android.app.SearchManager;
25import android.app.StatusBarManager;
26import android.app.UiModeManager;
27import android.content.ActivityNotFoundException;
28import android.content.BroadcastReceiver;
29import android.content.ComponentName;
30import android.content.ContentResolver;
31import android.content.Context;
32import android.content.Intent;
33import android.content.IntentFilter;
34import android.content.ServiceConnection;
35import android.content.pm.ActivityInfo;
36import android.content.pm.PackageManager;
37import android.content.pm.ResolveInfo;
38import android.content.res.CompatibilityInfo;
39import android.content.res.Configuration;
40import android.content.res.Resources;
41import android.content.res.TypedArray;
42import android.database.ContentObserver;
43import android.graphics.PixelFormat;
44import android.graphics.Rect;
45import android.media.AudioAttributes;
46import android.media.AudioManager;
47import android.media.AudioSystem;
48import android.media.IAudioService;
49import android.media.Ringtone;
50import android.media.RingtoneManager;
51import android.media.session.MediaSessionLegacyHelper;
52import android.os.Bundle;
53import android.os.Debug;
54import android.os.FactoryTest;
55import android.os.Handler;
56import android.os.IBinder;
57import android.os.Looper;
58import android.os.Message;
59import android.os.Messenger;
60import android.os.PowerManager;
61import android.os.RemoteException;
62import android.os.ServiceManager;
63import android.os.SystemClock;
64import android.os.SystemProperties;
65import android.os.UEventObserver;
66import android.os.UserHandle;
67import android.os.Vibrator;
68import android.provider.MediaStore;
69import android.provider.Settings;
70import android.service.dreams.DreamManagerInternal;
71import android.service.dreams.DreamService;
72import android.service.dreams.IDreamManager;
73import android.speech.RecognizerIntent;
74import android.telecom.TelecomManager;
75import android.util.DisplayMetrics;
76import android.util.EventLog;
77import android.util.Log;
78import android.util.Slog;
79import android.util.SparseArray;
80import android.view.Display;
81import android.view.Gravity;
82import android.view.HapticFeedbackConstants;
83import android.view.IApplicationToken;
84import android.view.IWindowManager;
85import android.view.InputChannel;
86import android.view.InputDevice;
87import android.view.InputEvent;
88import android.view.InputEventReceiver;
89import android.view.KeyCharacterMap;
90import android.view.KeyCharacterMap.FallbackAction;
91import android.view.KeyEvent;
92import android.view.MotionEvent;
93import android.view.PhoneWindow;
94import android.view.Surface;
95import android.view.View;
96import android.view.ViewConfiguration;
97import android.view.Window;
98import android.view.WindowManager;
99import android.view.WindowManagerGlobal;
100import android.view.WindowManagerInternal;
101import android.view.WindowManagerPolicy;
102import android.view.accessibility.AccessibilityEvent;
103import android.view.accessibility.AccessibilityManager;
104import android.view.animation.Animation;
105import android.view.animation.AnimationSet;
106import android.view.animation.AnimationUtils;
107import com.android.internal.R;
108import com.android.internal.statusbar.IStatusBarService;
109import com.android.internal.widget.PointerLocationView;
110import com.android.server.LocalServices;
111import com.android.server.policy.keyguard.KeyguardServiceDelegate;
112import com.android.server.policy.keyguard.KeyguardServiceDelegate.ShowListener;
113
114import java.io.File;
115import java.io.FileReader;
116import java.io.IOException;
117import java.io.PrintWriter;
118import java.util.HashSet;
119import java.util.List;
120
121import static android.view.WindowManager.LayoutParams.*;
122import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
123import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
124import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
125import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
126import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
127import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
128
129/**
130 * WindowManagerPolicy implementation for the Android phone UI.  This
131 * introduces a new method suffix, Lp, for an internal lock of the
132 * PhoneWindowManager.  This is used to protect some internal state, and
133 * can be acquired with either the Lw and Li lock held, so has the restrictions
134 * of both of those when held.
135 */
136public class PhoneWindowManager implements WindowManagerPolicy {
137    static final String TAG = "WindowManager";
138    static final boolean DEBUG = false;
139    static final boolean localLOGV = false;
140    static final boolean DEBUG_INPUT = false;
141    static final boolean DEBUG_KEYGUARD = false;
142    static final boolean DEBUG_LAYOUT = false;
143    static final boolean DEBUG_STARTING_WINDOW = false;
144    static final boolean DEBUG_WAKEUP = false;
145    static final boolean SHOW_STARTING_ANIMATIONS = true;
146    static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
147
148    // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
149    // No longer recommended for desk docks; still useful in car docks.
150    static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true;
151    static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
152
153    static final int SHORT_PRESS_POWER_NOTHING = 0;
154    static final int SHORT_PRESS_POWER_GO_TO_SLEEP = 1;
155    static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2;
156    static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3;
157    static final int SHORT_PRESS_POWER_GO_HOME = 4;
158
159    static final int LONG_PRESS_POWER_NOTHING = 0;
160    static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
161    static final int LONG_PRESS_POWER_SHUT_OFF = 2;
162    static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
163
164    static final int MULTI_PRESS_POWER_NOTHING = 0;
165    static final int MULTI_PRESS_POWER_THEATER_MODE = 1;
166    static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2;
167
168    // These need to match the documentation/constant in
169    // core/res/res/values/config.xml
170    static final int LONG_PRESS_HOME_NOTHING = 0;
171    static final int LONG_PRESS_HOME_RECENT_SYSTEM_UI = 1;
172    static final int LONG_PRESS_HOME_ASSIST = 2;
173
174    static final int DOUBLE_TAP_HOME_NOTHING = 0;
175    static final int DOUBLE_TAP_HOME_RECENT_SYSTEM_UI = 1;
176
177    static final int APPLICATION_MEDIA_SUBLAYER = -2;
178    static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
179    static final int APPLICATION_PANEL_SUBLAYER = 1;
180    static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
181
182    static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
183    static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
184    static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
185    static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
186    static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";
187
188    /**
189     * These are the system UI flags that, when changing, can cause the layout
190     * of the screen to change.
191     */
192    static final int SYSTEM_UI_CHANGING_LAYOUT =
193              View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
194            | View.SYSTEM_UI_FLAG_FULLSCREEN
195            | View.STATUS_BAR_TRANSLUCENT
196            | View.NAVIGATION_BAR_TRANSLUCENT
197            | View.SYSTEM_UI_TRANSPARENT;
198
199    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
200            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
201            .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
202            .build();
203
204    /**
205     * Keyguard stuff
206     */
207    private WindowState mKeyguardScrim;
208    private boolean mKeyguardHidden;
209    private boolean mKeyguardDrawnOnce;
210
211    /* Table of Application Launch keys.  Maps from key codes to intent categories.
212     *
213     * These are special keys that are used to launch particular kinds of applications,
214     * such as a web browser.  HID defines nearly a hundred of them in the Consumer (0x0C)
215     * usage page.  We don't support quite that many yet...
216     */
217    static SparseArray<String> sApplicationLaunchKeyCategories;
218    static {
219        sApplicationLaunchKeyCategories = new SparseArray<String>();
220        sApplicationLaunchKeyCategories.append(
221                KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER);
222        sApplicationLaunchKeyCategories.append(
223                KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL);
224        sApplicationLaunchKeyCategories.append(
225                KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS);
226        sApplicationLaunchKeyCategories.append(
227                KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR);
228        sApplicationLaunchKeyCategories.append(
229                KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC);
230        sApplicationLaunchKeyCategories.append(
231                KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
232    }
233
234    /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
235    static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;
236
237    /**
238     * Lock protecting internal state.  Must not call out into window
239     * manager with lock held.  (This lock will be acquired in places
240     * where the window manager is calling in with its own lock held.)
241     */
242    private final Object mLock = new Object();
243
244    Context mContext;
245    IWindowManager mWindowManager;
246    WindowManagerFuncs mWindowManagerFuncs;
247    WindowManagerInternal mWindowManagerInternal;
248    PowerManager mPowerManager;
249    DreamManagerInternal mDreamManagerInternal;
250    IStatusBarService mStatusBarService;
251    boolean mPreloadedRecentApps;
252    final Object mServiceAquireLock = new Object();
253    Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
254    SearchManager mSearchManager;
255    AccessibilityManager mAccessibilityManager;
256    BurnInProtectionHelper mBurnInProtectionHelper;
257
258    // Vibrator pattern for haptic feedback of a long press.
259    long[] mLongPressVibePattern;
260
261    // Vibrator pattern for haptic feedback of virtual key press.
262    long[] mVirtualKeyVibePattern;
263
264    // Vibrator pattern for a short vibration.
265    long[] mKeyboardTapVibePattern;
266
267    // Vibrator pattern for a short vibration when tapping on an hour/minute tick of a Clock.
268    long[] mClockTickVibePattern;
269
270    // Vibrator pattern for a short vibration when tapping on a day/month/year date of a Calendar.
271    long[] mCalendarDateVibePattern;
272
273    // Vibrator pattern for haptic feedback during boot when safe mode is disabled.
274    long[] mSafeModeDisabledVibePattern;
275
276    // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
277    long[] mSafeModeEnabledVibePattern;
278
279    /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
280    boolean mEnableShiftMenuBugReports = false;
281
282    boolean mSafeMode;
283    WindowState mStatusBar = null;
284    int mStatusBarHeight;
285    WindowState mNavigationBar = null;
286    boolean mHasNavigationBar = false;
287    boolean mCanHideNavigationBar = false;
288    boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?
289    boolean mNavigationBarOnBottom = true; // is the navigation bar on the bottom *right now*?
290    int[] mNavigationBarHeightForRotation = new int[4];
291    int[] mNavigationBarWidthForRotation = new int[4];
292
293    boolean mBootMessageNeedsHiding;
294    KeyguardServiceDelegate mKeyguardDelegate;
295    final Runnable mWindowManagerDrawCallback = new Runnable() {
296        @Override
297        public void run() {
298            if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!");
299            mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);
300        }
301    };
302    final ShowListener mKeyguardDelegateCallback = new ShowListener() {
303        @Override
304        public void onShown(IBinder windowToken) {
305            if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onShown.");
306            mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
307        }
308    };
309
310    GlobalActions mGlobalActions;
311    Handler mHandler;
312    WindowState mLastInputMethodWindow = null;
313    WindowState mLastInputMethodTargetWindow = null;
314
315    // FIXME This state is shared between the input reader and handler thread.
316    // Technically it's broken and buggy but it has been like this for many years
317    // and we have not yet seen any problems.  Someday we'll rewrite this logic
318    // so that only one thread is involved in handling input policy.  Unfortunately
319    // it's on a critical path for power management so we can't just post the work to the
320    // handler thread.  We'll need to resolve this someday by teaching the input dispatcher
321    // to hold wakelocks during dispatch and eliminating the critical path.
322    volatile boolean mPowerKeyHandled;
323    volatile boolean mBeganFromNonInteractive;
324    volatile int mPowerKeyPressCounter;
325    volatile boolean mEndCallKeyHandled;
326
327    boolean mRecentsVisible;
328    int mRecentAppsHeldModifiers;
329    boolean mLanguageSwitchKeyPressed;
330
331    int mLidState = LID_ABSENT;
332    int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT;
333    boolean mHaveBuiltInKeyboard;
334
335    boolean mSystemReady;
336    boolean mSystemBooted;
337    boolean mHdmiPlugged;
338    IUiModeManager mUiModeManager;
339    int mUiMode;
340    int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
341    int mLidOpenRotation;
342    int mCarDockRotation;
343    int mDeskDockRotation;
344    int mUndockedHdmiRotation;
345    int mDemoHdmiRotation;
346    boolean mDemoHdmiRotationLock;
347    int mDemoRotation;
348    boolean mDemoRotationLock;
349
350    boolean mWakeGestureEnabledSetting;
351    MyWakeGestureListener mWakeGestureListener;
352
353    // Default display does not rotate, apps that require non-default orientation will have to
354    // have the orientation emulated.
355    private boolean mForceDefaultOrientation = false;
356
357    int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
358    int mUserRotation = Surface.ROTATION_0;
359    boolean mAccelerometerDefault;
360
361    boolean mSupportAutoRotation;
362    int mAllowAllRotations = -1;
363    boolean mCarDockEnablesAccelerometer;
364    boolean mDeskDockEnablesAccelerometer;
365    int mLidKeyboardAccessibility;
366    int mLidNavigationAccessibility;
367    boolean mLidControlsSleep;
368    int mShortPressOnPowerBehavior;
369    int mLongPressOnPowerBehavior;
370    int mDoublePressOnPowerBehavior;
371    int mTriplePressOnPowerBehavior;
372    boolean mAwake;
373    boolean mScreenOnEarly;
374    boolean mScreenOnFully;
375    ScreenOnListener mScreenOnListener;
376    boolean mKeyguardDrawComplete;
377    boolean mWindowManagerDrawComplete;
378    boolean mOrientationSensorEnabled = false;
379    int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
380    boolean mHasSoftInput = false;
381    boolean mTranslucentDecorEnabled = true;
382    boolean mUseTvRouting;
383    boolean mUseMasterVolume;
384
385    int mPointerLocationMode = 0; // guarded by mLock
386
387    // The last window we were told about in focusChanged.
388    WindowState mFocusedWindow;
389    IApplicationToken mFocusedApp;
390
391    PointerLocationView mPointerLocationView;
392
393    // The current size of the screen; really; extends into the overscan area of
394    // the screen and doesn't account for any system elements like the status bar.
395    int mOverscanScreenLeft, mOverscanScreenTop;
396    int mOverscanScreenWidth, mOverscanScreenHeight;
397    // The current visible size of the screen; really; (ir)regardless of whether the status
398    // bar can be hidden but not extending into the overscan area.
399    int mUnrestrictedScreenLeft, mUnrestrictedScreenTop;
400    int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight;
401    // Like mOverscanScreen*, but allowed to move into the overscan region where appropriate.
402    int mRestrictedOverscanScreenLeft, mRestrictedOverscanScreenTop;
403    int mRestrictedOverscanScreenWidth, mRestrictedOverscanScreenHeight;
404    // The current size of the screen; these may be different than (0,0)-(dw,dh)
405    // if the status bar can't be hidden; in that case it effectively carves out
406    // that area of the display from all other windows.
407    int mRestrictedScreenLeft, mRestrictedScreenTop;
408    int mRestrictedScreenWidth, mRestrictedScreenHeight;
409    // During layout, the current screen borders accounting for any currently
410    // visible system UI elements.
411    int mSystemLeft, mSystemTop, mSystemRight, mSystemBottom;
412    // For applications requesting stable content insets, these are them.
413    int mStableLeft, mStableTop, mStableRight, mStableBottom;
414    // For applications requesting stable content insets but have also set the
415    // fullscreen window flag, these are the stable dimensions without the status bar.
416    int mStableFullscreenLeft, mStableFullscreenTop;
417    int mStableFullscreenRight, mStableFullscreenBottom;
418    // During layout, the current screen borders with all outer decoration
419    // (status bar, input method dock) accounted for.
420    int mCurLeft, mCurTop, mCurRight, mCurBottom;
421    // During layout, the frame in which content should be displayed
422    // to the user, accounting for all screen decoration except for any
423    // space they deem as available for other content.  This is usually
424    // the same as mCur*, but may be larger if the screen decor has supplied
425    // content insets.
426    int mContentLeft, mContentTop, mContentRight, mContentBottom;
427    // During layout, the frame in which voice content should be displayed
428    // to the user, accounting for all screen decoration except for any
429    // space they deem as available for other content.
430    int mVoiceContentLeft, mVoiceContentTop, mVoiceContentRight, mVoiceContentBottom;
431    // During layout, the current screen borders along which input method
432    // windows are placed.
433    int mDockLeft, mDockTop, mDockRight, mDockBottom;
434    // During layout, the layer at which the doc window is placed.
435    int mDockLayer;
436    // During layout, this is the layer of the status bar.
437    int mStatusBarLayer;
438    int mLastSystemUiFlags;
439    // Bits that we are in the process of clearing, so we want to prevent
440    // them from being set by applications until everything has been updated
441    // to have them clear.
442    int mResettingSystemUiFlags = 0;
443    // Bits that we are currently always keeping cleared.
444    int mForceClearedSystemUiFlags = 0;
445    // What we last reported to system UI about whether the compatibility
446    // menu needs to be displayed.
447    boolean mLastFocusNeedsMenu = false;
448
449    FakeWindow mHideNavFakeWindow = null;
450
451    static final Rect mTmpParentFrame = new Rect();
452    static final Rect mTmpDisplayFrame = new Rect();
453    static final Rect mTmpOverscanFrame = new Rect();
454    static final Rect mTmpContentFrame = new Rect();
455    static final Rect mTmpVisibleFrame = new Rect();
456    static final Rect mTmpDecorFrame = new Rect();
457    static final Rect mTmpStableFrame = new Rect();
458    static final Rect mTmpNavigationFrame = new Rect();
459
460    WindowState mTopFullscreenOpaqueWindowState;
461    WindowState mTopFullscreenOpaqueOrDimmingWindowState;
462    HashSet<IApplicationToken> mAppsToBeHidden = new HashSet<IApplicationToken>();
463    HashSet<IApplicationToken> mAppsThatDismissKeyguard = new HashSet<IApplicationToken>();
464    boolean mTopIsFullscreen;
465    boolean mForceStatusBar;
466    boolean mForceStatusBarFromKeyguard;
467    boolean mHideLockScreen;
468    boolean mForcingShowNavBar;
469    int mForcingShowNavBarLayer;
470
471    // States of keyguard dismiss.
472    private static final int DISMISS_KEYGUARD_NONE = 0; // Keyguard not being dismissed.
473    private static final int DISMISS_KEYGUARD_START = 1; // Keyguard needs to be dismissed.
474    private static final int DISMISS_KEYGUARD_CONTINUE = 2; // Keyguard has been dismissed.
475    int mDismissKeyguard = DISMISS_KEYGUARD_NONE;
476
477    /** The window that is currently dismissing the keyguard. Dismissing the keyguard must only
478     * be done once per window. */
479    private WindowState mWinDismissingKeyguard;
480
481    /** The window that is currently showing "over" the keyguard. If there is an app window
482     * belonging to another app on top of this the keyguard shows. If there is a fullscreen
483     * app window under this, still dismiss the keyguard but don't show the app underneath. Show
484     * the wallpaper. */
485    private WindowState mWinShowWhenLocked;
486
487    boolean mShowingLockscreen;
488    boolean mShowingDream;
489    boolean mDreamingLockscreen;
490    boolean mKeyguardSecure;
491    boolean mKeyguardSecureIncludingHidden;
492    volatile boolean mKeyguardOccluded;
493    boolean mHomePressed;
494    boolean mHomeConsumed;
495    boolean mHomeDoubleTapPending;
496    Intent mHomeIntent;
497    Intent mCarDockIntent;
498    Intent mDeskDockIntent;
499    boolean mSearchKeyShortcutPending;
500    boolean mConsumeSearchKeyUp;
501    boolean mAssistKeyLongPressed;
502    boolean mPendingMetaAction;
503
504    // support for activating the lock screen while the screen is on
505    boolean mAllowLockscreenWhenOn;
506    int mLockScreenTimeout;
507    boolean mLockScreenTimerActive;
508
509    // Behavior of ENDCALL Button.  (See Settings.System.END_BUTTON_BEHAVIOR.)
510    int mEndcallBehavior;
511
512    // Behavior of POWER button while in-call and screen on.
513    // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
514    int mIncallPowerBehavior;
515
516    Display mDisplay;
517
518    int mLandscapeRotation = 0;  // default landscape rotation
519    int mSeascapeRotation = 0;   // "other" landscape rotation, 180 degrees from mLandscapeRotation
520    int mPortraitRotation = 0;   // default portrait rotation
521    int mUpsideDownRotation = 0; // "other" portrait rotation
522
523    int mOverscanLeft = 0;
524    int mOverscanTop = 0;
525    int mOverscanRight = 0;
526    int mOverscanBottom = 0;
527
528    // What we do when the user long presses on home
529    private int mLongPressOnHomeBehavior;
530
531    // What we do when the user double-taps on home
532    private int mDoubleTapOnHomeBehavior;
533
534    // Allowed theater mode wake actions
535    private boolean mAllowTheaterModeWakeFromKey;
536    private boolean mAllowTheaterModeWakeFromPowerKey;
537    private boolean mAllowTheaterModeWakeFromMotion;
538    private boolean mAllowTheaterModeWakeFromMotionWhenNotDreaming;
539    private boolean mAllowTheaterModeWakeFromCameraLens;
540    private boolean mAllowTheaterModeWakeFromLidSwitch;
541    private boolean mAllowTheaterModeWakeFromWakeGesture;
542
543    // Whether to go to sleep entering theater mode from power button
544    private boolean mGoToSleepOnButtonPressTheaterMode;
545
546    // Screenshot trigger states
547    // Time to volume and power must be pressed within this interval of each other.
548    private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
549    // Increase the chord delay when taking a screenshot from the keyguard
550    private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f;
551    private boolean mScreenshotChordEnabled;
552    private boolean mScreenshotChordVolumeDownKeyTriggered;
553    private long mScreenshotChordVolumeDownKeyTime;
554    private boolean mScreenshotChordVolumeDownKeyConsumed;
555    private boolean mScreenshotChordVolumeUpKeyTriggered;
556    private boolean mScreenshotChordPowerKeyTriggered;
557    private long mScreenshotChordPowerKeyTime;
558
559    /* The number of steps between min and max brightness */
560    private static final int BRIGHTNESS_STEPS = 10;
561
562    SettingsObserver mSettingsObserver;
563    ShortcutManager mShortcutManager;
564    PowerManager.WakeLock mBroadcastWakeLock;
565    PowerManager.WakeLock mPowerKeyWakeLock;
566    boolean mHavePendingMediaKeyRepeatWithWakeLock;
567
568    private int mCurrentUserId;
569
570    // Maps global key codes to the components that will handle them.
571    private GlobalKeyManager mGlobalKeyManager;
572
573    // Fallback actions by key code.
574    private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions =
575            new SparseArray<KeyCharacterMap.FallbackAction>();
576
577    private final LogDecelerateInterpolator mLogDecelerateInterpolator
578            = new LogDecelerateInterpolator(100, 0);
579
580    private static final int MSG_ENABLE_POINTER_LOCATION = 1;
581    private static final int MSG_DISABLE_POINTER_LOCATION = 2;
582    private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
583    private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
584    private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
585    private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6;
586    private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7;
587    private static final int MSG_DISPATCH_SHOW_RECENTS = 9;
588    private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10;
589    private static final int MSG_HIDE_BOOT_MESSAGE = 11;
590    private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12;
591    private static final int MSG_POWER_DELAYED_PRESS = 13;
592    private static final int MSG_POWER_LONG_PRESS = 14;
593
594    private class PolicyHandler extends Handler {
595        @Override
596        public void handleMessage(Message msg) {
597            switch (msg.what) {
598                case MSG_ENABLE_POINTER_LOCATION:
599                    enablePointerLocation();
600                    break;
601                case MSG_DISABLE_POINTER_LOCATION:
602                    disablePointerLocation();
603                    break;
604                case MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK:
605                    dispatchMediaKeyWithWakeLock((KeyEvent)msg.obj);
606                    break;
607                case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK:
608                    dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj);
609                    break;
610                case MSG_DISPATCH_SHOW_RECENTS:
611                    showRecentApps(false);
612                    break;
613                case MSG_DISPATCH_SHOW_GLOBAL_ACTIONS:
614                    showGlobalActionsInternal();
615                    break;
616                case MSG_KEYGUARD_DRAWN_COMPLETE:
617                    if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete");
618                    finishKeyguardDrawn();
619                    break;
620                case MSG_KEYGUARD_DRAWN_TIMEOUT:
621                    Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete");
622                    finishKeyguardDrawn();
623                    break;
624                case MSG_WINDOW_MANAGER_DRAWN_COMPLETE:
625                    if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete");
626                    finishWindowsDrawn();
627                    break;
628                case MSG_HIDE_BOOT_MESSAGE:
629                    handleHideBootMessage();
630                    break;
631                case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK:
632                    launchVoiceAssistWithWakeLock(msg.arg1 != 0);
633                    break;
634                case MSG_POWER_DELAYED_PRESS:
635                    powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2);
636                    finishPowerKeyPress();
637                    break;
638                case MSG_POWER_LONG_PRESS:
639                    powerLongPress();
640                    break;
641            }
642        }
643    }
644
645    private UEventObserver mHDMIObserver = new UEventObserver() {
646        @Override
647        public void onUEvent(UEventObserver.UEvent event) {
648            setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
649        }
650    };
651
652    class SettingsObserver extends ContentObserver {
653        SettingsObserver(Handler handler) {
654            super(handler);
655        }
656
657        void observe() {
658            // Observe all users' changes
659            ContentResolver resolver = mContext.getContentResolver();
660            resolver.registerContentObserver(Settings.System.getUriFor(
661                    Settings.System.END_BUTTON_BEHAVIOR), false, this,
662                    UserHandle.USER_ALL);
663            resolver.registerContentObserver(Settings.Secure.getUriFor(
664                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this,
665                    UserHandle.USER_ALL);
666            resolver.registerContentObserver(Settings.Secure.getUriFor(
667                    Settings.Secure.WAKE_GESTURE_ENABLED), false, this,
668                    UserHandle.USER_ALL);
669            resolver.registerContentObserver(Settings.System.getUriFor(
670                    Settings.System.ACCELEROMETER_ROTATION), false, this,
671                    UserHandle.USER_ALL);
672            resolver.registerContentObserver(Settings.System.getUriFor(
673                    Settings.System.USER_ROTATION), false, this,
674                    UserHandle.USER_ALL);
675            resolver.registerContentObserver(Settings.System.getUriFor(
676                    Settings.System.SCREEN_OFF_TIMEOUT), false, this,
677                    UserHandle.USER_ALL);
678            resolver.registerContentObserver(Settings.System.getUriFor(
679                    Settings.System.POINTER_LOCATION), false, this,
680                    UserHandle.USER_ALL);
681            resolver.registerContentObserver(Settings.Secure.getUriFor(
682                    Settings.Secure.DEFAULT_INPUT_METHOD), false, this,
683                    UserHandle.USER_ALL);
684            resolver.registerContentObserver(Settings.Secure.getUriFor(
685                    Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this,
686                    UserHandle.USER_ALL);
687            resolver.registerContentObserver(Settings.Global.getUriFor(
688                    Settings.Global.POLICY_CONTROL), false, this,
689                    UserHandle.USER_ALL);
690            updateSettings();
691        }
692
693        @Override public void onChange(boolean selfChange) {
694            updateSettings();
695            updateRotation(false);
696        }
697    }
698
699    class MyWakeGestureListener extends WakeGestureListener {
700        MyWakeGestureListener(Context context, Handler handler) {
701            super(context, handler);
702        }
703
704        @Override
705        public void onWakeUp() {
706            synchronized (mLock) {
707                if (shouldEnableWakeGestureLp()) {
708                    performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
709                    wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture);
710                }
711            }
712        }
713    }
714
715    class MyOrientationListener extends WindowOrientationListener {
716        MyOrientationListener(Context context, Handler handler) {
717            super(context, handler);
718        }
719
720        @Override
721        public void onProposedRotationChanged(int rotation) {
722            if (localLOGV) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
723            updateRotation(false);
724        }
725    }
726    MyOrientationListener mOrientationListener;
727
728    private final StatusBarController mStatusBarController = new StatusBarController();
729
730    private final BarController mNavigationBarController = new BarController("NavigationBar",
731            View.NAVIGATION_BAR_TRANSIENT,
732            View.NAVIGATION_BAR_UNHIDE,
733            View.NAVIGATION_BAR_TRANSLUCENT,
734            StatusBarManager.WINDOW_NAVIGATION_BAR,
735            WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
736
737    private ImmersiveModeConfirmation mImmersiveModeConfirmation;
738
739    private SystemGesturesPointerEventListener mSystemGestures;
740
741    IStatusBarService getStatusBarService() {
742        synchronized (mServiceAquireLock) {
743            if (mStatusBarService == null) {
744                mStatusBarService = IStatusBarService.Stub.asInterface(
745                        ServiceManager.getService("statusbar"));
746            }
747            return mStatusBarService;
748        }
749    }
750
751    /*
752     * We always let the sensor be switched on by default except when
753     * the user has explicitly disabled sensor based rotation or when the
754     * screen is switched off.
755     */
756    boolean needSensorRunningLp() {
757        if (mSupportAutoRotation) {
758            if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
759                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
760                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
761                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
762                // If the application has explicitly requested to follow the
763                // orientation, then we need to turn the sensor on.
764                return true;
765            }
766        }
767        if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
768                (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
769                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
770                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
771            // enable accelerometer if we are docked in a dock that enables accelerometer
772            // orientation management,
773            return true;
774        }
775        if (mUserRotationMode == USER_ROTATION_LOCKED) {
776            // If the setting for using the sensor by default is enabled, then
777            // we will always leave it on.  Note that the user could go to
778            // a window that forces an orientation that does not use the
779            // sensor and in theory we could turn it off... however, when next
780            // turning it on we won't have a good value for the current
781            // orientation for a little bit, which can cause orientation
782            // changes to lag, so we'd like to keep it always on.  (It will
783            // still be turned off when the screen is off.)
784            return false;
785        }
786        return mSupportAutoRotation;
787    }
788
789    /*
790     * Various use cases for invoking this function
791     * screen turning off, should always disable listeners if already enabled
792     * screen turned on and current app has sensor based orientation, enable listeners
793     * if not already enabled
794     * screen turned on and current app does not have sensor orientation, disable listeners if
795     * already enabled
796     * screen turning on and current app has sensor based orientation, enable listeners if needed
797     * screen turning on and current app has nosensor based orientation, do nothing
798     */
799    void updateOrientationListenerLp() {
800        if (!mOrientationListener.canDetectOrientation()) {
801            // If sensor is turned off or nonexistent for some reason
802            return;
803        }
804        //Could have been invoked due to screen turning on or off or
805        //change of the currently visible window's orientation
806        if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly
807                + ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation
808                + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled);
809        boolean disable = true;
810        if (mScreenOnEarly && mAwake) {
811            if (needSensorRunningLp()) {
812                disable = false;
813                //enable listener if not already enabled
814                if (!mOrientationSensorEnabled) {
815                    mOrientationListener.enable();
816                    if(localLOGV) Slog.v(TAG, "Enabling listeners");
817                    mOrientationSensorEnabled = true;
818                }
819            }
820        }
821        //check if sensors need to be disabled
822        if (disable && mOrientationSensorEnabled) {
823            mOrientationListener.disable();
824            if(localLOGV) Slog.v(TAG, "Disabling listeners");
825            mOrientationSensorEnabled = false;
826        }
827    }
828
829    private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
830        // Hold a wake lock until the power key is released.
831        if (!mPowerKeyWakeLock.isHeld()) {
832            mPowerKeyWakeLock.acquire();
833        }
834
835        // Cancel multi-press detection timeout.
836        if (mPowerKeyPressCounter != 0) {
837            mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);
838        }
839
840        // Detect user pressing the power button in panic when an application has
841        // taken over the whole screen.
842        boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
843                SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags));
844        if (panic) {
845            mHandler.post(mRequestTransientNav);
846        }
847
848        // Latch power key state to detect screenshot chord.
849        if (interactive && !mScreenshotChordPowerKeyTriggered
850                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
851            mScreenshotChordPowerKeyTriggered = true;
852            mScreenshotChordPowerKeyTime = event.getDownTime();
853            interceptScreenshotChord();
854        }
855
856        // Stop ringing or end call if configured to do so when power is pressed.
857        TelecomManager telecomManager = getTelecommService();
858        boolean hungUp = false;
859        if (telecomManager != null) {
860            if (telecomManager.isRinging()) {
861                // Pressing Power while there's a ringing incoming
862                // call should silence the ringer.
863                telecomManager.silenceRinger();
864            } else if ((mIncallPowerBehavior
865                    & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
866                    && telecomManager.isInCall() && interactive) {
867                // Otherwise, if "Power button ends call" is enabled,
868                // the Power button will hang up any current active call.
869                hungUp = telecomManager.endCall();
870            }
871        }
872
873        // If the power key has still not yet been handled, then detect short
874        // press, long press, or multi press and decide what to do.
875        mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
876                || mScreenshotChordVolumeUpKeyTriggered;
877        if (!mPowerKeyHandled) {
878            if (interactive) {
879                // When interactive, we're already awake.
880                // Wait for a long press or for the button to be released to decide what to do.
881                if (hasLongPressOnPowerBehavior()) {
882                    Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
883                    msg.setAsynchronous(true);
884                    mHandler.sendMessageDelayed(msg,
885                            ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
886                }
887            } else {
888                wakeUpFromPowerKey(event.getDownTime());
889                final int maxCount = getMaxMultiPressPowerCount();
890
891                if (maxCount <= 1) {
892                    mPowerKeyHandled = true;
893                } else {
894                    mBeganFromNonInteractive = true;
895                }
896            }
897        }
898    }
899
900    private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
901        final boolean handled = canceled || mPowerKeyHandled;
902        mScreenshotChordPowerKeyTriggered = false;
903        cancelPendingScreenshotChordAction();
904        cancelPendingPowerKeyAction();
905
906        if (!handled) {
907            // Figure out how to handle the key now that it has been released.
908            mPowerKeyPressCounter += 1;
909
910            final int maxCount = getMaxMultiPressPowerCount();
911            final long eventTime = event.getDownTime();
912            if (mPowerKeyPressCounter < maxCount) {
913                // This could be a multi-press.  Wait a little bit longer to confirm.
914                // Continue holding the wake lock.
915                Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
916                        interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
917                msg.setAsynchronous(true);
918                mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
919                return;
920            }
921
922            // No other actions.  Handle it immediately.
923            powerPress(eventTime, interactive, mPowerKeyPressCounter);
924        }
925
926        // Done.  Reset our state.
927        finishPowerKeyPress();
928    }
929
930    private void finishPowerKeyPress() {
931        mBeganFromNonInteractive = false;
932        mPowerKeyPressCounter = 0;
933        if (mPowerKeyWakeLock.isHeld()) {
934            mPowerKeyWakeLock.release();
935        }
936    }
937
938    private void cancelPendingPowerKeyAction() {
939        if (!mPowerKeyHandled) {
940            mPowerKeyHandled = true;
941            mHandler.removeMessages(MSG_POWER_LONG_PRESS);
942        }
943    }
944
945    private void powerPress(long eventTime, boolean interactive, int count) {
946        if (mScreenOnEarly && !mScreenOnFully) {
947            Slog.i(TAG, "Suppressed redundant power key press while "
948                    + "already in the process of turning the screen on.");
949            return;
950        }
951
952        if (count == 2) {
953            powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
954        } else if (count == 3) {
955            powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
956        } else if (interactive && !mBeganFromNonInteractive) {
957            switch (mShortPressOnPowerBehavior) {
958                case SHORT_PRESS_POWER_NOTHING:
959                    break;
960                case SHORT_PRESS_POWER_GO_TO_SLEEP:
961                    mPowerManager.goToSleep(eventTime,
962                            PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
963                    break;
964                case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
965                    mPowerManager.goToSleep(eventTime,
966                            PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
967                            PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
968                    break;
969                case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
970                    mPowerManager.goToSleep(eventTime,
971                            PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
972                            PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
973                    launchHomeFromHotKey();
974                    break;
975                case SHORT_PRESS_POWER_GO_HOME:
976                    launchHomeFromHotKey();
977                    break;
978            }
979        }
980    }
981
982    private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) {
983        switch (behavior) {
984            case MULTI_PRESS_POWER_NOTHING:
985                break;
986            case MULTI_PRESS_POWER_THEATER_MODE:
987                if (isTheaterModeEnabled()) {
988                    Slog.i(TAG, "Toggling theater mode off.");
989                    Settings.Global.putInt(mContext.getContentResolver(),
990                            Settings.Global.THEATER_MODE_ON, 0);
991                    if (!interactive) {
992                        wakeUpFromPowerKey(eventTime);
993                    }
994                } else {
995                    Slog.i(TAG, "Toggling theater mode on.");
996                    Settings.Global.putInt(mContext.getContentResolver(),
997                            Settings.Global.THEATER_MODE_ON, 1);
998
999                    if (mGoToSleepOnButtonPressTheaterMode && interactive) {
1000                        mPowerManager.goToSleep(eventTime,
1001                                PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
1002                    }
1003                }
1004                break;
1005            case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
1006                Slog.i(TAG, "Starting brightness boost.");
1007                if (!interactive) {
1008                    wakeUpFromPowerKey(eventTime);
1009                }
1010                mPowerManager.boostScreenBrightness(eventTime);
1011                break;
1012        }
1013    }
1014
1015    private int getMaxMultiPressPowerCount() {
1016        if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
1017            return 3;
1018        }
1019        if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
1020            return 2;
1021        }
1022        return 1;
1023    }
1024
1025    private void powerLongPress() {
1026        final int behavior = getResolvedLongPressOnPowerBehavior();
1027        switch (behavior) {
1028        case LONG_PRESS_POWER_NOTHING:
1029            break;
1030        case LONG_PRESS_POWER_GLOBAL_ACTIONS:
1031            mPowerKeyHandled = true;
1032            if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
1033                performAuditoryFeedbackForAccessibilityIfNeed();
1034            }
1035            showGlobalActionsInternal();
1036            break;
1037        case LONG_PRESS_POWER_SHUT_OFF:
1038        case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
1039            mPowerKeyHandled = true;
1040            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1041            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
1042            mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
1043            break;
1044        }
1045    }
1046
1047    private int getResolvedLongPressOnPowerBehavior() {
1048        if (FactoryTest.isLongPressOnPowerOffEnabled()) {
1049            return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
1050        }
1051        return mLongPressOnPowerBehavior;
1052    }
1053
1054    private boolean hasLongPressOnPowerBehavior() {
1055        return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;
1056    }
1057
1058    private void interceptScreenshotChord() {
1059        if (mScreenshotChordEnabled
1060                && mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered
1061                && !mScreenshotChordVolumeUpKeyTriggered) {
1062            final long now = SystemClock.uptimeMillis();
1063            if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
1064                    && now <= mScreenshotChordPowerKeyTime
1065                            + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
1066                mScreenshotChordVolumeDownKeyConsumed = true;
1067                cancelPendingPowerKeyAction();
1068
1069                mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
1070            }
1071        }
1072    }
1073
1074    private long getScreenshotChordLongPressDelay() {
1075        if (mKeyguardDelegate.isShowing()) {
1076            // Double the time it takes to take a screenshot from the keyguard
1077            return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER *
1078                    ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1079        }
1080        return ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout();
1081    }
1082
1083    private void cancelPendingScreenshotChordAction() {
1084        mHandler.removeCallbacks(mScreenshotRunnable);
1085    }
1086
1087    private final Runnable mEndCallLongPress = new Runnable() {
1088        @Override
1089        public void run() {
1090            mEndCallKeyHandled = true;
1091            if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
1092                performAuditoryFeedbackForAccessibilityIfNeed();
1093            }
1094            showGlobalActionsInternal();
1095        }
1096    };
1097
1098    private final Runnable mScreenshotRunnable = new Runnable() {
1099        @Override
1100        public void run() {
1101            takeScreenshot();
1102        }
1103    };
1104
1105    @Override
1106    public void showGlobalActions() {
1107        mHandler.removeMessages(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
1108        mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
1109    }
1110
1111    void showGlobalActionsInternal() {
1112        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
1113        if (mGlobalActions == null) {
1114            mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
1115        }
1116        final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();
1117        mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
1118        if (keyguardShowing) {
1119            // since it took two seconds of long press to bring this up,
1120            // poke the wake lock so they have some time to see the dialog.
1121            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
1122        }
1123    }
1124
1125    boolean isDeviceProvisioned() {
1126        return Settings.Global.getInt(
1127                mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
1128    }
1129
1130    boolean isUserSetupComplete() {
1131        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
1132                Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
1133    }
1134
1135    private void handleShortPressOnHome() {
1136        // If there's a dream running then use home to escape the dream
1137        // but don't actually go home.
1138        if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) {
1139            mDreamManagerInternal.stopDream(false /*immediate*/);
1140            return;
1141        }
1142
1143        // Go home!
1144        launchHomeFromHotKey();
1145    }
1146
1147    private void handleLongPressOnHome() {
1148        if (mLongPressOnHomeBehavior != LONG_PRESS_HOME_NOTHING) {
1149            mHomeConsumed = true;
1150            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1151
1152            if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
1153                toggleRecentApps();
1154            } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_ASSIST) {
1155                launchAssistAction();
1156            }
1157        }
1158    }
1159
1160    private void handleDoubleTapOnHome() {
1161        if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
1162            mHomeConsumed = true;
1163            toggleRecentApps();
1164        }
1165    }
1166
1167    private final Runnable mHomeDoubleTapTimeoutRunnable = new Runnable() {
1168        @Override
1169        public void run() {
1170            if (mHomeDoubleTapPending) {
1171                mHomeDoubleTapPending = false;
1172                handleShortPressOnHome();
1173            }
1174        }
1175    };
1176
1177    /** {@inheritDoc} */
1178    @Override
1179    public void init(Context context, IWindowManager windowManager,
1180            WindowManagerFuncs windowManagerFuncs) {
1181        mContext = context;
1182        mWindowManager = windowManager;
1183        mWindowManagerFuncs = windowManagerFuncs;
1184        mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
1185        mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
1186        if (context.getResources().getBoolean(
1187                com.android.internal.R.bool.config_enableBurnInProtection)){
1188            mBurnInProtectionHelper = new BurnInProtectionHelper(context);
1189        }
1190
1191        mHandler = new PolicyHandler();
1192        mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
1193        mOrientationListener = new MyOrientationListener(mContext, mHandler);
1194        try {
1195            mOrientationListener.setCurrentRotation(windowManager.getRotation());
1196        } catch (RemoteException ex) { }
1197        mSettingsObserver = new SettingsObserver(mHandler);
1198        mSettingsObserver.observe();
1199        mShortcutManager = new ShortcutManager(context);
1200        mUiMode = context.getResources().getInteger(
1201                com.android.internal.R.integer.config_defaultUiModeType);
1202        mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
1203        mHomeIntent.addCategory(Intent.CATEGORY_HOME);
1204        mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1205                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1206        mCarDockIntent =  new Intent(Intent.ACTION_MAIN, null);
1207        mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
1208        mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1209                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1210        mDeskDockIntent =  new Intent(Intent.ACTION_MAIN, null);
1211        mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
1212        mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1213                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1214
1215        mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1216        mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1217                "PhoneWindowManager.mBroadcastWakeLock");
1218        mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1219                "PhoneWindowManager.mPowerKeyWakeLock");
1220        mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
1221        mSupportAutoRotation = mContext.getResources().getBoolean(
1222                com.android.internal.R.bool.config_supportAutoRotation);
1223        mLidOpenRotation = readRotation(
1224                com.android.internal.R.integer.config_lidOpenRotation);
1225        mCarDockRotation = readRotation(
1226                com.android.internal.R.integer.config_carDockRotation);
1227        mDeskDockRotation = readRotation(
1228                com.android.internal.R.integer.config_deskDockRotation);
1229        mUndockedHdmiRotation = readRotation(
1230                com.android.internal.R.integer.config_undockedHdmiRotation);
1231        mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
1232                com.android.internal.R.bool.config_carDockEnablesAccelerometer);
1233        mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
1234                com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
1235        mLidKeyboardAccessibility = mContext.getResources().getInteger(
1236                com.android.internal.R.integer.config_lidKeyboardAccessibility);
1237        mLidNavigationAccessibility = mContext.getResources().getInteger(
1238                com.android.internal.R.integer.config_lidNavigationAccessibility);
1239        mLidControlsSleep = mContext.getResources().getBoolean(
1240                com.android.internal.R.bool.config_lidControlsSleep);
1241        mTranslucentDecorEnabled = mContext.getResources().getBoolean(
1242                com.android.internal.R.bool.config_enableTranslucentDecor);
1243
1244        mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
1245                com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
1246        mAllowTheaterModeWakeFromPowerKey = mAllowTheaterModeWakeFromKey
1247                || mContext.getResources().getBoolean(
1248                    com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey);
1249        mAllowTheaterModeWakeFromMotion = mContext.getResources().getBoolean(
1250                com.android.internal.R.bool.config_allowTheaterModeWakeFromMotion);
1251        mAllowTheaterModeWakeFromMotionWhenNotDreaming = mContext.getResources().getBoolean(
1252                com.android.internal.R.bool.config_allowTheaterModeWakeFromMotionWhenNotDreaming);
1253        mAllowTheaterModeWakeFromCameraLens = mContext.getResources().getBoolean(
1254                com.android.internal.R.bool.config_allowTheaterModeWakeFromCameraLens);
1255        mAllowTheaterModeWakeFromLidSwitch = mContext.getResources().getBoolean(
1256                com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch);
1257        mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean(
1258                com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture);
1259
1260        mGoToSleepOnButtonPressTheaterMode = mContext.getResources().getBoolean(
1261                com.android.internal.R.bool.config_goToSleepOnButtonPressTheaterMode);
1262
1263        mShortPressOnPowerBehavior = mContext.getResources().getInteger(
1264                com.android.internal.R.integer.config_shortPressOnPowerBehavior);
1265        mLongPressOnPowerBehavior = mContext.getResources().getInteger(
1266                com.android.internal.R.integer.config_longPressOnPowerBehavior);
1267        mDoublePressOnPowerBehavior = mContext.getResources().getInteger(
1268                com.android.internal.R.integer.config_doublePressOnPowerBehavior);
1269        mTriplePressOnPowerBehavior = mContext.getResources().getInteger(
1270                com.android.internal.R.integer.config_triplePressOnPowerBehavior);
1271
1272        mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION;
1273        mUseMasterVolume = mContext.getResources().getBoolean(
1274                com.android.internal.R.bool.config_useMasterVolume);
1275
1276        readConfigurationDependentBehaviors();
1277
1278        mAccessibilityManager = (AccessibilityManager) context.getSystemService(
1279                Context.ACCESSIBILITY_SERVICE);
1280
1281        // register for dock events
1282        IntentFilter filter = new IntentFilter();
1283        filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
1284        filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
1285        filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
1286        filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
1287        filter.addAction(Intent.ACTION_DOCK_EVENT);
1288        Intent intent = context.registerReceiver(mDockReceiver, filter);
1289        if (intent != null) {
1290            // Retrieve current sticky dock event broadcast.
1291            mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
1292                    Intent.EXTRA_DOCK_STATE_UNDOCKED);
1293        }
1294
1295        // register for dream-related broadcasts
1296        filter = new IntentFilter();
1297        filter.addAction(Intent.ACTION_DREAMING_STARTED);
1298        filter.addAction(Intent.ACTION_DREAMING_STOPPED);
1299        context.registerReceiver(mDreamReceiver, filter);
1300
1301        // register for multiuser-relevant broadcasts
1302        filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
1303        context.registerReceiver(mMultiuserReceiver, filter);
1304
1305        // monitor for system gestures
1306        mSystemGestures = new SystemGesturesPointerEventListener(context,
1307                new SystemGesturesPointerEventListener.Callbacks() {
1308                    @Override
1309                    public void onSwipeFromTop() {
1310                        if (mStatusBar != null) {
1311                            requestTransientBars(mStatusBar);
1312                        }
1313                    }
1314                    @Override
1315                    public void onSwipeFromBottom() {
1316                        if (mNavigationBar != null && mNavigationBarOnBottom) {
1317                            requestTransientBars(mNavigationBar);
1318                        }
1319                    }
1320                    @Override
1321                    public void onSwipeFromRight() {
1322                        if (mNavigationBar != null && !mNavigationBarOnBottom) {
1323                            requestTransientBars(mNavigationBar);
1324                        }
1325                    }
1326                    @Override
1327                    public void onDebug() {
1328                        // no-op
1329                    }
1330                    @Override
1331                    public void onDown() {
1332                        mOrientationListener.onTouchStart();
1333                    }
1334                    @Override
1335                    public void onUpOrCancel() {
1336                        mOrientationListener.onTouchEnd();
1337                    }
1338                });
1339        mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext);
1340        mWindowManagerFuncs.registerPointerEventListener(mSystemGestures);
1341
1342        mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
1343        mLongPressVibePattern = getLongIntArray(mContext.getResources(),
1344                com.android.internal.R.array.config_longPressVibePattern);
1345        mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(),
1346                com.android.internal.R.array.config_virtualKeyVibePattern);
1347        mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(),
1348                com.android.internal.R.array.config_keyboardTapVibePattern);
1349        mClockTickVibePattern = getLongIntArray(mContext.getResources(),
1350                com.android.internal.R.array.config_clockTickVibePattern);
1351        mCalendarDateVibePattern = getLongIntArray(mContext.getResources(),
1352                com.android.internal.R.array.config_calendarDateVibePattern);
1353        mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
1354                com.android.internal.R.array.config_safeModeDisabledVibePattern);
1355        mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
1356                com.android.internal.R.array.config_safeModeEnabledVibePattern);
1357
1358        mScreenshotChordEnabled = mContext.getResources().getBoolean(
1359                com.android.internal.R.bool.config_enableScreenshotChord);
1360
1361        mGlobalKeyManager = new GlobalKeyManager(mContext);
1362
1363        // Controls rotation and the like.
1364        initializeHdmiState();
1365
1366        // Match current screen state.
1367        if (!mPowerManager.isInteractive()) {
1368            goingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
1369        }
1370
1371        mWindowManagerInternal.registerAppTransitionListener(
1372                mStatusBarController.getAppTransitionListener());
1373    }
1374
1375    /**
1376     * Read values from config.xml that may be overridden depending on
1377     * the configuration of the device.
1378     * eg. Disable long press on home goes to recents on sw600dp.
1379     */
1380    private void readConfigurationDependentBehaviors() {
1381        mLongPressOnHomeBehavior = mContext.getResources().getInteger(
1382                com.android.internal.R.integer.config_longPressOnHomeBehavior);
1383        if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||
1384                mLongPressOnHomeBehavior > LONG_PRESS_HOME_ASSIST) {
1385            mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
1386        }
1387
1388        mDoubleTapOnHomeBehavior = mContext.getResources().getInteger(
1389                com.android.internal.R.integer.config_doubleTapOnHomeBehavior);
1390        if (mDoubleTapOnHomeBehavior < DOUBLE_TAP_HOME_NOTHING ||
1391                mDoubleTapOnHomeBehavior > DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
1392            mDoubleTapOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
1393        }
1394    }
1395
1396    @Override
1397    public void setInitialDisplaySize(Display display, int width, int height, int density) {
1398        // This method might be called before the policy has been fully initialized
1399        // or for other displays we don't care about.
1400        if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) {
1401            return;
1402        }
1403        mDisplay = display;
1404
1405        final Resources res = mContext.getResources();
1406        int shortSize, longSize;
1407        if (width > height) {
1408            shortSize = height;
1409            longSize = width;
1410            mLandscapeRotation = Surface.ROTATION_0;
1411            mSeascapeRotation = Surface.ROTATION_180;
1412            if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
1413                mPortraitRotation = Surface.ROTATION_90;
1414                mUpsideDownRotation = Surface.ROTATION_270;
1415            } else {
1416                mPortraitRotation = Surface.ROTATION_270;
1417                mUpsideDownRotation = Surface.ROTATION_90;
1418            }
1419        } else {
1420            shortSize = width;
1421            longSize = height;
1422            mPortraitRotation = Surface.ROTATION_0;
1423            mUpsideDownRotation = Surface.ROTATION_180;
1424            if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
1425                mLandscapeRotation = Surface.ROTATION_270;
1426                mSeascapeRotation = Surface.ROTATION_90;
1427            } else {
1428                mLandscapeRotation = Surface.ROTATION_90;
1429                mSeascapeRotation = Surface.ROTATION_270;
1430            }
1431        }
1432
1433        mStatusBarHeight =
1434                res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
1435
1436        // Height of the navigation bar when presented horizontally at bottom
1437        mNavigationBarHeightForRotation[mPortraitRotation] =
1438        mNavigationBarHeightForRotation[mUpsideDownRotation] =
1439                res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
1440        mNavigationBarHeightForRotation[mLandscapeRotation] =
1441        mNavigationBarHeightForRotation[mSeascapeRotation] = res.getDimensionPixelSize(
1442                com.android.internal.R.dimen.navigation_bar_height_landscape);
1443
1444        // Width of the navigation bar when presented vertically along one side
1445        mNavigationBarWidthForRotation[mPortraitRotation] =
1446        mNavigationBarWidthForRotation[mUpsideDownRotation] =
1447        mNavigationBarWidthForRotation[mLandscapeRotation] =
1448        mNavigationBarWidthForRotation[mSeascapeRotation] =
1449                res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
1450
1451        // SystemUI (status bar) layout policy
1452        int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
1453        int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
1454
1455        // Allow the navigation bar to move on non-square small devices (phones).
1456        mNavigationBarCanMove = width != height && shortSizeDp < 600;
1457
1458        mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
1459        // Allow a system property to override this. Used by the emulator.
1460        // See also hasNavigationBar().
1461        String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
1462        if ("1".equals(navBarOverride)) {
1463            mHasNavigationBar = false;
1464        } else if ("0".equals(navBarOverride)) {
1465            mHasNavigationBar = true;
1466        }
1467
1468        // For demo purposes, allow the rotation of the HDMI display to be controlled.
1469        // By default, HDMI locks rotation to landscape.
1470        if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
1471            mDemoHdmiRotation = mPortraitRotation;
1472        } else {
1473            mDemoHdmiRotation = mLandscapeRotation;
1474        }
1475        mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
1476
1477        // For demo purposes, allow the rotation of the remote display to be controlled.
1478        // By default, remote display locks rotation to landscape.
1479        if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
1480            mDemoRotation = mPortraitRotation;
1481        } else {
1482            mDemoRotation = mLandscapeRotation;
1483        }
1484        mDemoRotationLock = SystemProperties.getBoolean(
1485                "persist.demo.rotationlock", false);
1486
1487        // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
1488        // http://developer.android.com/guide/practices/screens_support.html#range
1489        mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 &&
1490                res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
1491                // For debug purposes the next line turns this feature off with:
1492                // $ adb shell setprop config.override_forced_orient true
1493                // $ adb shell wm size reset
1494                !"true".equals(SystemProperties.get("config.override_forced_orient"));
1495    }
1496
1497    /**
1498     * @return whether the navigation bar can be hidden, e.g. the device has a
1499     *         navigation bar and touch exploration is not enabled
1500     */
1501    private boolean canHideNavigationBar() {
1502        return mHasNavigationBar
1503                && !mAccessibilityManager.isTouchExplorationEnabled();
1504    }
1505
1506    @Override
1507    public boolean isDefaultOrientationForced() {
1508        return mForceDefaultOrientation;
1509    }
1510
1511    @Override
1512    public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) {
1513        if (display.getDisplayId() == Display.DEFAULT_DISPLAY) {
1514            mOverscanLeft = left;
1515            mOverscanTop = top;
1516            mOverscanRight = right;
1517            mOverscanBottom = bottom;
1518        }
1519    }
1520
1521    public void updateSettings() {
1522        ContentResolver resolver = mContext.getContentResolver();
1523        boolean updateRotation = false;
1524        synchronized (mLock) {
1525            mEndcallBehavior = Settings.System.getIntForUser(resolver,
1526                    Settings.System.END_BUTTON_BEHAVIOR,
1527                    Settings.System.END_BUTTON_BEHAVIOR_DEFAULT,
1528                    UserHandle.USER_CURRENT);
1529            mIncallPowerBehavior = Settings.Secure.getIntForUser(resolver,
1530                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
1531                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT,
1532                    UserHandle.USER_CURRENT);
1533
1534            // Configure wake gesture.
1535            boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver,
1536                    Settings.Secure.WAKE_GESTURE_ENABLED, 0,
1537                    UserHandle.USER_CURRENT) != 0;
1538            if (mWakeGestureEnabledSetting != wakeGestureEnabledSetting) {
1539                mWakeGestureEnabledSetting = wakeGestureEnabledSetting;
1540                updateWakeGestureListenerLp();
1541            }
1542
1543            // Configure rotation lock.
1544            int userRotation = Settings.System.getIntForUser(resolver,
1545                    Settings.System.USER_ROTATION, Surface.ROTATION_0,
1546                    UserHandle.USER_CURRENT);
1547            if (mUserRotation != userRotation) {
1548                mUserRotation = userRotation;
1549                updateRotation = true;
1550            }
1551            int userRotationMode = Settings.System.getIntForUser(resolver,
1552                    Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
1553                            WindowManagerPolicy.USER_ROTATION_FREE :
1554                                    WindowManagerPolicy.USER_ROTATION_LOCKED;
1555            if (mUserRotationMode != userRotationMode) {
1556                mUserRotationMode = userRotationMode;
1557                updateRotation = true;
1558                updateOrientationListenerLp();
1559            }
1560
1561            if (mSystemReady) {
1562                int pointerLocation = Settings.System.getIntForUser(resolver,
1563                        Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT);
1564                if (mPointerLocationMode != pointerLocation) {
1565                    mPointerLocationMode = pointerLocation;
1566                    mHandler.sendEmptyMessage(pointerLocation != 0 ?
1567                            MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
1568                }
1569            }
1570            // use screen off timeout setting as the timeout for the lockscreen
1571            mLockScreenTimeout = Settings.System.getIntForUser(resolver,
1572                    Settings.System.SCREEN_OFF_TIMEOUT, 0, UserHandle.USER_CURRENT);
1573            String imId = Settings.Secure.getStringForUser(resolver,
1574                    Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.USER_CURRENT);
1575            boolean hasSoftInput = imId != null && imId.length() > 0;
1576            if (mHasSoftInput != hasSoftInput) {
1577                mHasSoftInput = hasSoftInput;
1578                updateRotation = true;
1579            }
1580            if (mImmersiveModeConfirmation != null) {
1581                mImmersiveModeConfirmation.loadSetting(mCurrentUserId);
1582            }
1583            PolicyControl.reloadFromSetting(mContext);
1584        }
1585        if (updateRotation) {
1586            updateRotation(true);
1587        }
1588    }
1589
1590    private void updateWakeGestureListenerLp() {
1591        if (shouldEnableWakeGestureLp()) {
1592            mWakeGestureListener.requestWakeUpTrigger();
1593        } else {
1594            mWakeGestureListener.cancelWakeUpTrigger();
1595        }
1596    }
1597
1598    private boolean shouldEnableWakeGestureLp() {
1599        return mWakeGestureEnabledSetting && !mAwake
1600                && (!mLidControlsSleep || mLidState != LID_CLOSED)
1601                && mWakeGestureListener.isSupported();
1602    }
1603
1604    private void enablePointerLocation() {
1605        if (mPointerLocationView == null) {
1606            mPointerLocationView = new PointerLocationView(mContext);
1607            mPointerLocationView.setPrintCoords(false);
1608            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
1609                    WindowManager.LayoutParams.MATCH_PARENT,
1610                    WindowManager.LayoutParams.MATCH_PARENT);
1611            lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
1612            lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
1613                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
1614                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
1615                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
1616            if (ActivityManager.isHighEndGfx()) {
1617                lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
1618                lp.privateFlags |=
1619                        WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
1620            }
1621            lp.format = PixelFormat.TRANSLUCENT;
1622            lp.setTitle("PointerLocation");
1623            WindowManager wm = (WindowManager)
1624                    mContext.getSystemService(Context.WINDOW_SERVICE);
1625            lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
1626            wm.addView(mPointerLocationView, lp);
1627            mWindowManagerFuncs.registerPointerEventListener(mPointerLocationView);
1628        }
1629    }
1630
1631    private void disablePointerLocation() {
1632        if (mPointerLocationView != null) {
1633            mWindowManagerFuncs.unregisterPointerEventListener(mPointerLocationView);
1634            WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
1635            wm.removeView(mPointerLocationView);
1636            mPointerLocationView = null;
1637        }
1638    }
1639
1640    private int readRotation(int resID) {
1641        try {
1642            int rotation = mContext.getResources().getInteger(resID);
1643            switch (rotation) {
1644                case 0:
1645                    return Surface.ROTATION_0;
1646                case 90:
1647                    return Surface.ROTATION_90;
1648                case 180:
1649                    return Surface.ROTATION_180;
1650                case 270:
1651                    return Surface.ROTATION_270;
1652            }
1653        } catch (Resources.NotFoundException e) {
1654            // fall through
1655        }
1656        return -1;
1657    }
1658
1659    /** {@inheritDoc} */
1660    @Override
1661    public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) {
1662        int type = attrs.type;
1663
1664        outAppOp[0] = AppOpsManager.OP_NONE;
1665
1666        if (!((type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW)
1667                || (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW)
1668                || (type >= FIRST_SYSTEM_WINDOW && type <= LAST_SYSTEM_WINDOW))) {
1669            return WindowManagerGlobal.ADD_INVALID_TYPE;
1670        }
1671
1672        if (type < FIRST_SYSTEM_WINDOW || type > LAST_SYSTEM_WINDOW) {
1673            // Window manager will make sure these are okay.
1674            return WindowManagerGlobal.ADD_OKAY;
1675        }
1676        String permission = null;
1677        switch (type) {
1678            case TYPE_TOAST:
1679                // XXX right now the app process has complete control over
1680                // this...  should introduce a token to let the system
1681                // monitor/control what they are doing.
1682                outAppOp[0] = AppOpsManager.OP_TOAST_WINDOW;
1683                break;
1684            case TYPE_DREAM:
1685            case TYPE_INPUT_METHOD:
1686            case TYPE_WALLPAPER:
1687            case TYPE_PRIVATE_PRESENTATION:
1688            case TYPE_VOICE_INTERACTION:
1689            case TYPE_ACCESSIBILITY_OVERLAY:
1690                // The window manager will check these.
1691                break;
1692            case TYPE_PHONE:
1693            case TYPE_PRIORITY_PHONE:
1694            case TYPE_SYSTEM_ALERT:
1695            case TYPE_SYSTEM_ERROR:
1696            case TYPE_SYSTEM_OVERLAY:
1697                permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
1698                outAppOp[0] = AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
1699                break;
1700            default:
1701                permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
1702        }
1703        if (permission != null) {
1704            if (mContext.checkCallingOrSelfPermission(permission)
1705                    != PackageManager.PERMISSION_GRANTED) {
1706                return WindowManagerGlobal.ADD_PERMISSION_DENIED;
1707            }
1708        }
1709        return WindowManagerGlobal.ADD_OKAY;
1710    }
1711
1712    @Override
1713    public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) {
1714
1715        // If this switch statement is modified, modify the comment in the declarations of
1716        // the type in {@link WindowManager.LayoutParams} as well.
1717        switch (attrs.type) {
1718            default:
1719                // These are the windows that by default are shown only to the user that created
1720                // them. If this needs to be overridden, set
1721                // {@link WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS} in
1722                // {@link WindowManager.LayoutParams}. Note that permission
1723                // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well.
1724                if ((attrs.privateFlags & PRIVATE_FLAG_SHOW_FOR_ALL_USERS) == 0) {
1725                    return true;
1726                }
1727                break;
1728
1729            // These are the windows that by default are shown to all users. However, to
1730            // protect against spoofing, check permissions below.
1731            case TYPE_APPLICATION_STARTING:
1732            case TYPE_BOOT_PROGRESS:
1733            case TYPE_DISPLAY_OVERLAY:
1734            case TYPE_HIDDEN_NAV_CONSUMER:
1735            case TYPE_KEYGUARD_SCRIM:
1736            case TYPE_KEYGUARD_DIALOG:
1737            case TYPE_MAGNIFICATION_OVERLAY:
1738            case TYPE_NAVIGATION_BAR:
1739            case TYPE_NAVIGATION_BAR_PANEL:
1740            case TYPE_PHONE:
1741            case TYPE_POINTER:
1742            case TYPE_PRIORITY_PHONE:
1743            case TYPE_SEARCH_BAR:
1744            case TYPE_STATUS_BAR:
1745            case TYPE_STATUS_BAR_PANEL:
1746            case TYPE_STATUS_BAR_SUB_PANEL:
1747            case TYPE_SYSTEM_DIALOG:
1748            case TYPE_VOLUME_OVERLAY:
1749            case TYPE_PRIVATE_PRESENTATION:
1750                break;
1751        }
1752
1753        // Check if third party app has set window to system window type.
1754        return mContext.checkCallingOrSelfPermission(
1755                android.Manifest.permission.INTERNAL_SYSTEM_WINDOW)
1756                        != PackageManager.PERMISSION_GRANTED;
1757    }
1758
1759    @Override
1760    public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
1761        switch (attrs.type) {
1762            case TYPE_SYSTEM_OVERLAY:
1763            case TYPE_SECURE_SYSTEM_OVERLAY:
1764                // These types of windows can't receive input events.
1765                attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
1766                        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
1767                attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
1768                break;
1769            case TYPE_STATUS_BAR:
1770
1771                // If the Keyguard is in a hidden state (occluded by another window), we force to
1772                // remove the wallpaper and keyguard flag so that any change in-flight after setting
1773                // the keyguard as occluded wouldn't set these flags again.
1774                // See {@link #processKeyguardSetHiddenResultLw}.
1775                if (mKeyguardHidden) {
1776                    attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
1777                    attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
1778                }
1779                break;
1780        }
1781
1782        if (attrs.type != TYPE_STATUS_BAR) {
1783            // The status bar is the only window allowed to exhibit keyguard behavior.
1784            attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
1785        }
1786
1787        if (ActivityManager.isHighEndGfx()
1788                && (attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
1789            attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
1790                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
1791        }
1792    }
1793
1794    void readLidState() {
1795        mLidState = mWindowManagerFuncs.getLidState();
1796    }
1797
1798    private void readCameraLensCoverState() {
1799        mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState();
1800    }
1801
1802    private boolean isHidden(int accessibilityMode) {
1803        switch (accessibilityMode) {
1804            case 1:
1805                return mLidState == LID_CLOSED;
1806            case 2:
1807                return mLidState == LID_OPEN;
1808            default:
1809                return false;
1810        }
1811    }
1812
1813    /** {@inheritDoc} */
1814    @Override
1815    public void adjustConfigurationLw(Configuration config, int keyboardPresence,
1816            int navigationPresence) {
1817        mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0;
1818
1819        readConfigurationDependentBehaviors();
1820        readLidState();
1821        applyLidSwitchState();
1822
1823        if (config.keyboard == Configuration.KEYBOARD_NOKEYS
1824                || (keyboardPresence == PRESENCE_INTERNAL
1825                        && isHidden(mLidKeyboardAccessibility))) {
1826            config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
1827            if (!mHasSoftInput) {
1828                config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
1829            }
1830        }
1831
1832        if (config.navigation == Configuration.NAVIGATION_NONAV
1833                || (navigationPresence == PRESENCE_INTERNAL
1834                        && isHidden(mLidNavigationAccessibility))) {
1835            config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
1836        }
1837    }
1838
1839    /** {@inheritDoc} */
1840    @Override
1841    public int windowTypeToLayerLw(int type) {
1842        if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
1843            return 2;
1844        }
1845        switch (type) {
1846        case TYPE_PRIVATE_PRESENTATION:
1847            return 2;
1848        case TYPE_WALLPAPER:
1849            // wallpaper is at the bottom, though the window manager may move it.
1850            return 2;
1851        case TYPE_PHONE:
1852            return 3;
1853        case TYPE_SEARCH_BAR:
1854            return 4;
1855        case TYPE_VOICE_INTERACTION:
1856            // voice interaction layer is almost immediately above apps.
1857            return 5;
1858        case TYPE_SYSTEM_DIALOG:
1859            return 6;
1860        case TYPE_TOAST:
1861            // toasts and the plugged-in battery thing
1862            return 7;
1863        case TYPE_PRIORITY_PHONE:
1864            // SIM errors and unlock.  Not sure if this really should be in a high layer.
1865            return 8;
1866        case TYPE_DREAM:
1867            // used for Dreams (screensavers with TYPE_DREAM windows)
1868            return 9;
1869        case TYPE_SYSTEM_ALERT:
1870            // like the ANR / app crashed dialogs
1871            return 10;
1872        case TYPE_INPUT_METHOD:
1873            // on-screen keyboards and other such input method user interfaces go here.
1874            return 11;
1875        case TYPE_INPUT_METHOD_DIALOG:
1876            // on-screen keyboards and other such input method user interfaces go here.
1877            return 12;
1878        case TYPE_KEYGUARD_SCRIM:
1879            // the safety window that shows behind keyguard while keyguard is starting
1880            return 13;
1881        case TYPE_STATUS_BAR_SUB_PANEL:
1882            return 14;
1883        case TYPE_STATUS_BAR:
1884            return 15;
1885        case TYPE_STATUS_BAR_PANEL:
1886            return 16;
1887        case TYPE_KEYGUARD_DIALOG:
1888            return 17;
1889        case TYPE_VOLUME_OVERLAY:
1890            // the on-screen volume indicator and controller shown when the user
1891            // changes the device volume
1892            return 18;
1893        case TYPE_SYSTEM_OVERLAY:
1894            // the on-screen volume indicator and controller shown when the user
1895            // changes the device volume
1896            return 19;
1897        case TYPE_NAVIGATION_BAR:
1898            // the navigation bar, if available, shows atop most things
1899            return 20;
1900        case TYPE_NAVIGATION_BAR_PANEL:
1901            // some panels (e.g. search) need to show on top of the navigation bar
1902            return 21;
1903        case TYPE_SYSTEM_ERROR:
1904            // system-level error dialogs
1905            return 22;
1906        case TYPE_MAGNIFICATION_OVERLAY:
1907            // used to highlight the magnified portion of a display
1908            return 23;
1909        case TYPE_DISPLAY_OVERLAY:
1910            // used to simulate secondary display devices
1911            return 24;
1912        case TYPE_DRAG:
1913            // the drag layer: input for drag-and-drop is associated with this window,
1914            // which sits above all other focusable windows
1915            return 25;
1916        case TYPE_ACCESSIBILITY_OVERLAY:
1917            // overlay put by accessibility services to intercept user interaction
1918            return 26;
1919        case TYPE_SECURE_SYSTEM_OVERLAY:
1920            return 27;
1921        case TYPE_BOOT_PROGRESS:
1922            return 28;
1923        case TYPE_POINTER:
1924            // the (mouse) pointer layer
1925            return 29;
1926        case TYPE_HIDDEN_NAV_CONSUMER:
1927            return 30;
1928        }
1929        Log.e(TAG, "Unknown window type: " + type);
1930        return 2;
1931    }
1932
1933    /** {@inheritDoc} */
1934    @Override
1935    public int subWindowTypeToLayerLw(int type) {
1936        switch (type) {
1937        case TYPE_APPLICATION_PANEL:
1938        case TYPE_APPLICATION_ATTACHED_DIALOG:
1939            return APPLICATION_PANEL_SUBLAYER;
1940        case TYPE_APPLICATION_MEDIA:
1941            return APPLICATION_MEDIA_SUBLAYER;
1942        case TYPE_APPLICATION_MEDIA_OVERLAY:
1943            return APPLICATION_MEDIA_OVERLAY_SUBLAYER;
1944        case TYPE_APPLICATION_SUB_PANEL:
1945            return APPLICATION_SUB_PANEL_SUBLAYER;
1946        }
1947        Log.e(TAG, "Unknown sub-window type: " + type);
1948        return 0;
1949    }
1950
1951    @Override
1952    public int getMaxWallpaperLayer() {
1953        return windowTypeToLayerLw(TYPE_STATUS_BAR);
1954    }
1955
1956    @Override
1957    public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation) {
1958        if (mHasNavigationBar) {
1959            // For a basic navigation bar, when we are in landscape mode we place
1960            // the navigation bar to the side.
1961            if (mNavigationBarCanMove && fullWidth > fullHeight) {
1962                return fullWidth - mNavigationBarWidthForRotation[rotation];
1963            }
1964        }
1965        return fullWidth;
1966    }
1967
1968    @Override
1969    public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation) {
1970        if (mHasNavigationBar) {
1971            // For a basic navigation bar, when we are in portrait mode we place
1972            // the navigation bar to the bottom.
1973            if (!mNavigationBarCanMove || fullWidth < fullHeight) {
1974                return fullHeight - mNavigationBarHeightForRotation[rotation];
1975            }
1976        }
1977        return fullHeight;
1978    }
1979
1980    @Override
1981    public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation) {
1982        return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation);
1983    }
1984
1985    @Override
1986    public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation) {
1987        // There is a separate status bar at the top of the display.  We don't count that as part
1988        // of the fixed decor, since it can hide; however, for purposes of configurations,
1989        // we do want to exclude it since applications can't generally use that part
1990        // of the screen.
1991        return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation) - mStatusBarHeight;
1992    }
1993
1994    @Override
1995    public boolean isForceHiding(WindowManager.LayoutParams attrs) {
1996        return (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
1997                (isKeyguardHostWindow(attrs) &&
1998                        (mKeyguardDelegate != null && mKeyguardDelegate.isShowing())) ||
1999                (attrs.type == TYPE_KEYGUARD_SCRIM);
2000    }
2001
2002    @Override
2003    public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) {
2004        return attrs.type == TYPE_STATUS_BAR;
2005    }
2006
2007    @Override
2008    public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
2009        switch (attrs.type) {
2010            case TYPE_STATUS_BAR:
2011            case TYPE_NAVIGATION_BAR:
2012            case TYPE_WALLPAPER:
2013            case TYPE_DREAM:
2014            case TYPE_KEYGUARD_SCRIM:
2015                return false;
2016            default:
2017                return true;
2018        }
2019    }
2020
2021    @Override
2022    public WindowState getWinShowWhenLockedLw() {
2023        return mWinShowWhenLocked;
2024    }
2025
2026    /** {@inheritDoc} */
2027    @Override
2028    public View addStartingWindow(IBinder appToken, String packageName, int theme,
2029            CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
2030            int icon, int logo, int windowFlags) {
2031        if (!SHOW_STARTING_ANIMATIONS) {
2032            return null;
2033        }
2034        if (packageName == null) {
2035            return null;
2036        }
2037
2038        WindowManager wm = null;
2039        View view = null;
2040
2041        try {
2042            Context context = mContext;
2043            if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow " + packageName
2044                    + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
2045                    + Integer.toHexString(theme));
2046            if (theme != context.getThemeResId() || labelRes != 0) {
2047                try {
2048                    context = context.createPackageContext(packageName, 0);
2049                    context.setTheme(theme);
2050                } catch (PackageManager.NameNotFoundException e) {
2051                    // Ignore
2052                }
2053            }
2054
2055            Window win = new PhoneWindow(context);
2056            final TypedArray ta = win.getWindowStyle();
2057            if (ta.getBoolean(
2058                        com.android.internal.R.styleable.Window_windowDisablePreview, false)
2059                || ta.getBoolean(
2060                        com.android.internal.R.styleable.Window_windowShowWallpaper,false)) {
2061                return null;
2062            }
2063
2064            Resources r = context.getResources();
2065            win.setTitle(r.getText(labelRes, nonLocalizedLabel));
2066
2067            win.setType(
2068                WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
2069            // Force the window flags: this is a fake window, so it is not really
2070            // touchable or focusable by the user.  We also add in the ALT_FOCUSABLE_IM
2071            // flag because we do know that the next window will take input
2072            // focus, so we want to get the IME window up on top of us right away.
2073            win.setFlags(
2074                windowFlags|
2075                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2076                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2077                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
2078                windowFlags|
2079                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2080                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2081                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
2082
2083            win.setDefaultIcon(icon);
2084            win.setDefaultLogo(logo);
2085
2086            win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
2087                    WindowManager.LayoutParams.MATCH_PARENT);
2088
2089            final WindowManager.LayoutParams params = win.getAttributes();
2090            params.token = appToken;
2091            params.packageName = packageName;
2092            params.windowAnimations = win.getWindowStyle().getResourceId(
2093                    com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
2094            params.privateFlags |=
2095                    WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
2096            params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
2097
2098            if (!compatInfo.supportsScreen()) {
2099                params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
2100            }
2101
2102            params.setTitle("Starting " + packageName);
2103
2104            wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
2105            view = win.getDecorView();
2106
2107            if (win.isFloating()) {
2108                // Whoops, there is no way to display an animation/preview
2109                // of such a thing!  After all that work...  let's skip it.
2110                // (Note that we must do this here because it is in
2111                // getDecorView() where the theme is evaluated...  maybe
2112                // we should peek the floating attribute from the theme
2113                // earlier.)
2114                return null;
2115            }
2116
2117            if (DEBUG_STARTING_WINDOW) Slog.d(
2118                TAG, "Adding starting window for " + packageName
2119                + " / " + appToken + ": "
2120                + (view.getParent() != null ? view : null));
2121
2122            wm.addView(view, params);
2123
2124            // Only return the view if it was successfully added to the
2125            // window manager... which we can tell by it having a parent.
2126            return view.getParent() != null ? view : null;
2127        } catch (WindowManager.BadTokenException e) {
2128            // ignore
2129            Log.w(TAG, appToken + " already running, starting window not displayed. " +
2130                    e.getMessage());
2131        } catch (RuntimeException e) {
2132            // don't crash if something else bad happens, for example a
2133            // failure loading resources because we are loading from an app
2134            // on external storage that has been unmounted.
2135            Log.w(TAG, appToken + " failed creating starting window", e);
2136        } finally {
2137            if (view != null && view.getParent() == null) {
2138                Log.w(TAG, "view not successfully added to wm, removing view");
2139                wm.removeViewImmediate(view);
2140            }
2141        }
2142
2143        return null;
2144    }
2145
2146    /** {@inheritDoc} */
2147    @Override
2148    public void removeStartingWindow(IBinder appToken, View window) {
2149        if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Removing starting window for " + appToken + ": "
2150                + window + " Callers=" + Debug.getCallers(4));
2151
2152        if (window != null) {
2153            WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
2154            wm.removeView(window);
2155        }
2156    }
2157
2158    /**
2159     * Preflight adding a window to the system.
2160     *
2161     * Currently enforces that three window types are singletons:
2162     * <ul>
2163     * <li>STATUS_BAR_TYPE</li>
2164     * <li>KEYGUARD_TYPE</li>
2165     * </ul>
2166     *
2167     * @param win The window to be added
2168     * @param attrs Information about the window to be added
2169     *
2170     * @return If ok, WindowManagerImpl.ADD_OKAY.  If too many singletons,
2171     * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
2172     */
2173    @Override
2174    public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
2175        switch (attrs.type) {
2176            case TYPE_STATUS_BAR:
2177                mContext.enforceCallingOrSelfPermission(
2178                        android.Manifest.permission.STATUS_BAR_SERVICE,
2179                        "PhoneWindowManager");
2180                if (mStatusBar != null) {
2181                    if (mStatusBar.isAlive()) {
2182                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2183                    }
2184                }
2185                mStatusBar = win;
2186                mStatusBarController.setWindow(win);
2187                break;
2188            case TYPE_NAVIGATION_BAR:
2189                mContext.enforceCallingOrSelfPermission(
2190                        android.Manifest.permission.STATUS_BAR_SERVICE,
2191                        "PhoneWindowManager");
2192                if (mNavigationBar != null) {
2193                    if (mNavigationBar.isAlive()) {
2194                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2195                    }
2196                }
2197                mNavigationBar = win;
2198                mNavigationBarController.setWindow(win);
2199                if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
2200                break;
2201            case TYPE_NAVIGATION_BAR_PANEL:
2202                mContext.enforceCallingOrSelfPermission(
2203                        android.Manifest.permission.STATUS_BAR_SERVICE,
2204                        "PhoneWindowManager");
2205                break;
2206            case TYPE_STATUS_BAR_PANEL:
2207                mContext.enforceCallingOrSelfPermission(
2208                        android.Manifest.permission.STATUS_BAR_SERVICE,
2209                        "PhoneWindowManager");
2210                break;
2211            case TYPE_STATUS_BAR_SUB_PANEL:
2212                mContext.enforceCallingOrSelfPermission(
2213                        android.Manifest.permission.STATUS_BAR_SERVICE,
2214                        "PhoneWindowManager");
2215                break;
2216            case TYPE_KEYGUARD_SCRIM:
2217                if (mKeyguardScrim != null) {
2218                    return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2219                }
2220                mKeyguardScrim = win;
2221                break;
2222        }
2223        return WindowManagerGlobal.ADD_OKAY;
2224    }
2225
2226    /** {@inheritDoc} */
2227    @Override
2228    public void removeWindowLw(WindowState win) {
2229        if (mStatusBar == win) {
2230            mStatusBar = null;
2231            mStatusBarController.setWindow(null);
2232            mKeyguardDelegate.showScrim();
2233        } else if (mKeyguardScrim == win) {
2234            Log.v(TAG, "Removing keyguard scrim");
2235            mKeyguardScrim = null;
2236        } if (mNavigationBar == win) {
2237            mNavigationBar = null;
2238            mNavigationBarController.setWindow(null);
2239        }
2240    }
2241
2242    static final boolean PRINT_ANIM = false;
2243
2244    /** {@inheritDoc} */
2245    @Override
2246    public int selectAnimationLw(WindowState win, int transit) {
2247        if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
2248              + ": transit=" + transit);
2249        if (win == mStatusBar) {
2250            boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
2251            if (transit == TRANSIT_EXIT
2252                    || transit == TRANSIT_HIDE) {
2253                return isKeyguard ? -1 : R.anim.dock_top_exit;
2254            } else if (transit == TRANSIT_ENTER
2255                    || transit == TRANSIT_SHOW) {
2256                return isKeyguard ? -1 : R.anim.dock_top_enter;
2257            }
2258        } else if (win == mNavigationBar) {
2259            // This can be on either the bottom or the right.
2260            if (mNavigationBarOnBottom) {
2261                if (transit == TRANSIT_EXIT
2262                        || transit == TRANSIT_HIDE) {
2263                    return R.anim.dock_bottom_exit;
2264                } else if (transit == TRANSIT_ENTER
2265                        || transit == TRANSIT_SHOW) {
2266                    return R.anim.dock_bottom_enter;
2267                }
2268            } else {
2269                if (transit == TRANSIT_EXIT
2270                        || transit == TRANSIT_HIDE) {
2271                    return R.anim.dock_right_exit;
2272                } else if (transit == TRANSIT_ENTER
2273                        || transit == TRANSIT_SHOW) {
2274                    return R.anim.dock_right_enter;
2275                }
2276            }
2277        }
2278
2279        if (transit == TRANSIT_PREVIEW_DONE) {
2280            if (win.hasAppShownWindows()) {
2281                if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
2282                return com.android.internal.R.anim.app_starting_exit;
2283            }
2284        } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
2285                && transit == TRANSIT_ENTER) {
2286            // Special case: we are animating in a dream, while the keyguard
2287            // is shown.  We don't want an animation on the dream, because
2288            // we need it shown immediately with the keyguard animating away
2289            // to reveal it.
2290            return -1;
2291        }
2292
2293        return 0;
2294    }
2295
2296    @Override
2297    public void selectRotationAnimationLw(int anim[]) {
2298        if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
2299                + mTopFullscreenOpaqueWindowState + " rotationAnimation="
2300                + (mTopFullscreenOpaqueWindowState == null ?
2301                        "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation));
2302        if (mTopFullscreenOpaqueWindowState != null && mTopIsFullscreen) {
2303            switch (mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation) {
2304                case ROTATION_ANIMATION_CROSSFADE:
2305                    anim[0] = R.anim.rotation_animation_xfade_exit;
2306                    anim[1] = R.anim.rotation_animation_enter;
2307                    break;
2308                case ROTATION_ANIMATION_JUMPCUT:
2309                    anim[0] = R.anim.rotation_animation_jump_exit;
2310                    anim[1] = R.anim.rotation_animation_enter;
2311                    break;
2312                case ROTATION_ANIMATION_ROTATE:
2313                default:
2314                    anim[0] = anim[1] = 0;
2315                    break;
2316            }
2317        } else {
2318            anim[0] = anim[1] = 0;
2319        }
2320    }
2321
2322    @Override
2323    public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId,
2324            boolean forceDefault) {
2325        switch (exitAnimId) {
2326            case R.anim.rotation_animation_xfade_exit:
2327            case R.anim.rotation_animation_jump_exit:
2328                // These are the only cases that matter.
2329                if (forceDefault) {
2330                    return false;
2331                }
2332                int anim[] = new int[2];
2333                selectRotationAnimationLw(anim);
2334                return (exitAnimId == anim[0] && enterAnimId == anim[1]);
2335            default:
2336                return true;
2337        }
2338    }
2339
2340    @Override
2341    public Animation createForceHideEnterAnimation(boolean onWallpaper,
2342            boolean goingToNotificationShade) {
2343        if (goingToNotificationShade) {
2344            return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
2345        }
2346
2347        AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ?
2348                    R.anim.lock_screen_behind_enter_wallpaper :
2349                    R.anim.lock_screen_behind_enter);
2350
2351        // TODO: Use XML interpolators when we have log interpolators available in XML.
2352        final List<Animation> animations = set.getAnimations();
2353        for (int i = animations.size() - 1; i >= 0; --i) {
2354            animations.get(i).setInterpolator(mLogDecelerateInterpolator);
2355        }
2356
2357        return set;
2358    }
2359
2360
2361    @Override
2362    public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade) {
2363        if (goingToNotificationShade) {
2364            return null;
2365        } else {
2366            return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
2367        }
2368    }
2369
2370    private static void awakenDreams() {
2371        IDreamManager dreamManager = getDreamManager();
2372        if (dreamManager != null) {
2373            try {
2374                dreamManager.awaken();
2375            } catch (RemoteException e) {
2376                // fine, stay asleep then
2377            }
2378        }
2379    }
2380
2381    static IDreamManager getDreamManager() {
2382        return IDreamManager.Stub.asInterface(
2383                ServiceManager.checkService(DreamService.DREAM_SERVICE));
2384    }
2385
2386    TelecomManager getTelecommService() {
2387        return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
2388    }
2389
2390    static IAudioService getAudioService() {
2391        IAudioService audioService = IAudioService.Stub.asInterface(
2392                ServiceManager.checkService(Context.AUDIO_SERVICE));
2393        if (audioService == null) {
2394            Log.w(TAG, "Unable to find IAudioService interface.");
2395        }
2396        return audioService;
2397    }
2398
2399    boolean keyguardOn() {
2400        return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode();
2401    }
2402
2403    private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
2404            WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
2405            WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
2406        };
2407
2408    /** {@inheritDoc} */
2409    @Override
2410    public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
2411        final boolean keyguardOn = keyguardOn();
2412        final int keyCode = event.getKeyCode();
2413        final int repeatCount = event.getRepeatCount();
2414        final int metaState = event.getMetaState();
2415        final int flags = event.getFlags();
2416        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
2417        final boolean canceled = event.isCanceled();
2418
2419        if (DEBUG_INPUT) {
2420            Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
2421                    + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
2422                    + " canceled=" + canceled);
2423        }
2424
2425        // If we think we might have a volume down & power key chord on the way
2426        // but we're not sure, then tell the dispatcher to wait a little while and
2427        // try again later before dispatching.
2428        if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
2429            if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
2430                final long now = SystemClock.uptimeMillis();
2431                final long timeoutTime = mScreenshotChordVolumeDownKeyTime
2432                        + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
2433                if (now < timeoutTime) {
2434                    return timeoutTime - now;
2435                }
2436            }
2437            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
2438                    && mScreenshotChordVolumeDownKeyConsumed) {
2439                if (!down) {
2440                    mScreenshotChordVolumeDownKeyConsumed = false;
2441                }
2442                return -1;
2443            }
2444        }
2445
2446        // Cancel any pending meta actions if we see any other keys being pressed between the down
2447        // of the meta key and its corresponding up.
2448        if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
2449            mPendingMetaAction = false;
2450        }
2451
2452        // First we always handle the home key here, so applications
2453        // can never break it, although if keyguard is on, we do let
2454        // it handle it, because that gives us the correct 5 second
2455        // timeout.
2456        if (keyCode == KeyEvent.KEYCODE_HOME) {
2457
2458            // If we have released the home key, and didn't do anything else
2459            // while it was pressed, then it is time to go home!
2460            if (!down) {
2461                cancelPreloadRecentApps();
2462
2463                mHomePressed = false;
2464                if (mHomeConsumed) {
2465                    mHomeConsumed = false;
2466                    return -1;
2467                }
2468
2469                if (canceled) {
2470                    Log.i(TAG, "Ignoring HOME; event canceled.");
2471                    return -1;
2472                }
2473
2474                // If an incoming call is ringing, HOME is totally disabled.
2475                // (The user is already on the InCallUI at this point,
2476                // and his ONLY options are to answer or reject the call.)
2477                TelecomManager telecomManager = getTelecommService();
2478                if (telecomManager != null && telecomManager.isRinging()) {
2479                    Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
2480                    return -1;
2481                }
2482
2483                // Delay handling home if a double-tap is possible.
2484                if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
2485                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
2486                    mHomeDoubleTapPending = true;
2487                    mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
2488                            ViewConfiguration.getDoubleTapTimeout());
2489                    return -1;
2490                }
2491
2492                handleShortPressOnHome();
2493                return -1;
2494            }
2495
2496            // If a system window has focus, then it doesn't make sense
2497            // right now to interact with applications.
2498            WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
2499            if (attrs != null) {
2500                final int type = attrs.type;
2501                if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM
2502                        || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
2503                        || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
2504                    // the "app" is keyguard, so give it the key
2505                    return 0;
2506                }
2507                final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
2508                for (int i=0; i<typeCount; i++) {
2509                    if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
2510                        // don't do anything, but also don't pass it to the app
2511                        return -1;
2512                    }
2513                }
2514            }
2515
2516            // Remember that home is pressed and handle special actions.
2517            if (repeatCount == 0) {
2518                mHomePressed = true;
2519                if (mHomeDoubleTapPending) {
2520                    mHomeDoubleTapPending = false;
2521                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
2522                    handleDoubleTapOnHome();
2523                } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI
2524                        || mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
2525                    preloadRecentApps();
2526                }
2527            } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
2528                if (!keyguardOn) {
2529                    handleLongPressOnHome();
2530                }
2531            }
2532            return -1;
2533        } else if (keyCode == KeyEvent.KEYCODE_MENU) {
2534            // Hijack modified menu keys for debugging features
2535            final int chordBug = KeyEvent.META_SHIFT_ON;
2536
2537            if (down && repeatCount == 0) {
2538                if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
2539                    Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
2540                    mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
2541                            null, null, null, 0, null, null);
2542                    return -1;
2543                } else if (SHOW_PROCESSES_ON_ALT_MENU &&
2544                        (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
2545                    Intent service = new Intent();
2546                    service.setClassName(mContext, "com.android.server.LoadAverageService");
2547                    ContentResolver res = mContext.getContentResolver();
2548                    boolean shown = Settings.Global.getInt(
2549                            res, Settings.Global.SHOW_PROCESSES, 0) != 0;
2550                    if (!shown) {
2551                        mContext.startService(service);
2552                    } else {
2553                        mContext.stopService(service);
2554                    }
2555                    Settings.Global.putInt(
2556                            res, Settings.Global.SHOW_PROCESSES, shown ? 0 : 1);
2557                    return -1;
2558                }
2559            }
2560        } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
2561            if (down) {
2562                if (repeatCount == 0) {
2563                    mSearchKeyShortcutPending = true;
2564                    mConsumeSearchKeyUp = false;
2565                }
2566            } else {
2567                mSearchKeyShortcutPending = false;
2568                if (mConsumeSearchKeyUp) {
2569                    mConsumeSearchKeyUp = false;
2570                    return -1;
2571                }
2572            }
2573            return 0;
2574        } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
2575            if (!keyguardOn) {
2576                if (down && repeatCount == 0) {
2577                    preloadRecentApps();
2578                } else if (!down) {
2579                    toggleRecentApps();
2580                }
2581            }
2582            return -1;
2583        } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
2584            if (down) {
2585                if (repeatCount == 0) {
2586                    mAssistKeyLongPressed = false;
2587                } else if (repeatCount == 1) {
2588                    mAssistKeyLongPressed = true;
2589                    if (!keyguardOn) {
2590                         launchAssistLongPressAction();
2591                    }
2592                }
2593            } else {
2594                if (mAssistKeyLongPressed) {
2595                    mAssistKeyLongPressed = false;
2596                } else {
2597                    if (!keyguardOn) {
2598                        launchAssistAction();
2599                    }
2600                }
2601            }
2602            return -1;
2603        } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
2604            if (!down) {
2605                Intent voiceIntent;
2606                if (!keyguardOn) {
2607                    voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
2608                } else {
2609                    voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
2610                    voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
2611                }
2612                mContext.startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
2613            }
2614        } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
2615            if (down && repeatCount == 0) {
2616                mHandler.post(mScreenshotRunnable);
2617            }
2618            return -1;
2619        } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP
2620                || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) {
2621            if (down) {
2622                int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
2623
2624                // Disable autobrightness if it's on
2625                int auto = Settings.System.getIntForUser(
2626                        mContext.getContentResolver(),
2627                        Settings.System.SCREEN_BRIGHTNESS_MODE,
2628                        Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
2629                        UserHandle.USER_CURRENT_OR_SELF);
2630                if (auto != 0) {
2631                    Settings.System.putIntForUser(mContext.getContentResolver(),
2632                            Settings.System.SCREEN_BRIGHTNESS_MODE,
2633                            Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
2634                            UserHandle.USER_CURRENT_OR_SELF);
2635                }
2636
2637                int min = mPowerManager.getMinimumScreenBrightnessSetting();
2638                int max = mPowerManager.getMaximumScreenBrightnessSetting();
2639                int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction;
2640                int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
2641                        Settings.System.SCREEN_BRIGHTNESS,
2642                        mPowerManager.getDefaultScreenBrightnessSetting(),
2643                        UserHandle.USER_CURRENT_OR_SELF);
2644                brightness += step;
2645                // Make sure we don't go beyond the limits.
2646                brightness = Math.min(max, brightness);
2647                brightness = Math.max(min, brightness);
2648
2649                Settings.System.putIntForUser(mContext.getContentResolver(),
2650                        Settings.System.SCREEN_BRIGHTNESS, brightness,
2651                        UserHandle.USER_CURRENT_OR_SELF);
2652                mContext.startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
2653                        UserHandle.CURRENT_OR_SELF);
2654            }
2655            return -1;
2656        } else if (KeyEvent.isMetaKey(keyCode)) {
2657            if (down) {
2658                mPendingMetaAction = true;
2659            } else if (mPendingMetaAction) {
2660                launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD);
2661            }
2662            return -1;
2663        }
2664
2665        // Shortcuts are invoked through Search+key, so intercept those here
2666        // Any printing key that is chorded with Search should be consumed
2667        // even if no shortcut was invoked.  This prevents text from being
2668        // inadvertently inserted when using a keyboard that has built-in macro
2669        // shortcut keys (that emit Search+x) and some of them are not registered.
2670        if (mSearchKeyShortcutPending) {
2671            final KeyCharacterMap kcm = event.getKeyCharacterMap();
2672            if (kcm.isPrintingKey(keyCode)) {
2673                mConsumeSearchKeyUp = true;
2674                mSearchKeyShortcutPending = false;
2675                if (down && repeatCount == 0 && !keyguardOn) {
2676                    Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
2677                    if (shortcutIntent != null) {
2678                        shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2679                        try {
2680                            mContext.startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
2681                        } catch (ActivityNotFoundException ex) {
2682                            Slog.w(TAG, "Dropping shortcut key combination because "
2683                                    + "the activity to which it is registered was not found: "
2684                                    + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);
2685                        }
2686                    } else {
2687                        Slog.i(TAG, "Dropping unregistered shortcut key combination: "
2688                                + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));
2689                    }
2690                }
2691                return -1;
2692            }
2693        }
2694
2695        // Invoke shortcuts using Meta.
2696        if (down && repeatCount == 0 && !keyguardOn
2697                && (metaState & KeyEvent.META_META_ON) != 0) {
2698            final KeyCharacterMap kcm = event.getKeyCharacterMap();
2699            if (kcm.isPrintingKey(keyCode)) {
2700                Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
2701                        metaState & ~(KeyEvent.META_META_ON
2702                                | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
2703                if (shortcutIntent != null) {
2704                    shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2705                    try {
2706                        mContext.startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
2707                    } catch (ActivityNotFoundException ex) {
2708                        Slog.w(TAG, "Dropping shortcut key combination because "
2709                                + "the activity to which it is registered was not found: "
2710                                + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
2711                    }
2712                    return -1;
2713                }
2714            }
2715        }
2716
2717        // Handle application launch keys.
2718        if (down && repeatCount == 0 && !keyguardOn) {
2719            String category = sApplicationLaunchKeyCategories.get(keyCode);
2720            if (category != null) {
2721                Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
2722                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2723                try {
2724                    mContext.startActivityAsUser(intent, UserHandle.CURRENT);
2725                } catch (ActivityNotFoundException ex) {
2726                    Slog.w(TAG, "Dropping application launch key because "
2727                            + "the activity to which it is registered was not found: "
2728                            + "keyCode=" + keyCode + ", category=" + category, ex);
2729                }
2730                return -1;
2731            }
2732        }
2733
2734        // Display task switcher for ALT-TAB.
2735        if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
2736            if (mRecentAppsHeldModifiers == 0 && !keyguardOn) {
2737                final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
2738                if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
2739                    mRecentAppsHeldModifiers = shiftlessModifiers;
2740                    showRecentApps(true);
2741                    return -1;
2742                }
2743            }
2744        } else if (!down && mRecentAppsHeldModifiers != 0
2745                && (metaState & mRecentAppsHeldModifiers) == 0) {
2746            mRecentAppsHeldModifiers = 0;
2747            hideRecentApps(true, false);
2748        }
2749
2750        // Handle keyboard language switching.
2751        if (down && repeatCount == 0
2752                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
2753                        || (keyCode == KeyEvent.KEYCODE_SPACE
2754                                && (metaState & KeyEvent.META_CTRL_MASK) != 0))) {
2755            int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
2756            mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
2757            return -1;
2758        }
2759        if (mLanguageSwitchKeyPressed && !down
2760                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
2761                        || keyCode == KeyEvent.KEYCODE_SPACE)) {
2762            mLanguageSwitchKeyPressed = false;
2763            return -1;
2764        }
2765
2766        if (isValidGlobalKey(keyCode)
2767                && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
2768            return -1;
2769        }
2770
2771        // Reserve all the META modifier combos for system behavior
2772        if ((metaState & KeyEvent.META_META_ON) != 0) {
2773            return -1;
2774        }
2775
2776        // Let the application handle the key.
2777        return 0;
2778    }
2779
2780    /** {@inheritDoc} */
2781    @Override
2782    public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
2783        // Note: This method is only called if the initial down was unhandled.
2784        if (DEBUG_INPUT) {
2785            Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
2786                    + ", flags=" + event.getFlags()
2787                    + ", keyCode=" + event.getKeyCode()
2788                    + ", scanCode=" + event.getScanCode()
2789                    + ", metaState=" + event.getMetaState()
2790                    + ", repeatCount=" + event.getRepeatCount()
2791                    + ", policyFlags=" + policyFlags);
2792        }
2793
2794        KeyEvent fallbackEvent = null;
2795        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
2796            final KeyCharacterMap kcm = event.getKeyCharacterMap();
2797            final int keyCode = event.getKeyCode();
2798            final int metaState = event.getMetaState();
2799            final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
2800                    && event.getRepeatCount() == 0;
2801
2802            // Check for fallback actions specified by the key character map.
2803            final FallbackAction fallbackAction;
2804            if (initialDown) {
2805                fallbackAction = kcm.getFallbackAction(keyCode, metaState);
2806            } else {
2807                fallbackAction = mFallbackActions.get(keyCode);
2808            }
2809
2810            if (fallbackAction != null) {
2811                if (DEBUG_INPUT) {
2812                    Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode
2813                            + " metaState=" + Integer.toHexString(fallbackAction.metaState));
2814                }
2815
2816                final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
2817                fallbackEvent = KeyEvent.obtain(
2818                        event.getDownTime(), event.getEventTime(),
2819                        event.getAction(), fallbackAction.keyCode,
2820                        event.getRepeatCount(), fallbackAction.metaState,
2821                        event.getDeviceId(), event.getScanCode(),
2822                        flags, event.getSource(), null);
2823
2824                if (!interceptFallback(win, fallbackEvent, policyFlags)) {
2825                    fallbackEvent.recycle();
2826                    fallbackEvent = null;
2827                }
2828
2829                if (initialDown) {
2830                    mFallbackActions.put(keyCode, fallbackAction);
2831                } else if (event.getAction() == KeyEvent.ACTION_UP) {
2832                    mFallbackActions.remove(keyCode);
2833                    fallbackAction.recycle();
2834                }
2835            }
2836        }
2837
2838        if (DEBUG_INPUT) {
2839            if (fallbackEvent == null) {
2840                Slog.d(TAG, "No fallback.");
2841            } else {
2842                Slog.d(TAG, "Performing fallback: " + fallbackEvent);
2843            }
2844        }
2845        return fallbackEvent;
2846    }
2847
2848    private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
2849        int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
2850        if ((actions & ACTION_PASS_TO_USER) != 0) {
2851            long delayMillis = interceptKeyBeforeDispatching(
2852                    win, fallbackEvent, policyFlags);
2853            if (delayMillis == 0) {
2854                return true;
2855            }
2856        }
2857        return false;
2858    }
2859
2860    private void launchAssistLongPressAction() {
2861        performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
2862        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
2863
2864        // launch the search activity
2865        Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
2866        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2867        try {
2868            // TODO: This only stops the factory-installed search manager.
2869            // Need to formalize an API to handle others
2870            SearchManager searchManager = getSearchManager();
2871            if (searchManager != null) {
2872                searchManager.stopSearch();
2873            }
2874            mContext.startActivityAsUser(intent, UserHandle.CURRENT);
2875        } catch (ActivityNotFoundException e) {
2876            Slog.w(TAG, "No activity to handle assist long press action.", e);
2877        }
2878    }
2879
2880    private void launchAssistAction() {
2881        launchAssistAction(null);
2882    }
2883
2884    private void launchAssistAction(String hint) {
2885        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
2886        Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
2887                .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
2888        if (intent != null) {
2889            if (hint != null) {
2890                intent.putExtra(hint, true);
2891            }
2892            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
2893                    | Intent.FLAG_ACTIVITY_SINGLE_TOP
2894                    | Intent.FLAG_ACTIVITY_CLEAR_TOP);
2895            try {
2896                mContext.startActivityAsUser(intent, UserHandle.CURRENT);
2897            } catch (ActivityNotFoundException e) {
2898                Slog.w(TAG, "No activity to handle assist action.", e);
2899            }
2900        }
2901    }
2902
2903    private SearchManager getSearchManager() {
2904        if (mSearchManager == null) {
2905            mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
2906        }
2907        return mSearchManager;
2908    }
2909
2910    private void preloadRecentApps() {
2911        mPreloadedRecentApps = true;
2912        try {
2913            IStatusBarService statusbar = getStatusBarService();
2914            if (statusbar != null) {
2915                statusbar.preloadRecentApps();
2916            }
2917        } catch (RemoteException e) {
2918            Slog.e(TAG, "RemoteException when preloading recent apps", e);
2919            // re-acquire status bar service next time it is needed.
2920            mStatusBarService = null;
2921        }
2922    }
2923
2924    private void cancelPreloadRecentApps() {
2925        if (mPreloadedRecentApps) {
2926            mPreloadedRecentApps = false;
2927            try {
2928                IStatusBarService statusbar = getStatusBarService();
2929                if (statusbar != null) {
2930                    statusbar.cancelPreloadRecentApps();
2931                }
2932            } catch (RemoteException e) {
2933                Slog.e(TAG, "RemoteException when cancelling recent apps preload", e);
2934                // re-acquire status bar service next time it is needed.
2935                mStatusBarService = null;
2936            }
2937        }
2938    }
2939
2940    private void toggleRecentApps() {
2941        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
2942        try {
2943            IStatusBarService statusbar = getStatusBarService();
2944            if (statusbar != null) {
2945                statusbar.toggleRecentApps();
2946            }
2947        } catch (RemoteException e) {
2948            Slog.e(TAG, "RemoteException when toggling recent apps", e);
2949            // re-acquire status bar service next time it is needed.
2950            mStatusBarService = null;
2951        }
2952    }
2953
2954    @Override
2955    public void showRecentApps() {
2956        mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
2957        mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_RECENTS);
2958    }
2959
2960    private void showRecentApps(boolean triggeredFromAltTab) {
2961        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
2962        try {
2963            IStatusBarService statusbar = getStatusBarService();
2964            if (statusbar != null) {
2965                statusbar.showRecentApps(triggeredFromAltTab);
2966            }
2967        } catch (RemoteException e) {
2968            Slog.e(TAG, "RemoteException when showing recent apps", e);
2969            // re-acquire status bar service next time it is needed.
2970            mStatusBarService = null;
2971        }
2972    }
2973
2974    private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
2975        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
2976        try {
2977            IStatusBarService statusbar = getStatusBarService();
2978            if (statusbar != null) {
2979                statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
2980            }
2981        } catch (RemoteException e) {
2982            Slog.e(TAG, "RemoteException when closing recent apps", e);
2983            // re-acquire status bar service next time it is needed.
2984            mStatusBarService = null;
2985        }
2986    }
2987
2988    /**
2989     * A home key -> launch home action was detected.  Take the appropriate action
2990     * given the situation with the keyguard.
2991     */
2992    void launchHomeFromHotKey() {
2993        if (isKeyguardShowingAndNotOccluded()) {
2994            // don't launch home if keyguard showing
2995        } else if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) {
2996            // when in keyguard restricted mode, must first verify unlock
2997            // before launching home
2998            mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
2999                @Override
3000                public void onKeyguardExitResult(boolean success) {
3001                    if (success) {
3002                        try {
3003                            ActivityManagerNative.getDefault().stopAppSwitches();
3004                        } catch (RemoteException e) {
3005                        }
3006                        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
3007                        startDockOrHome(true /*fromHomeKey*/);
3008                    }
3009                }
3010            });
3011        } else {
3012            // no keyguard stuff to worry about, just launch home!
3013            try {
3014                ActivityManagerNative.getDefault().stopAppSwitches();
3015            } catch (RemoteException e) {
3016            }
3017            if (mRecentsVisible) {
3018                // Hide Recents and notify it to launch Home
3019                awakenDreams();
3020                sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
3021                hideRecentApps(false, true);
3022            } else {
3023                // Otherwise, just launch Home
3024                sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
3025                startDockOrHome(true /*fromHomeKey*/);
3026            }
3027        }
3028    }
3029
3030    private final Runnable mClearHideNavigationFlag = new Runnable() {
3031        @Override
3032        public void run() {
3033            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
3034                // Clear flags.
3035                mForceClearedSystemUiFlags &=
3036                        ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
3037            }
3038            mWindowManagerFuncs.reevaluateStatusBarVisibility();
3039        }
3040    };
3041
3042    /**
3043     * Input handler used while nav bar is hidden.  Captures any touch on the screen,
3044     * to determine when the nav bar should be shown and prevent applications from
3045     * receiving those touches.
3046     */
3047    final class HideNavInputEventReceiver extends InputEventReceiver {
3048        public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
3049            super(inputChannel, looper);
3050        }
3051
3052        @Override
3053        public void onInputEvent(InputEvent event) {
3054            boolean handled = false;
3055            try {
3056                if (event instanceof MotionEvent
3057                        && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
3058                    final MotionEvent motionEvent = (MotionEvent)event;
3059                    if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
3060                        // When the user taps down, we re-show the nav bar.
3061                        boolean changed = false;
3062                        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
3063                            // Any user activity always causes us to show the
3064                            // navigation controls, if they had been hidden.
3065                            // We also clear the low profile and only content
3066                            // flags so that tapping on the screen will atomically
3067                            // restore all currently hidden screen decorations.
3068                            int newVal = mResettingSystemUiFlags |
3069                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
3070                                    View.SYSTEM_UI_FLAG_LOW_PROFILE |
3071                                    View.SYSTEM_UI_FLAG_FULLSCREEN;
3072                            if (mResettingSystemUiFlags != newVal) {
3073                                mResettingSystemUiFlags = newVal;
3074                                changed = true;
3075                            }
3076                            // We don't allow the system's nav bar to be hidden
3077                            // again for 1 second, to prevent applications from
3078                            // spamming us and keeping it from being shown.
3079                            newVal = mForceClearedSystemUiFlags |
3080                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
3081                            if (mForceClearedSystemUiFlags != newVal) {
3082                                mForceClearedSystemUiFlags = newVal;
3083                                changed = true;
3084                                mHandler.postDelayed(mClearHideNavigationFlag, 1000);
3085                            }
3086                        }
3087                        if (changed) {
3088                            mWindowManagerFuncs.reevaluateStatusBarVisibility();
3089                        }
3090                    }
3091                }
3092            } finally {
3093                finishInputEvent(event, handled);
3094            }
3095        }
3096    }
3097    final InputEventReceiver.Factory mHideNavInputEventReceiverFactory =
3098            new InputEventReceiver.Factory() {
3099        @Override
3100        public InputEventReceiver createInputEventReceiver(
3101                InputChannel inputChannel, Looper looper) {
3102            return new HideNavInputEventReceiver(inputChannel, looper);
3103        }
3104    };
3105
3106    @Override
3107    public int adjustSystemUiVisibilityLw(int visibility) {
3108        mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
3109        mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
3110        mRecentsVisible = (visibility & View.RECENT_APPS_VISIBLE) > 0;
3111
3112        // Reset any bits in mForceClearingStatusBarVisibility that
3113        // are now clear.
3114        mResettingSystemUiFlags &= visibility;
3115        // Clear any bits in the new visibility that are currently being
3116        // force cleared, before reporting it.
3117        return visibility & ~mResettingSystemUiFlags
3118                & ~mForceClearedSystemUiFlags;
3119    }
3120
3121    @Override
3122    public void getInsetHintLw(WindowManager.LayoutParams attrs, Rect outContentInsets,
3123            Rect outStableInsets) {
3124        final int fl = PolicyControl.getWindowFlags(null, attrs);
3125        final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
3126        final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
3127
3128        if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
3129                == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
3130            int availRight, availBottom;
3131            if (canHideNavigationBar() &&
3132                    (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
3133                availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
3134                availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
3135            } else {
3136                availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
3137                availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
3138            }
3139            if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
3140                if ((fl & FLAG_FULLSCREEN) != 0) {
3141                    outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop,
3142                            availRight - mStableFullscreenRight,
3143                            availBottom - mStableFullscreenBottom);
3144                } else {
3145                    outContentInsets.set(mStableLeft, mStableTop,
3146                            availRight - mStableRight, availBottom - mStableBottom);
3147                }
3148            } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
3149                outContentInsets.setEmpty();
3150            } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
3151                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
3152                outContentInsets.set(mCurLeft, mCurTop,
3153                        availRight - mCurRight, availBottom - mCurBottom);
3154            } else {
3155                outContentInsets.set(mCurLeft, mCurTop,
3156                        availRight - mCurRight, availBottom - mCurBottom);
3157            }
3158
3159            outStableInsets.set(mStableLeft, mStableTop,
3160                    availRight - mStableRight, availBottom - mStableBottom);
3161            return;
3162        }
3163        outContentInsets.setEmpty();
3164        outStableInsets.setEmpty();
3165    }
3166
3167    /** {@inheritDoc} */
3168    @Override
3169    public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
3170                              int displayRotation) {
3171        final int overscanLeft, overscanTop, overscanRight, overscanBottom;
3172        if (isDefaultDisplay) {
3173            switch (displayRotation) {
3174                case Surface.ROTATION_90:
3175                    overscanLeft = mOverscanTop;
3176                    overscanTop = mOverscanRight;
3177                    overscanRight = mOverscanBottom;
3178                    overscanBottom = mOverscanLeft;
3179                    break;
3180                case Surface.ROTATION_180:
3181                    overscanLeft = mOverscanRight;
3182                    overscanTop = mOverscanBottom;
3183                    overscanRight = mOverscanLeft;
3184                    overscanBottom = mOverscanTop;
3185                    break;
3186                case Surface.ROTATION_270:
3187                    overscanLeft = mOverscanBottom;
3188                    overscanTop = mOverscanLeft;
3189                    overscanRight = mOverscanTop;
3190                    overscanBottom = mOverscanRight;
3191                    break;
3192                default:
3193                    overscanLeft = mOverscanLeft;
3194                    overscanTop = mOverscanTop;
3195                    overscanRight = mOverscanRight;
3196                    overscanBottom = mOverscanBottom;
3197                    break;
3198            }
3199        } else {
3200            overscanLeft = 0;
3201            overscanTop = 0;
3202            overscanRight = 0;
3203            overscanBottom = 0;
3204        }
3205        mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0;
3206        mOverscanScreenTop = mRestrictedOverscanScreenTop = 0;
3207        mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth;
3208        mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight;
3209        mSystemLeft = 0;
3210        mSystemTop = 0;
3211        mSystemRight = displayWidth;
3212        mSystemBottom = displayHeight;
3213        mUnrestrictedScreenLeft = overscanLeft;
3214        mUnrestrictedScreenTop = overscanTop;
3215        mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight;
3216        mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom;
3217        mRestrictedScreenLeft = mUnrestrictedScreenLeft;
3218        mRestrictedScreenTop = mUnrestrictedScreenTop;
3219        mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth;
3220        mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight;
3221        mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft
3222                = mCurLeft = mUnrestrictedScreenLeft;
3223        mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop
3224                = mCurTop = mUnrestrictedScreenTop;
3225        mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight
3226                = mCurRight = displayWidth - overscanRight;
3227        mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom
3228                = mCurBottom = displayHeight - overscanBottom;
3229        mDockLayer = 0x10000000;
3230        mStatusBarLayer = -1;
3231
3232        // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
3233        final Rect pf = mTmpParentFrame;
3234        final Rect df = mTmpDisplayFrame;
3235        final Rect of = mTmpOverscanFrame;
3236        final Rect vf = mTmpVisibleFrame;
3237        final Rect dcf = mTmpDecorFrame;
3238        pf.left = df.left = of.left = vf.left = mDockLeft;
3239        pf.top = df.top = of.top = vf.top = mDockTop;
3240        pf.right = df.right = of.right = vf.right = mDockRight;
3241        pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom;
3242        dcf.setEmpty();  // Decor frame N/A for system bars.
3243
3244        if (isDefaultDisplay) {
3245            // For purposes of putting out fake window up to steal focus, we will
3246            // drive nav being hidden only by whether it is requested.
3247            final int sysui = mLastSystemUiFlags;
3248            boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
3249            boolean navTranslucent = (sysui
3250                    & (View.NAVIGATION_BAR_TRANSLUCENT | View.SYSTEM_UI_TRANSPARENT)) != 0;
3251            boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
3252            boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
3253            boolean navAllowedHidden = immersive || immersiveSticky;
3254            navTranslucent &= !immersiveSticky;  // transient trumps translucent
3255            boolean isKeyguardShowing = isStatusBarKeyguard() && !mHideLockScreen;
3256            if (!isKeyguardShowing) {
3257                navTranslucent &= areTranslucentBarsAllowed();
3258            }
3259
3260            // When the navigation bar isn't visible, we put up a fake
3261            // input window to catch all touch events.  This way we can
3262            // detect when the user presses anywhere to bring back the nav
3263            // bar and ensure the application doesn't see the event.
3264            if (navVisible || navAllowedHidden) {
3265                if (mHideNavFakeWindow != null) {
3266                    mHideNavFakeWindow.dismiss();
3267                    mHideNavFakeWindow = null;
3268                }
3269            } else if (mHideNavFakeWindow == null) {
3270                mHideNavFakeWindow = mWindowManagerFuncs.addFakeWindow(
3271                        mHandler.getLooper(), mHideNavInputEventReceiverFactory,
3272                        "hidden nav", WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER, 0,
3273                        0, false, false, true);
3274            }
3275
3276            // For purposes of positioning and showing the nav bar, if we have
3277            // decided that it can't be hidden (because of the screen aspect ratio),
3278            // then take that into account.
3279            navVisible |= !canHideNavigationBar();
3280
3281            boolean updateSysUiVisibility = false;
3282            if (mNavigationBar != null) {
3283                boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
3284                // Force the navigation bar to its appropriate place and
3285                // size.  We need to do this directly, instead of relying on
3286                // it to bubble up from the nav bar, because this needs to
3287                // change atomically with screen rotations.
3288                mNavigationBarOnBottom = (!mNavigationBarCanMove || displayWidth < displayHeight);
3289                if (mNavigationBarOnBottom) {
3290                    // It's a system nav bar or a portrait screen; nav bar goes on bottom.
3291                    int top = displayHeight - overscanBottom
3292                            - mNavigationBarHeightForRotation[displayRotation];
3293                    mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
3294                    mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
3295                    if (transientNavBarShowing) {
3296                        mNavigationBarController.setBarShowingLw(true);
3297                    } else if (navVisible) {
3298                        mNavigationBarController.setBarShowingLw(true);
3299                        mDockBottom = mTmpNavigationFrame.top;
3300                        mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
3301                        mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
3302                    } else {
3303                        // We currently want to hide the navigation UI.
3304                        mNavigationBarController.setBarShowingLw(false);
3305                    }
3306                    if (navVisible && !navTranslucent && !navAllowedHidden
3307                            && !mNavigationBar.isAnimatingLw()
3308                            && !mNavigationBarController.wasRecentlyTranslucent()) {
3309                        // If the opaque nav bar is currently requested to be visible,
3310                        // and not in the process of animating on or off, then
3311                        // we can tell the app that it is covered by it.
3312                        mSystemBottom = mTmpNavigationFrame.top;
3313                    }
3314                } else {
3315                    // Landscape screen; nav bar goes to the right.
3316                    int left = displayWidth - overscanRight
3317                            - mNavigationBarWidthForRotation[displayRotation];
3318                    mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
3319                    mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
3320                    if (transientNavBarShowing) {
3321                        mNavigationBarController.setBarShowingLw(true);
3322                    } else if (navVisible) {
3323                        mNavigationBarController.setBarShowingLw(true);
3324                        mDockRight = mTmpNavigationFrame.left;
3325                        mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
3326                        mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
3327                    } else {
3328                        // We currently want to hide the navigation UI.
3329                        mNavigationBarController.setBarShowingLw(false);
3330                    }
3331                    if (navVisible && !navTranslucent && !mNavigationBar.isAnimatingLw()
3332                            && !mNavigationBarController.wasRecentlyTranslucent()) {
3333                        // If the nav bar is currently requested to be visible,
3334                        // and not in the process of animating on or off, then
3335                        // we can tell the app that it is covered by it.
3336                        mSystemRight = mTmpNavigationFrame.left;
3337                    }
3338                }
3339                // Make sure the content and current rectangles are updated to
3340                // account for the restrictions from the navigation bar.
3341                mContentTop = mVoiceContentTop = mCurTop = mDockTop;
3342                mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
3343                mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
3344                mContentRight = mVoiceContentRight = mCurRight = mDockRight;
3345                mStatusBarLayer = mNavigationBar.getSurfaceLayer();
3346                // And compute the final frame.
3347                mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
3348                        mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
3349                        mTmpNavigationFrame);
3350                if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
3351                if (mNavigationBarController.checkHiddenLw()) {
3352                    updateSysUiVisibility = true;
3353                }
3354            }
3355            if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
3356                    mDockLeft, mDockTop, mDockRight, mDockBottom));
3357
3358            // decide where the status bar goes ahead of time
3359            if (mStatusBar != null) {
3360                // apply any navigation bar insets
3361                pf.left = df.left = of.left = mUnrestrictedScreenLeft;
3362                pf.top = df.top = of.top = mUnrestrictedScreenTop;
3363                pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
3364                pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
3365                        + mUnrestrictedScreenTop;
3366                vf.left = mStableLeft;
3367                vf.top = mStableTop;
3368                vf.right = mStableRight;
3369                vf.bottom = mStableBottom;
3370
3371                mStatusBarLayer = mStatusBar.getSurfaceLayer();
3372
3373                // Let the status bar determine its size.
3374                mStatusBar.computeFrameLw(pf, df, vf, vf, vf, dcf, vf);
3375
3376                // For layout, the status bar is always at the top with our fixed height.
3377                mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
3378
3379                boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
3380                boolean statusBarTranslucent = (sysui
3381                        & (View.STATUS_BAR_TRANSLUCENT | View.SYSTEM_UI_TRANSPARENT)) != 0;
3382                if (!isKeyguardShowing) {
3383                    statusBarTranslucent &= areTranslucentBarsAllowed();
3384                }
3385
3386                // If the status bar is hidden, we don't want to cause
3387                // windows behind it to scroll.
3388                if (mStatusBar.isVisibleLw() && !statusBarTransient) {
3389                    // Status bar may go away, so the screen area it occupies
3390                    // is available to apps but just covering them when the
3391                    // status bar is visible.
3392                    mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
3393
3394                    mContentTop = mVoiceContentTop = mCurTop = mDockTop;
3395                    mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
3396                    mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
3397                    mContentRight = mVoiceContentRight = mCurRight = mDockRight;
3398
3399                    if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " +
3400                        String.format(
3401                            "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
3402                            mDockLeft, mDockTop, mDockRight, mDockBottom,
3403                            mContentLeft, mContentTop, mContentRight, mContentBottom,
3404                            mCurLeft, mCurTop, mCurRight, mCurBottom));
3405                }
3406                if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
3407                        && !statusBarTransient && !statusBarTranslucent
3408                        && !mStatusBarController.wasRecentlyTranslucent()) {
3409                    // If the opaque status bar is currently requested to be visible,
3410                    // and not in the process of animating on or off, then
3411                    // we can tell the app that it is covered by it.
3412                    mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
3413                }
3414                if (mStatusBarController.checkHiddenLw()) {
3415                    updateSysUiVisibility = true;
3416                }
3417            }
3418            if (updateSysUiVisibility) {
3419                updateSystemUiVisibilityLw();
3420            }
3421        }
3422    }
3423
3424    /** {@inheritDoc} */
3425    @Override
3426    public int getSystemDecorLayerLw() {
3427        if (mStatusBar != null) return mStatusBar.getSurfaceLayer();
3428        if (mNavigationBar != null) return mNavigationBar.getSurfaceLayer();
3429        return 0;
3430    }
3431
3432    @Override
3433    public void getContentRectLw(Rect r) {
3434        r.set(mContentLeft, mContentTop, mContentRight, mContentBottom);
3435    }
3436
3437    void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
3438            boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
3439        if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
3440            // Here's a special case: if this attached window is a panel that is
3441            // above the dock window, and the window it is attached to is below
3442            // the dock window, then the frames we computed for the window it is
3443            // attached to can not be used because the dock is effectively part
3444            // of the underlying window and the attached window is floating on top
3445            // of the whole thing.  So, we ignore the attached window and explicitly
3446            // compute the frames that would be appropriate without the dock.
3447            df.left = of.left = cf.left = vf.left = mDockLeft;
3448            df.top = of.top = cf.top = vf.top = mDockTop;
3449            df.right = of.right = cf.right = vf.right = mDockRight;
3450            df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom;
3451        } else {
3452            // The effective display frame of the attached window depends on
3453            // whether it is taking care of insetting its content.  If not,
3454            // we need to use the parent's content frame so that the entire
3455            // window is positioned within that content.  Otherwise we can use
3456            // the overscan frame and let the attached window take care of
3457            // positioning its content appropriately.
3458            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
3459                // Set the content frame of the attached window to the parent's decor frame
3460                // (same as content frame when IME isn't present) if specifically requested by
3461                // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
3462                // Otherwise, use the overscan frame.
3463                cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
3464                        ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
3465            } else {
3466                // If the window is resizing, then we want to base the content
3467                // frame on our attached content frame to resize...  however,
3468                // things can be tricky if the attached window is NOT in resize
3469                // mode, in which case its content frame will be larger.
3470                // Ungh.  So to deal with that, make sure the content frame
3471                // we end up using is not covering the IM dock.
3472                cf.set(attached.getContentFrameLw());
3473                if (attached.isVoiceInteraction()) {
3474                    if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft;
3475                    if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop;
3476                    if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight;
3477                    if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom;
3478                } else if (attached.getSurfaceLayer() < mDockLayer) {
3479                    if (cf.left < mContentLeft) cf.left = mContentLeft;
3480                    if (cf.top < mContentTop) cf.top = mContentTop;
3481                    if (cf.right > mContentRight) cf.right = mContentRight;
3482                    if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
3483                }
3484            }
3485            df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
3486            of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
3487            vf.set(attached.getVisibleFrameLw());
3488        }
3489        // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
3490        // window should be positioned relative to its parent or the entire
3491        // screen.
3492        pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
3493                ? attached.getFrameLw() : df);
3494    }
3495
3496    private void applyStableConstraints(int sysui, int fl, Rect r) {
3497        if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
3498            // If app is requesting a stable layout, don't let the
3499            // content insets go below the stable values.
3500            if ((fl & FLAG_FULLSCREEN) != 0) {
3501                if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft;
3502                if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop;
3503                if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight;
3504                if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom;
3505            } else {
3506                if (r.left < mStableLeft) r.left = mStableLeft;
3507                if (r.top < mStableTop) r.top = mStableTop;
3508                if (r.right > mStableRight) r.right = mStableRight;
3509                if (r.bottom > mStableBottom) r.bottom = mStableBottom;
3510            }
3511        }
3512    }
3513
3514    /** {@inheritDoc} */
3515    @Override
3516    public void layoutWindowLw(WindowState win, WindowState attached) {
3517        // we've already done the status bar
3518        final WindowManager.LayoutParams attrs = win.getAttrs();
3519        if ((win == mStatusBar && (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) == 0) ||
3520                win == mNavigationBar) {
3521            return;
3522        }
3523        final boolean isDefaultDisplay = win.isDefaultDisplay();
3524        final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
3525                (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
3526        if (needsToOffsetInputMethodTarget) {
3527            if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
3528            offsetInputMethodWindowLw(mLastInputMethodWindow);
3529        }
3530
3531        final int fl = PolicyControl.getWindowFlags(win, attrs);
3532        final int sim = attrs.softInputMode;
3533        final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
3534
3535        final Rect pf = mTmpParentFrame;
3536        final Rect df = mTmpDisplayFrame;
3537        final Rect of = mTmpOverscanFrame;
3538        final Rect cf = mTmpContentFrame;
3539        final Rect vf = mTmpVisibleFrame;
3540        final Rect dcf = mTmpDecorFrame;
3541        final Rect sf = mTmpStableFrame;
3542        dcf.setEmpty();
3543
3544        final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
3545                && mNavigationBar != null && mNavigationBar.isVisibleLw());
3546
3547        final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
3548
3549        if (isDefaultDisplay) {
3550            sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom);
3551        } else {
3552            sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom);
3553        }
3554
3555        if (!isDefaultDisplay) {
3556            if (attached != null) {
3557                // If this window is attached to another, our display
3558                // frame is the same as the one we are attached to.
3559                setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
3560            } else {
3561                // Give the window full screen.
3562                pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
3563                pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
3564                pf.right = df.right = of.right = cf.right
3565                        = mOverscanScreenLeft + mOverscanScreenWidth;
3566                pf.bottom = df.bottom = of.bottom = cf.bottom
3567                        = mOverscanScreenTop + mOverscanScreenHeight;
3568            }
3569        } else  if (attrs.type == TYPE_INPUT_METHOD || attrs.type == TYPE_VOICE_INTERACTION) {
3570            pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
3571            pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
3572            pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
3573            // IM dock windows layout below the nav bar...
3574            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
3575            // ...with content insets above the nav bar
3576            cf.bottom = vf.bottom = mStableBottom;
3577            // IM dock windows always go to the bottom of the screen.
3578            attrs.gravity = Gravity.BOTTOM;
3579            mDockLayer = win.getSurfaceLayer();
3580        } else if (win == mStatusBar && (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
3581            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
3582            pf.top = df.top = of.top = mUnrestrictedScreenTop;
3583            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
3584            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop;
3585            cf.left = vf.left = mStableLeft;
3586            cf.top = vf.top = mStableTop;
3587            cf.right = vf.right = mStableRight;
3588            vf.bottom = mStableBottom;
3589            cf.bottom = mContentBottom;
3590        } else {
3591
3592            // Default policy decor for the default display
3593            dcf.left = mSystemLeft;
3594            dcf.top = mSystemTop;
3595            dcf.right = mSystemRight;
3596            dcf.bottom = mSystemBottom;
3597            final boolean inheritTranslucentDecor = (attrs.privateFlags
3598                    & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0;
3599            final boolean isAppWindow =
3600                    attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW &&
3601                    attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
3602            final boolean topAtRest =
3603                    win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
3604            if (isAppWindow && !inheritTranslucentDecor && !topAtRest) {
3605                if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
3606                        && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0
3607                        && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
3608                        && (fl & WindowManager.LayoutParams.
3609                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
3610                    // Ensure policy decor includes status bar
3611                    dcf.top = mStableTop;
3612                }
3613                if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0
3614                        && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
3615                        && (fl & WindowManager.LayoutParams.
3616                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
3617                    // Ensure policy decor includes navigation bar
3618                    dcf.bottom = mStableBottom;
3619                    dcf.right = mStableRight;
3620                }
3621            }
3622
3623            if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
3624                    == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
3625                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
3626                            + "): IN_SCREEN, INSET_DECOR");
3627                // This is the case for a normal activity window: we want it
3628                // to cover all of the screen space, and it can take care of
3629                // moving its contents to account for screen decorations that
3630                // intrude into that space.
3631                if (attached != null) {
3632                    // If this window is attached to another, our display
3633                    // frame is the same as the one we are attached to.
3634                    setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
3635                } else {
3636                    if (attrs.type == TYPE_STATUS_BAR_PANEL
3637                            || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
3638                        // Status bar panels are the only windows who can go on top of
3639                        // the status bar.  They are protected by the STATUS_BAR_SERVICE
3640                        // permission, so they have the same privileges as the status
3641                        // bar itself.
3642                        //
3643                        // However, they should still dodge the navigation bar if it exists.
3644
3645                        pf.left = df.left = of.left = hasNavBar
3646                                ? mDockLeft : mUnrestrictedScreenLeft;
3647                        pf.top = df.top = of.top = mUnrestrictedScreenTop;
3648                        pf.right = df.right = of.right = hasNavBar
3649                                ? mRestrictedScreenLeft+mRestrictedScreenWidth
3650                                : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
3651                        pf.bottom = df.bottom = of.bottom = hasNavBar
3652                                ? mRestrictedScreenTop+mRestrictedScreenHeight
3653                                : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
3654
3655                        if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
3656                                        "Laying out status bar window: (%d,%d - %d,%d)",
3657                                        pf.left, pf.top, pf.right, pf.bottom));
3658                    } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
3659                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
3660                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
3661                        // Asking to layout into the overscan region, so give it that pure
3662                        // unrestricted area.
3663                        pf.left = df.left = of.left = mOverscanScreenLeft;
3664                        pf.top = df.top = of.top = mOverscanScreenTop;
3665                        pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth;
3666                        pf.bottom = df.bottom = of.bottom = mOverscanScreenTop
3667                                + mOverscanScreenHeight;
3668                    } else if (canHideNavigationBar()
3669                            && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
3670                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
3671                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
3672                        // Asking for layout as if the nav bar is hidden, lets the
3673                        // application extend into the unrestricted overscan screen area.  We
3674                        // only do this for application windows to ensure no window that
3675                        // can be above the nav bar can do this.
3676                        pf.left = df.left = mOverscanScreenLeft;
3677                        pf.top = df.top = mOverscanScreenTop;
3678                        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
3679                        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
3680                        // We need to tell the app about where the frame inside the overscan
3681                        // is, so it can inset its content by that amount -- it didn't ask
3682                        // to actually extend itself into the overscan region.
3683                        of.left = mUnrestrictedScreenLeft;
3684                        of.top = mUnrestrictedScreenTop;
3685                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
3686                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
3687                    } else {
3688                        pf.left = df.left = mRestrictedOverscanScreenLeft;
3689                        pf.top = df.top = mRestrictedOverscanScreenTop;
3690                        pf.right = df.right = mRestrictedOverscanScreenLeft
3691                                + mRestrictedOverscanScreenWidth;
3692                        pf.bottom = df.bottom = mRestrictedOverscanScreenTop
3693                                + mRestrictedOverscanScreenHeight;
3694                        // We need to tell the app about where the frame inside the overscan
3695                        // is, so it can inset its content by that amount -- it didn't ask
3696                        // to actually extend itself into the overscan region.
3697                        of.left = mUnrestrictedScreenLeft;
3698                        of.top = mUnrestrictedScreenTop;
3699                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
3700                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
3701                    }
3702
3703                    if ((fl & FLAG_FULLSCREEN) == 0) {
3704                        if (win.isVoiceInteraction()) {
3705                            cf.left = mVoiceContentLeft;
3706                            cf.top = mVoiceContentTop;
3707                            cf.right = mVoiceContentRight;
3708                            cf.bottom = mVoiceContentBottom;
3709                        } else {
3710                            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
3711                                cf.left = mDockLeft;
3712                                cf.top = mDockTop;
3713                                cf.right = mDockRight;
3714                                cf.bottom = mDockBottom;
3715                            } else {
3716                                cf.left = mContentLeft;
3717                                cf.top = mContentTop;
3718                                cf.right = mContentRight;
3719                                cf.bottom = mContentBottom;
3720                            }
3721                        }
3722                    } else {
3723                        // Full screen windows are always given a layout that is as if the
3724                        // status bar and other transient decors are gone.  This is to avoid
3725                        // bad states when moving from a window that is not hding the
3726                        // status bar to one that is.
3727                        cf.left = mRestrictedScreenLeft;
3728                        cf.top = mRestrictedScreenTop;
3729                        cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
3730                        cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight;
3731                    }
3732                    applyStableConstraints(sysUiFl, fl, cf);
3733                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
3734                        vf.left = mCurLeft;
3735                        vf.top = mCurTop;
3736                        vf.right = mCurRight;
3737                        vf.bottom = mCurBottom;
3738                    } else {
3739                        vf.set(cf);
3740                    }
3741                }
3742            } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
3743                    & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
3744                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
3745                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
3746                        "): IN_SCREEN");
3747                // A window that has requested to fill the entire screen just
3748                // gets everything, period.
3749                if (attrs.type == TYPE_STATUS_BAR_PANEL
3750                        || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
3751                    pf.left = df.left = of.left = cf.left = hasNavBar
3752                            ? mDockLeft : mUnrestrictedScreenLeft;
3753                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
3754                    pf.right = df.right = of.right = cf.right = hasNavBar
3755                                        ? mRestrictedScreenLeft+mRestrictedScreenWidth
3756                                        : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
3757                    pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar
3758                                          ? mRestrictedScreenTop+mRestrictedScreenHeight
3759                                          : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
3760                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
3761                                    "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
3762                                    pf.left, pf.top, pf.right, pf.bottom));
3763                } else if (attrs.type == TYPE_NAVIGATION_BAR
3764                        || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
3765                    // The navigation bar has Real Ultimate Power.
3766                    pf.left = df.left = of.left = mUnrestrictedScreenLeft;
3767                    pf.top = df.top = of.top = mUnrestrictedScreenTop;
3768                    pf.right = df.right = of.right = mUnrestrictedScreenLeft
3769                            + mUnrestrictedScreenWidth;
3770                    pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop
3771                            + mUnrestrictedScreenHeight;
3772                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
3773                                    "Laying out navigation bar window: (%d,%d - %d,%d)",
3774                                    pf.left, pf.top, pf.right, pf.bottom));
3775                } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
3776                                || attrs.type == TYPE_BOOT_PROGRESS)
3777                        && ((fl & FLAG_FULLSCREEN) != 0)) {
3778                    // Fullscreen secure system overlays get what they ask for.
3779                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
3780                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
3781                    pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
3782                            + mOverscanScreenWidth;
3783                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
3784                            + mOverscanScreenHeight;
3785                } else if (attrs.type == TYPE_BOOT_PROGRESS) {
3786                    // Boot progress screen always covers entire display.
3787                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
3788                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
3789                    pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
3790                            + mOverscanScreenWidth;
3791                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
3792                            + mOverscanScreenHeight;
3793                } else if (attrs.type == TYPE_WALLPAPER) {
3794                    // The wallpaper also has Real Ultimate Power, but we want to tell
3795                    // it about the overscan area.
3796                    pf.left = df.left = mOverscanScreenLeft;
3797                    pf.top = df.top = mOverscanScreenTop;
3798                    pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
3799                    pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
3800                    of.left = cf.left = mUnrestrictedScreenLeft;
3801                    of.top = cf.top = mUnrestrictedScreenTop;
3802                    of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
3803                    of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
3804                } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
3805                        && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
3806                        && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
3807                    // Asking to layout into the overscan region, so give it that pure
3808                    // unrestricted area.
3809                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
3810                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
3811                    pf.right = df.right = of.right = cf.right
3812                            = mOverscanScreenLeft + mOverscanScreenWidth;
3813                    pf.bottom = df.bottom = of.bottom = cf.bottom
3814                            = mOverscanScreenTop + mOverscanScreenHeight;
3815                } else if (canHideNavigationBar()
3816                        && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
3817                        && (attrs.type == TYPE_STATUS_BAR
3818                            || attrs.type == TYPE_TOAST
3819                            || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
3820                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
3821                    // Asking for layout as if the nav bar is hidden, lets the
3822                    // application extend into the unrestricted screen area.  We
3823                    // only do this for application windows (or toasts) to ensure no window that
3824                    // can be above the nav bar can do this.
3825                    // XXX This assumes that an app asking for this will also
3826                    // ask for layout in only content.  We can't currently figure out
3827                    // what the screen would be if only laying out to hide the nav bar.
3828                    pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
3829                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
3830                    pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft
3831                            + mUnrestrictedScreenWidth;
3832                    pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
3833                            + mUnrestrictedScreenHeight;
3834                } else {
3835                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
3836                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
3837                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
3838                            + mRestrictedScreenWidth;
3839                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
3840                            + mRestrictedScreenHeight;
3841                }
3842
3843                applyStableConstraints(sysUiFl, fl, cf);
3844
3845                if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
3846                    vf.left = mCurLeft;
3847                    vf.top = mCurTop;
3848                    vf.right = mCurRight;
3849                    vf.bottom = mCurBottom;
3850                } else {
3851                    vf.set(cf);
3852                }
3853            } else if (attached != null) {
3854                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
3855                        "): attached to " + attached);
3856                // A child window should be placed inside of the same visible
3857                // frame that its parent had.
3858                setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf);
3859            } else {
3860                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
3861                        "): normal window");
3862                // Otherwise, a normal window must be placed inside the content
3863                // of all screen decorations.
3864                if (attrs.type == TYPE_STATUS_BAR_PANEL) {
3865                    // Status bar panels are the only windows who can go on top of
3866                    // the status bar.  They are protected by the STATUS_BAR_SERVICE
3867                    // permission, so they have the same privileges as the status
3868                    // bar itself.
3869                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
3870                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
3871                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
3872                            + mRestrictedScreenWidth;
3873                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
3874                            + mRestrictedScreenHeight;
3875                } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT
3876                        || attrs.type == TYPE_VOLUME_OVERLAY) {
3877                    // These dialogs are stable to interim decor changes.
3878                    pf.left = df.left = of.left = cf.left = mStableLeft;
3879                    pf.top = df.top = of.top = cf.top = mStableTop;
3880                    pf.right = df.right = of.right = cf.right = mStableRight;
3881                    pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom;
3882                } else {
3883                    pf.left = mContentLeft;
3884                    pf.top = mContentTop;
3885                    pf.right = mContentRight;
3886                    pf.bottom = mContentBottom;
3887                    if (win.isVoiceInteraction()) {
3888                        df.left = of.left = cf.left = mVoiceContentLeft;
3889                        df.top = of.top = cf.top = mVoiceContentTop;
3890                        df.right = of.right = cf.right = mVoiceContentRight;
3891                        df.bottom = of.bottom = cf.bottom = mVoiceContentBottom;
3892                    } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
3893                        df.left = of.left = cf.left = mDockLeft;
3894                        df.top = of.top = cf.top = mDockTop;
3895                        df.right = of.right = cf.right = mDockRight;
3896                        df.bottom = of.bottom = cf.bottom = mDockBottom;
3897                    } else {
3898                        df.left = of.left = cf.left = mContentLeft;
3899                        df.top = of.top = cf.top = mContentTop;
3900                        df.right = of.right = cf.right = mContentRight;
3901                        df.bottom = of.bottom = cf.bottom = mContentBottom;
3902                    }
3903                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
3904                        vf.left = mCurLeft;
3905                        vf.top = mCurTop;
3906                        vf.right = mCurRight;
3907                        vf.bottom = mCurBottom;
3908                    } else {
3909                        vf.set(cf);
3910                    }
3911                }
3912            }
3913        }
3914
3915        // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
3916        if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR) {
3917            df.left = df.top = -10000;
3918            df.right = df.bottom = 10000;
3919            if (attrs.type != TYPE_WALLPAPER) {
3920                of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
3921                of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
3922            }
3923        }
3924
3925        if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
3926                + ": sim=#" + Integer.toHexString(sim)
3927                + " attach=" + attached + " type=" + attrs.type
3928                + String.format(" flags=0x%08x", fl)
3929                + " pf=" + pf.toShortString() + " df=" + df.toShortString()
3930                + " of=" + of.toShortString()
3931                + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
3932                + " dcf=" + dcf.toShortString()
3933                + " sf=" + sf.toShortString());
3934
3935        win.computeFrameLw(pf, df, of, cf, vf, dcf, sf);
3936
3937        // Dock windows carve out the bottom of the screen, so normal windows
3938        // can't appear underneath them.
3939        if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleOrBehindKeyguardLw()
3940                && !win.getGivenInsetsPendingLw()) {
3941            setLastInputMethodWindowLw(null, null);
3942            offsetInputMethodWindowLw(win);
3943        }
3944        if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleOrBehindKeyguardLw()
3945                && !win.getGivenInsetsPendingLw()) {
3946            offsetVoiceInputWindowLw(win);
3947        }
3948    }
3949
3950    private void offsetInputMethodWindowLw(WindowState win) {
3951        int top = win.getDisplayFrameLw().top;
3952        top += win.getGivenContentInsetsLw().top;
3953        if (mContentBottom > top) {
3954            mContentBottom = top;
3955        }
3956        if (mVoiceContentBottom > top) {
3957            mVoiceContentBottom = top;
3958        }
3959        top = win.getVisibleFrameLw().top;
3960        top += win.getGivenVisibleInsetsLw().top;
3961        if (mCurBottom > top) {
3962            mCurBottom = top;
3963        }
3964        if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
3965                + mDockBottom + " mContentBottom="
3966                + mContentBottom + " mCurBottom=" + mCurBottom);
3967    }
3968
3969    private void offsetVoiceInputWindowLw(WindowState win) {
3970        int top = win.getDisplayFrameLw().top;
3971        top += win.getGivenContentInsetsLw().top;
3972        if (mVoiceContentBottom > top) {
3973            mVoiceContentBottom = top;
3974        }
3975    }
3976
3977    /** {@inheritDoc} */
3978    @Override
3979    public void finishLayoutLw() {
3980        return;
3981    }
3982
3983    /** {@inheritDoc} */
3984    @Override
3985    public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
3986        mTopFullscreenOpaqueWindowState = null;
3987        mTopFullscreenOpaqueOrDimmingWindowState = null;
3988        mAppsToBeHidden.clear();
3989        mAppsThatDismissKeyguard.clear();
3990        mForceStatusBar = false;
3991        mForceStatusBarFromKeyguard = false;
3992        mForcingShowNavBar = false;
3993        mForcingShowNavBarLayer = -1;
3994
3995        mHideLockScreen = false;
3996        mAllowLockscreenWhenOn = false;
3997        mDismissKeyguard = DISMISS_KEYGUARD_NONE;
3998        mShowingLockscreen = false;
3999        mShowingDream = false;
4000        mWinShowWhenLocked = null;
4001        mKeyguardSecure = isKeyguardSecure();
4002        mKeyguardSecureIncludingHidden = mKeyguardSecure
4003                && (mKeyguardDelegate != null && mKeyguardDelegate.isShowing());
4004    }
4005
4006    /** {@inheritDoc} */
4007    @Override
4008    public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs) {
4009        if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
4010                + win.isVisibleOrBehindKeyguardLw());
4011        final int fl = PolicyControl.getWindowFlags(win, attrs);
4012        if (mTopFullscreenOpaqueWindowState == null
4013                && win.isVisibleLw() && attrs.type == TYPE_INPUT_METHOD) {
4014            mForcingShowNavBar = true;
4015            mForcingShowNavBarLayer = win.getSurfaceLayer();
4016        }
4017        if (attrs.type == TYPE_STATUS_BAR && (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
4018            mForceStatusBarFromKeyguard = true;
4019        }
4020        if (mTopFullscreenOpaqueWindowState == null &&
4021                win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
4022            if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
4023                if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
4024                    mForceStatusBarFromKeyguard = true;
4025                } else {
4026                    mForceStatusBar = true;
4027                }
4028            }
4029            if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
4030                mShowingLockscreen = true;
4031            }
4032            boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
4033                    && attrs.type < FIRST_SYSTEM_WINDOW;
4034            if (attrs.type == TYPE_DREAM) {
4035                // If the lockscreen was showing when the dream started then wait
4036                // for the dream to draw before hiding the lockscreen.
4037                if (!mDreamingLockscreen
4038                        || (win.isVisibleLw() && win.hasDrawnLw())) {
4039                    mShowingDream = true;
4040                    appWindow = true;
4041                }
4042            }
4043
4044            final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0;
4045            final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0;
4046            if (appWindow) {
4047                final IApplicationToken appToken = win.getAppToken();
4048                if (showWhenLocked) {
4049                    // Remove any previous windows with the same appToken.
4050                    mAppsToBeHidden.remove(appToken);
4051                    mAppsThatDismissKeyguard.remove(appToken);
4052                    if (mAppsToBeHidden.isEmpty()) {
4053                        if (dismissKeyguard && !mKeyguardSecure) {
4054                            mAppsThatDismissKeyguard.add(appToken);
4055                        } else {
4056                            mWinShowWhenLocked = win;
4057                            mHideLockScreen = true;
4058                            mForceStatusBarFromKeyguard = false;
4059                        }
4060                    }
4061                } else if (dismissKeyguard) {
4062                    if (mKeyguardSecure) {
4063                        mAppsToBeHidden.add(appToken);
4064                    } else {
4065                        mAppsToBeHidden.remove(appToken);
4066                    }
4067                    mAppsThatDismissKeyguard.add(appToken);
4068                } else {
4069                    mAppsToBeHidden.add(appToken);
4070                }
4071                if (attrs.x == 0 && attrs.y == 0
4072                        && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
4073                        && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
4074                    if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
4075                    mTopFullscreenOpaqueWindowState = win;
4076                    if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
4077                        mTopFullscreenOpaqueOrDimmingWindowState = win;
4078                    }
4079                    if (!mAppsThatDismissKeyguard.isEmpty() &&
4080                            mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
4081                        if (DEBUG_LAYOUT) Slog.v(TAG,
4082                                "Setting mDismissKeyguard true by win " + win);
4083                        mDismissKeyguard = mWinDismissingKeyguard == win ?
4084                                DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
4085                        mWinDismissingKeyguard = win;
4086                        mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure;
4087                    } else if (mAppsToBeHidden.isEmpty() && showWhenLocked) {
4088                        if (DEBUG_LAYOUT) Slog.v(TAG,
4089                                "Setting mHideLockScreen to true by win " + win);
4090                        mHideLockScreen = true;
4091                        mForceStatusBarFromKeyguard = false;
4092                    }
4093                    if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
4094                        mAllowLockscreenWhenOn = true;
4095                    }
4096                }
4097
4098                if (mWinShowWhenLocked != null &&
4099                        mWinShowWhenLocked.getAppToken() != win.getAppToken()) {
4100                    win.hideLw(false);
4101                }
4102            }
4103        }
4104        if (mTopFullscreenOpaqueOrDimmingWindowState == null
4105                && win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()
4106                && win.isDimming()) {
4107            mTopFullscreenOpaqueOrDimmingWindowState = win;
4108        }
4109    }
4110
4111    /** {@inheritDoc} */
4112    @Override
4113    public int finishPostLayoutPolicyLw() {
4114        if (mWinShowWhenLocked != null &&
4115                mWinShowWhenLocked != mTopFullscreenOpaqueWindowState) {
4116            // A dialog is dismissing the keyguard. Put the wallpaper behind it and hide the
4117            // fullscreen window.
4118            // TODO: Make sure FLAG_SHOW_WALLPAPER is restored when dialog is dismissed. Or not.
4119            mWinShowWhenLocked.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
4120            mTopFullscreenOpaqueWindowState.hideLw(false);
4121            mTopFullscreenOpaqueWindowState = mWinShowWhenLocked;
4122        }
4123
4124        int changes = 0;
4125        boolean topIsFullscreen = false;
4126
4127        final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
4128                ? mTopFullscreenOpaqueWindowState.getAttrs()
4129                : null;
4130
4131        // If we are not currently showing a dream then remember the current
4132        // lockscreen state.  We will use this to determine whether the dream
4133        // started while the lockscreen was showing and remember this state
4134        // while the dream is showing.
4135        if (!mShowingDream) {
4136            mDreamingLockscreen = mShowingLockscreen;
4137        }
4138
4139        if (mStatusBar != null) {
4140            if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
4141                    + " forcefkg=" + mForceStatusBarFromKeyguard
4142                    + " top=" + mTopFullscreenOpaqueWindowState);
4143            if (mForceStatusBar || mForceStatusBarFromKeyguard) {
4144                if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
4145                if (mStatusBarController.setBarShowingLw(true)) {
4146                    changes |= FINISH_LAYOUT_REDO_LAYOUT;
4147                }
4148                // Maintain fullscreen layout until incoming animation is complete.
4149                topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
4150                // Transient status bar on the lockscreen is not allowed
4151                if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) {
4152                    mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
4153                            mLastSystemUiFlags, mLastSystemUiFlags);
4154                }
4155            } else if (mTopFullscreenOpaqueWindowState != null) {
4156                final int fl = PolicyControl.getWindowFlags(null, lp);
4157                if (localLOGV) {
4158                    Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
4159                            + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw());
4160                    Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
4161                            + " lp.flags=0x" + Integer.toHexString(fl));
4162                }
4163                topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
4164                        || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
4165                // The subtle difference between the window for mTopFullscreenOpaqueWindowState
4166                // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
4167                // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
4168                // case though.
4169                if (mStatusBarController.isTransientShowing()) {
4170                    if (mStatusBarController.setBarShowingLw(true)) {
4171                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
4172                    }
4173                } else if (topIsFullscreen) {
4174                    if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
4175                    if (mStatusBarController.setBarShowingLw(false)) {
4176                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
4177                    } else {
4178                        if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
4179                    }
4180                } else {
4181                    if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
4182                    if (mStatusBarController.setBarShowingLw(true)) {
4183                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
4184                    }
4185                }
4186            }
4187        }
4188
4189        if (mTopIsFullscreen != topIsFullscreen) {
4190            if (!topIsFullscreen) {
4191                // Force another layout when status bar becomes fully shown.
4192                changes |= FINISH_LAYOUT_REDO_LAYOUT;
4193            }
4194            mTopIsFullscreen = topIsFullscreen;
4195        }
4196
4197        // Hide the key guard if a visible window explicitly specifies that it wants to be
4198        // displayed when the screen is locked.
4199        if (mKeyguardDelegate != null && mStatusBar != null) {
4200            if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
4201                    + mHideLockScreen);
4202            if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardSecure) {
4203                mKeyguardHidden = true;
4204                if (setKeyguardOccludedLw(true)) {
4205                    changes |= FINISH_LAYOUT_REDO_LAYOUT
4206                            | FINISH_LAYOUT_REDO_CONFIG
4207                            | FINISH_LAYOUT_REDO_WALLPAPER;
4208                }
4209                if (mKeyguardDelegate.isShowing()) {
4210                    mHandler.post(new Runnable() {
4211                        @Override
4212                        public void run() {
4213                            mKeyguardDelegate.keyguardDone(false, false);
4214                        }
4215                    });
4216                }
4217            } else if (mHideLockScreen) {
4218                mKeyguardHidden = true;
4219                if (setKeyguardOccludedLw(true)) {
4220                    changes |= FINISH_LAYOUT_REDO_LAYOUT
4221                            | FINISH_LAYOUT_REDO_CONFIG
4222                            | FINISH_LAYOUT_REDO_WALLPAPER;
4223                }
4224            } else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) {
4225                // This is the case of keyguard isSecure() and not mHideLockScreen.
4226                if (mDismissKeyguard == DISMISS_KEYGUARD_START) {
4227                    // Only launch the next keyguard unlock window once per window.
4228                    mKeyguardHidden = false;
4229                    if (setKeyguardOccludedLw(false)) {
4230                        changes |= FINISH_LAYOUT_REDO_LAYOUT
4231                                | FINISH_LAYOUT_REDO_CONFIG
4232                                | FINISH_LAYOUT_REDO_WALLPAPER;
4233                    }
4234                    mHandler.post(new Runnable() {
4235                        @Override
4236                        public void run() {
4237                            mKeyguardDelegate.dismiss();
4238                        }
4239                    });
4240                }
4241            } else {
4242                mWinDismissingKeyguard = null;
4243                mKeyguardHidden = false;
4244                if (setKeyguardOccludedLw(false)) {
4245                    changes |= FINISH_LAYOUT_REDO_LAYOUT
4246                            | FINISH_LAYOUT_REDO_CONFIG
4247                            | FINISH_LAYOUT_REDO_WALLPAPER;
4248                }
4249            }
4250        }
4251
4252        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
4253            // If the navigation bar has been hidden or shown, we need to do another
4254            // layout pass to update that window.
4255            changes |= FINISH_LAYOUT_REDO_LAYOUT;
4256        }
4257
4258        // update since mAllowLockscreenWhenOn might have changed
4259        updateLockScreenTimeout();
4260        return changes;
4261    }
4262
4263    /**
4264     * Updates the occluded state of the Keyguard.
4265     *
4266     * @return Whether the flags have changed and we have to redo the layout.
4267     */
4268    private boolean setKeyguardOccludedLw(boolean isOccluded) {
4269        boolean wasOccluded = mKeyguardOccluded;
4270        boolean showing = mKeyguardDelegate.isShowing();
4271        if (wasOccluded && !isOccluded && showing) {
4272            mKeyguardOccluded = false;
4273            mKeyguardDelegate.setOccluded(false);
4274            mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
4275            mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
4276            return true;
4277        } else if (!wasOccluded && isOccluded && showing) {
4278            mKeyguardOccluded = true;
4279            mKeyguardDelegate.setOccluded(true);
4280            mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
4281            mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
4282            return true;
4283        } else {
4284            return false;
4285        }
4286    }
4287
4288    private boolean isStatusBarKeyguard() {
4289        return mStatusBar != null
4290                && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
4291    }
4292
4293    @Override
4294    public boolean allowAppAnimationsLw() {
4295        if (isStatusBarKeyguard() || mShowingDream) {
4296            // If keyguard or dreams is currently visible, no reason to animate behind it.
4297            return false;
4298        }
4299        return true;
4300    }
4301
4302    @Override
4303    public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
4304        mFocusedWindow = newFocus;
4305        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
4306            // If the navigation bar has been hidden or shown, we need to do another
4307            // layout pass to update that window.
4308            return FINISH_LAYOUT_REDO_LAYOUT;
4309        }
4310        return 0;
4311    }
4312
4313    /** {@inheritDoc} */
4314    @Override
4315    public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
4316        // lid changed state
4317        final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
4318        if (newLidState == mLidState) {
4319            return;
4320        }
4321
4322        mLidState = newLidState;
4323        applyLidSwitchState();
4324        updateRotation(true);
4325
4326        if (lidOpen) {
4327            wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch);
4328        } else if (!mLidControlsSleep) {
4329            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
4330        }
4331    }
4332
4333    @Override
4334    public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
4335        int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
4336        if (mCameraLensCoverState == lensCoverState) {
4337            return;
4338        }
4339        if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
4340                lensCoverState == CAMERA_LENS_UNCOVERED) {
4341            Intent intent;
4342            final boolean keyguardActive = mKeyguardDelegate == null ? false :
4343                    mKeyguardDelegate.isShowing();
4344            if (keyguardActive) {
4345                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
4346            } else {
4347                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
4348            }
4349            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens);
4350            mContext.startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
4351        }
4352        mCameraLensCoverState = lensCoverState;
4353    }
4354
4355    void setHdmiPlugged(boolean plugged) {
4356        if (mHdmiPlugged != plugged) {
4357            mHdmiPlugged = plugged;
4358            updateRotation(true, true);
4359            Intent intent = new Intent(ACTION_HDMI_PLUGGED);
4360            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
4361            intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
4362            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
4363        }
4364    }
4365
4366    void initializeHdmiState() {
4367        boolean plugged = false;
4368        // watch for HDMI plug messages if the hdmi switch exists
4369        if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
4370            mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
4371
4372            final String filename = "/sys/class/switch/hdmi/state";
4373            FileReader reader = null;
4374            try {
4375                reader = new FileReader(filename);
4376                char[] buf = new char[15];
4377                int n = reader.read(buf);
4378                if (n > 1) {
4379                    plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
4380                }
4381            } catch (IOException ex) {
4382                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
4383            } catch (NumberFormatException ex) {
4384                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
4385            } finally {
4386                if (reader != null) {
4387                    try {
4388                        reader.close();
4389                    } catch (IOException ex) {
4390                    }
4391                }
4392            }
4393        }
4394        // This dance forces the code in setHdmiPlugged to run.
4395        // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
4396        mHdmiPlugged = !plugged;
4397        setHdmiPlugged(!mHdmiPlugged);
4398    }
4399
4400    final Object mScreenshotLock = new Object();
4401    ServiceConnection mScreenshotConnection = null;
4402
4403    final Runnable mScreenshotTimeout = new Runnable() {
4404        @Override public void run() {
4405            synchronized (mScreenshotLock) {
4406                if (mScreenshotConnection != null) {
4407                    mContext.unbindService(mScreenshotConnection);
4408                    mScreenshotConnection = null;
4409                }
4410            }
4411        }
4412    };
4413
4414    // Assume this is called from the Handler thread.
4415    private void takeScreenshot() {
4416        synchronized (mScreenshotLock) {
4417            if (mScreenshotConnection != null) {
4418                return;
4419            }
4420            ComponentName cn = new ComponentName("com.android.systemui",
4421                    "com.android.systemui.screenshot.TakeScreenshotService");
4422            Intent intent = new Intent();
4423            intent.setComponent(cn);
4424            ServiceConnection conn = new ServiceConnection() {
4425                @Override
4426                public void onServiceConnected(ComponentName name, IBinder service) {
4427                    synchronized (mScreenshotLock) {
4428                        if (mScreenshotConnection != this) {
4429                            return;
4430                        }
4431                        Messenger messenger = new Messenger(service);
4432                        Message msg = Message.obtain(null, 1);
4433                        final ServiceConnection myConn = this;
4434                        Handler h = new Handler(mHandler.getLooper()) {
4435                            @Override
4436                            public void handleMessage(Message msg) {
4437                                synchronized (mScreenshotLock) {
4438                                    if (mScreenshotConnection == myConn) {
4439                                        mContext.unbindService(mScreenshotConnection);
4440                                        mScreenshotConnection = null;
4441                                        mHandler.removeCallbacks(mScreenshotTimeout);
4442                                    }
4443                                }
4444                            }
4445                        };
4446                        msg.replyTo = new Messenger(h);
4447                        msg.arg1 = msg.arg2 = 0;
4448                        if (mStatusBar != null && mStatusBar.isVisibleLw())
4449                            msg.arg1 = 1;
4450                        if (mNavigationBar != null && mNavigationBar.isVisibleLw())
4451                            msg.arg2 = 1;
4452                        try {
4453                            messenger.send(msg);
4454                        } catch (RemoteException e) {
4455                        }
4456                    }
4457                }
4458                @Override
4459                public void onServiceDisconnected(ComponentName name) {}
4460            };
4461            if (mContext.bindServiceAsUser(
4462                    intent, conn, Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) {
4463                mScreenshotConnection = conn;
4464                mHandler.postDelayed(mScreenshotTimeout, 10000);
4465            }
4466        }
4467    }
4468
4469    /** {@inheritDoc} */
4470    @Override
4471    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
4472        if (!mSystemBooted) {
4473            // If we have not yet booted, don't let key events do anything.
4474            return 0;
4475        }
4476
4477        final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
4478        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
4479        final boolean canceled = event.isCanceled();
4480        final int keyCode = event.getKeyCode();
4481
4482        final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
4483
4484        // If screen is off then we treat the case where the keyguard is open but hidden
4485        // the same as if it were open and in front.
4486        // This will prevent any keys other than the power button from waking the screen
4487        // when the keyguard is hidden by another activity.
4488        final boolean keyguardActive = (mKeyguardDelegate == null ? false :
4489                                            (interactive ?
4490                                                isKeyguardShowingAndNotOccluded() :
4491                                                mKeyguardDelegate.isShowing()));
4492
4493        if (DEBUG_INPUT) {
4494            Log.d(TAG, "interceptKeyTq keycode=" + keyCode
4495                    + " interactive=" + interactive + " keyguardActive=" + keyguardActive
4496                    + " policyFlags=" + Integer.toHexString(policyFlags));
4497        }
4498
4499        // Basic policy based on interactive state.
4500        int result;
4501        boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
4502                || event.isWakeKey();
4503        if (interactive || (isInjected && !isWakeKey)) {
4504            // When the device is interactive or the key is injected pass the
4505            // key to the application.
4506            result = ACTION_PASS_TO_USER;
4507            isWakeKey = false;
4508        } else if (!interactive && shouldDispatchInputWhenNonInteractive()) {
4509            // If we're currently dozing with the screen on and the keyguard showing, pass the key
4510            // to the application but preserve its wake key status to make sure we still move
4511            // from dozing to fully interactive if we would normally go from off to fully
4512            // interactive.
4513            result = ACTION_PASS_TO_USER;
4514        } else {
4515            // When the screen is off and the key is not injected, determine whether
4516            // to wake the device but don't pass the key to the application.
4517            result = 0;
4518            if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
4519                isWakeKey = false;
4520            }
4521        }
4522
4523        // If the key would be handled globally, just return the result, don't worry about special
4524        // key processing.
4525        if (isValidGlobalKey(keyCode)
4526                && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
4527            if (isWakeKey) {
4528                wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey);
4529            }
4530            return result;
4531        }
4532
4533        boolean useHapticFeedback = down
4534                && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
4535                && event.getRepeatCount() == 0;
4536
4537        // Handle special keys.
4538        switch (keyCode) {
4539            case KeyEvent.KEYCODE_VOLUME_DOWN:
4540            case KeyEvent.KEYCODE_VOLUME_UP:
4541            case KeyEvent.KEYCODE_VOLUME_MUTE: {
4542                if (mUseTvRouting) {
4543                    // On TVs volume keys never go to the foreground app
4544                    result &= ~ACTION_PASS_TO_USER;
4545                }
4546                if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
4547                    if (down) {
4548                        if (interactive && !mScreenshotChordVolumeDownKeyTriggered
4549                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
4550                            mScreenshotChordVolumeDownKeyTriggered = true;
4551                            mScreenshotChordVolumeDownKeyTime = event.getDownTime();
4552                            mScreenshotChordVolumeDownKeyConsumed = false;
4553                            cancelPendingPowerKeyAction();
4554                            interceptScreenshotChord();
4555                        }
4556                    } else {
4557                        mScreenshotChordVolumeDownKeyTriggered = false;
4558                        cancelPendingScreenshotChordAction();
4559                    }
4560                } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
4561                    if (down) {
4562                        if (interactive && !mScreenshotChordVolumeUpKeyTriggered
4563                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
4564                            mScreenshotChordVolumeUpKeyTriggered = true;
4565                            cancelPendingPowerKeyAction();
4566                            cancelPendingScreenshotChordAction();
4567                        }
4568                    } else {
4569                        mScreenshotChordVolumeUpKeyTriggered = false;
4570                        cancelPendingScreenshotChordAction();
4571                    }
4572                }
4573                if (down) {
4574                    TelecomManager telecomManager = getTelecommService();
4575                    if (telecomManager != null) {
4576                        if (telecomManager.isRinging()) {
4577                            // If an incoming call is ringing, either VOLUME key means
4578                            // "silence ringer".  We handle these keys here, rather than
4579                            // in the InCallScreen, to make sure we'll respond to them
4580                            // even if the InCallScreen hasn't come to the foreground yet.
4581                            // Look for the DOWN event here, to agree with the "fallback"
4582                            // behavior in the InCallScreen.
4583                            Log.i(TAG, "interceptKeyBeforeQueueing:"
4584                                  + " VOLUME key-down while ringing: Silence ringer!");
4585
4586                            // Silence the ringer.  (It's safe to call this
4587                            // even if the ringer has already been silenced.)
4588                            telecomManager.silenceRinger();
4589
4590                            // And *don't* pass this key thru to the current activity
4591                            // (which is probably the InCallScreen.)
4592                            result &= ~ACTION_PASS_TO_USER;
4593                            break;
4594                        }
4595                        if (telecomManager.isInCall()
4596                                && (result & ACTION_PASS_TO_USER) == 0) {
4597                            // If we are in call but we decided not to pass the key to
4598                            // the application, just pass it to the session service.
4599
4600                            MediaSessionLegacyHelper.getHelper(mContext)
4601                                    .sendVolumeKeyEvent(event, false);
4602                            break;
4603                        }
4604                    }
4605
4606                    if ((result & ACTION_PASS_TO_USER) == 0) {
4607                        if (mUseTvRouting) {
4608                            dispatchDirectAudioEvent(event);
4609                        } else {
4610                            // If we aren't passing to the user and no one else
4611                            // handled it send it to the session manager to
4612                            // figure out.
4613                            MediaSessionLegacyHelper.getHelper(mContext)
4614                                    .sendVolumeKeyEvent(event, true);
4615                        }
4616                        break;
4617                    }
4618                }
4619                break;
4620            }
4621
4622            case KeyEvent.KEYCODE_ENDCALL: {
4623                result &= ~ACTION_PASS_TO_USER;
4624                if (down) {
4625                    TelecomManager telecomManager = getTelecommService();
4626                    boolean hungUp = false;
4627                    if (telecomManager != null) {
4628                        hungUp = telecomManager.endCall();
4629                    }
4630                    if (interactive && !hungUp) {
4631                        mEndCallKeyHandled = false;
4632                        mHandler.postDelayed(mEndCallLongPress,
4633                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
4634                    } else {
4635                        mEndCallKeyHandled = true;
4636                    }
4637                } else {
4638                    if (!mEndCallKeyHandled) {
4639                        mHandler.removeCallbacks(mEndCallLongPress);
4640                        if (!canceled) {
4641                            if ((mEndcallBehavior
4642                                    & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
4643                                if (goHome()) {
4644                                    break;
4645                                }
4646                            }
4647                            if ((mEndcallBehavior
4648                                    & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
4649                                mPowerManager.goToSleep(event.getEventTime(),
4650                                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
4651                                isWakeKey = false;
4652                            }
4653                        }
4654                    }
4655                }
4656                break;
4657            }
4658
4659            case KeyEvent.KEYCODE_POWER: {
4660                result &= ~ACTION_PASS_TO_USER;
4661                isWakeKey = false; // wake-up will be handled separately
4662                if (down) {
4663                    interceptPowerKeyDown(event, interactive);
4664                } else {
4665                    interceptPowerKeyUp(event, interactive, canceled);
4666                }
4667                break;
4668            }
4669
4670            case KeyEvent.KEYCODE_SLEEP: {
4671                result &= ~ACTION_PASS_TO_USER;
4672                if (!mPowerManager.isInteractive()) {
4673                    useHapticFeedback = false; // suppress feedback if already non-interactive
4674                }
4675                mPowerManager.goToSleep(event.getEventTime(),
4676                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
4677                isWakeKey = false;
4678                break;
4679            }
4680
4681            case KeyEvent.KEYCODE_WAKEUP: {
4682                result &= ~ACTION_PASS_TO_USER;
4683                isWakeKey = true;
4684                break;
4685            }
4686
4687            case KeyEvent.KEYCODE_MEDIA_PLAY:
4688            case KeyEvent.KEYCODE_MEDIA_PAUSE:
4689            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
4690            case KeyEvent.KEYCODE_HEADSETHOOK:
4691            case KeyEvent.KEYCODE_MUTE:
4692            case KeyEvent.KEYCODE_MEDIA_STOP:
4693            case KeyEvent.KEYCODE_MEDIA_NEXT:
4694            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
4695            case KeyEvent.KEYCODE_MEDIA_REWIND:
4696            case KeyEvent.KEYCODE_MEDIA_RECORD:
4697            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
4698            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
4699                if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
4700                    // If the global session is active pass all media keys to it
4701                    // instead of the active window.
4702                    result &= ~ACTION_PASS_TO_USER;
4703                }
4704                if ((result & ACTION_PASS_TO_USER) == 0) {
4705                    // Only do this if we would otherwise not pass it to the user. In that
4706                    // case, the PhoneWindow class will do the same thing, except it will
4707                    // only do it if the showing app doesn't process the key on its own.
4708                    // Note that we need to make a copy of the key event here because the
4709                    // original key event will be recycled when we return.
4710                    mBroadcastWakeLock.acquire();
4711                    Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
4712                            new KeyEvent(event));
4713                    msg.setAsynchronous(true);
4714                    msg.sendToTarget();
4715                }
4716                break;
4717            }
4718
4719            case KeyEvent.KEYCODE_CALL: {
4720                if (down) {
4721                    TelecomManager telecomManager = getTelecommService();
4722                    if (telecomManager != null) {
4723                        if (telecomManager.isRinging()) {
4724                            Log.i(TAG, "interceptKeyBeforeQueueing:"
4725                                  + " CALL key-down while ringing: Answer the call!");
4726                            telecomManager.acceptRingingCall();
4727
4728                            // And *don't* pass this key thru to the current activity
4729                            // (which is presumably the InCallScreen.)
4730                            result &= ~ACTION_PASS_TO_USER;
4731                        }
4732                    }
4733                }
4734                break;
4735            }
4736            case KeyEvent.KEYCODE_VOICE_ASSIST: {
4737                // Only do this if we would otherwise not pass it to the user. In that case,
4738                // interceptKeyBeforeDispatching would apply a similar but different policy in
4739                // order to invoke voice assist actions. Note that we need to make a copy of the
4740                // key event here because the original key event will be recycled when we return.
4741                if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
4742                    mBroadcastWakeLock.acquire();
4743                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
4744                            keyguardActive ? 1 : 0, 0);
4745                    msg.setAsynchronous(true);
4746                    msg.sendToTarget();
4747                }
4748            }
4749        }
4750
4751        if (useHapticFeedback) {
4752            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
4753        }
4754
4755        if (isWakeKey) {
4756            wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey);
4757        }
4758
4759        return result;
4760    }
4761
4762    /**
4763     * Returns true if the key can have global actions attached to it.
4764     * We reserve all power management keys for the system since they require
4765     * very careful handling.
4766     */
4767    private static boolean isValidGlobalKey(int keyCode) {
4768        switch (keyCode) {
4769            case KeyEvent.KEYCODE_POWER:
4770            case KeyEvent.KEYCODE_WAKEUP:
4771            case KeyEvent.KEYCODE_SLEEP:
4772                return false;
4773            default:
4774                return true;
4775        }
4776    }
4777
4778    /**
4779     * When the screen is off we ignore some keys that might otherwise typically
4780     * be considered wake keys.  We filter them out here.
4781     *
4782     * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
4783     * is always considered a wake key.
4784     */
4785    private boolean isWakeKeyWhenScreenOff(int keyCode) {
4786        switch (keyCode) {
4787            // ignore volume keys unless docked
4788            case KeyEvent.KEYCODE_VOLUME_UP:
4789            case KeyEvent.KEYCODE_VOLUME_DOWN:
4790            case KeyEvent.KEYCODE_VOLUME_MUTE:
4791                return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
4792
4793            // ignore media and camera keys
4794            case KeyEvent.KEYCODE_MUTE:
4795            case KeyEvent.KEYCODE_HEADSETHOOK:
4796            case KeyEvent.KEYCODE_MEDIA_PLAY:
4797            case KeyEvent.KEYCODE_MEDIA_PAUSE:
4798            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
4799            case KeyEvent.KEYCODE_MEDIA_STOP:
4800            case KeyEvent.KEYCODE_MEDIA_NEXT:
4801            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
4802            case KeyEvent.KEYCODE_MEDIA_REWIND:
4803            case KeyEvent.KEYCODE_MEDIA_RECORD:
4804            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
4805            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
4806            case KeyEvent.KEYCODE_CAMERA:
4807                return false;
4808        }
4809        return true;
4810    }
4811
4812
4813    /** {@inheritDoc} */
4814    @Override
4815    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
4816        if ((policyFlags & FLAG_WAKE) != 0) {
4817            if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion)) {
4818                return 0;
4819            }
4820        }
4821
4822        if (shouldDispatchInputWhenNonInteractive()) {
4823            return ACTION_PASS_TO_USER;
4824        }
4825
4826        // If we have not passed the action up and we are in theater mode without dreaming,
4827        // there will be no dream to intercept the touch and wake into ambient.  The device should
4828        // wake up in this case.
4829        if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
4830            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming);
4831        }
4832
4833        return 0;
4834    }
4835
4836    private boolean shouldDispatchInputWhenNonInteractive() {
4837        // Send events to keyguard while the screen is on.
4838        if (isKeyguardShowingAndNotOccluded() && mDisplay != null
4839                && mDisplay.getState() != Display.STATE_OFF) {
4840            return true;
4841        }
4842
4843        // Send events to a dozing dream even if the screen is off since the dream
4844        // is in control of the state of the screen.
4845        IDreamManager dreamManager = getDreamManager();
4846
4847        try {
4848            if (dreamManager != null && dreamManager.isDreaming()) {
4849                return true;
4850            }
4851        } catch (RemoteException e) {
4852            Slog.e(TAG, "RemoteException when checking if dreaming", e);
4853        }
4854
4855        // Otherwise, consume events since the user can't see what is being
4856        // interacted with.
4857        return false;
4858    }
4859
4860    private void dispatchDirectAudioEvent(KeyEvent event) {
4861        if (event.getAction() != KeyEvent.ACTION_DOWN) {
4862            return;
4863        }
4864        int keyCode = event.getKeyCode();
4865        int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND;
4866        String pkgName = mContext.getOpPackageName();
4867        switch (keyCode) {
4868            case KeyEvent.KEYCODE_VOLUME_UP:
4869                try {
4870                    if (mUseMasterVolume) {
4871                        getAudioService().adjustMasterVolume(AudioManager.ADJUST_RAISE, flags,
4872                                pkgName);
4873                    } else {
4874                        getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
4875                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName);
4876                    }
4877                } catch (RemoteException e) {
4878                    Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
4879                }
4880                break;
4881            case KeyEvent.KEYCODE_VOLUME_DOWN:
4882                try {
4883                    if (mUseMasterVolume) {
4884                        getAudioService().adjustMasterVolume(AudioManager.ADJUST_LOWER, flags,
4885                                pkgName);
4886                    } else {
4887                        getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
4888                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName);
4889                    }
4890                } catch (RemoteException e) {
4891                    Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
4892                }
4893                break;
4894            case KeyEvent.KEYCODE_VOLUME_MUTE:
4895                try {
4896                    if (event.getRepeatCount() == 0) {
4897                        if (mUseMasterVolume) {
4898                            getAudioService().adjustMasterVolume(AudioManager.ADJUST_TOGGLE_MUTE,
4899                                    flags, pkgName);
4900                        } else {
4901                            getAudioService().adjustSuggestedStreamVolume(
4902                                    AudioManager.ADJUST_TOGGLE_MUTE,
4903                                    AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName);
4904                        }
4905                    }
4906                } catch (RemoteException e) {
4907                    Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
4908                }
4909                break;
4910        }
4911    }
4912
4913    void dispatchMediaKeyWithWakeLock(KeyEvent event) {
4914        if (DEBUG_INPUT) {
4915            Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
4916        }
4917
4918        if (mHavePendingMediaKeyRepeatWithWakeLock) {
4919            if (DEBUG_INPUT) {
4920                Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
4921            }
4922
4923            mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
4924            mHavePendingMediaKeyRepeatWithWakeLock = false;
4925            mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
4926        }
4927
4928        dispatchMediaKeyWithWakeLockToAudioService(event);
4929
4930        if (event.getAction() == KeyEvent.ACTION_DOWN
4931                && event.getRepeatCount() == 0) {
4932            mHavePendingMediaKeyRepeatWithWakeLock = true;
4933
4934            Message msg = mHandler.obtainMessage(
4935                    MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
4936            msg.setAsynchronous(true);
4937            mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
4938        } else {
4939            mBroadcastWakeLock.release();
4940        }
4941    }
4942
4943    void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
4944        mHavePendingMediaKeyRepeatWithWakeLock = false;
4945
4946        KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
4947                SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
4948        if (DEBUG_INPUT) {
4949            Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
4950        }
4951
4952        dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
4953        mBroadcastWakeLock.release();
4954    }
4955
4956    void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
4957        if (ActivityManagerNative.isSystemReady()) {
4958            MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
4959        }
4960    }
4961
4962    void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
4963        Intent voiceIntent =
4964            new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
4965        voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
4966        mContext.startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
4967        mBroadcastWakeLock.release();
4968    }
4969
4970    BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
4971        @Override
4972        public void onReceive(Context context, Intent intent) {
4973            if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
4974                mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
4975                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
4976            } else {
4977                try {
4978                    IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
4979                            ServiceManager.getService(Context.UI_MODE_SERVICE));
4980                    mUiMode = uiModeService.getCurrentModeType();
4981                } catch (RemoteException e) {
4982                }
4983            }
4984            updateRotation(true);
4985            synchronized (mLock) {
4986                updateOrientationListenerLp();
4987            }
4988        }
4989    };
4990
4991    BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
4992        @Override
4993        public void onReceive(Context context, Intent intent) {
4994            if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
4995                if (mKeyguardDelegate != null) {
4996                    mKeyguardDelegate.onDreamingStarted();
4997                }
4998            } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
4999                if (mKeyguardDelegate != null) {
5000                    mKeyguardDelegate.onDreamingStopped();
5001                }
5002            }
5003        }
5004    };
5005
5006    BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
5007        @Override
5008        public void onReceive(Context context, Intent intent) {
5009            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
5010                // tickle the settings observer: this first ensures that we're
5011                // observing the relevant settings for the newly-active user,
5012                // and then updates our own bookkeeping based on the now-
5013                // current user.
5014                mSettingsObserver.onChange(false);
5015
5016                // force a re-application of focused window sysui visibility.
5017                // the window may never have been shown for this user
5018                // e.g. the keyguard when going through the new-user setup flow
5019                synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
5020                    mLastSystemUiFlags = 0;
5021                    updateSystemUiVisibilityLw();
5022                }
5023            }
5024        }
5025    };
5026
5027    private final Runnable mRequestTransientNav = new Runnable() {
5028        @Override
5029        public void run() {
5030            requestTransientBars(mNavigationBar);
5031        }
5032    };
5033
5034    private void requestTransientBars(WindowState swipeTarget) {
5035        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
5036            if (!isUserSetupComplete()) {
5037                // Swipe-up for navigation bar is disabled during setup
5038                return;
5039            }
5040            boolean sb = mStatusBarController.checkShowTransientBarLw();
5041            boolean nb = mNavigationBarController.checkShowTransientBarLw();
5042            if (sb || nb) {
5043                // Don't show status bar when swiping on already visible navigation bar
5044                if (!nb && swipeTarget == mNavigationBar) {
5045                    if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
5046                    return;
5047                }
5048                if (sb) mStatusBarController.showTransient();
5049                if (nb) mNavigationBarController.showTransient();
5050                mImmersiveModeConfirmation.confirmCurrentPrompt();
5051                updateSystemUiVisibilityLw();
5052            }
5053        }
5054    }
5055
5056    // Called on the PowerManager's Notifier thread.
5057    @Override
5058    public void goingToSleep(int why) {
5059        EventLog.writeEvent(70000, 0);
5060        if (DEBUG_WAKEUP) Slog.i(TAG, "Going to sleep...");
5061
5062        // We must get this work done here because the power manager will drop
5063        // the wake lock and let the system suspend once this function returns.
5064        synchronized (mLock) {
5065            mAwake = false;
5066            mKeyguardDrawComplete = false;
5067            updateWakeGestureListenerLp();
5068            updateOrientationListenerLp();
5069            updateLockScreenTimeout();
5070        }
5071
5072        if (mKeyguardDelegate != null) {
5073            mKeyguardDelegate.onScreenTurnedOff(why);
5074        }
5075    }
5076
5077    private void wakeUpFromPowerKey(long eventTime) {
5078        wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey);
5079    }
5080
5081    private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode) {
5082        if (!wakeInTheaterMode && isTheaterModeEnabled()) {
5083            return false;
5084        }
5085
5086        mPowerManager.wakeUp(wakeTime);
5087        return true;
5088    }
5089
5090    // Called on the PowerManager's Notifier thread.
5091    @Override
5092    public void wakingUp() {
5093        EventLog.writeEvent(70000, 1);
5094        if (DEBUG_WAKEUP) Slog.i(TAG, "Waking up...");
5095
5096        // Since goToSleep performs these functions synchronously, we must
5097        // do the same here.  We cannot post this work to a handler because
5098        // that might cause it to become reordered with respect to what
5099        // may happen in a future call to goToSleep.
5100        synchronized (mLock) {
5101            mAwake = true;
5102            mKeyguardDrawComplete = false;
5103            if (mKeyguardDelegate != null) {
5104                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
5105                mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
5106            }
5107
5108            updateWakeGestureListenerLp();
5109            updateOrientationListenerLp();
5110            updateLockScreenTimeout();
5111        }
5112
5113        if (mKeyguardDelegate != null) {
5114            mKeyguardDelegate.onScreenTurnedOn(mKeyguardDelegateCallback);
5115            // ... eventually calls finishKeyguardDrawn
5116        } else {
5117            if (DEBUG_WAKEUP) Slog.d(TAG, "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
5118            finishKeyguardDrawn();
5119        }
5120    }
5121
5122    private void finishKeyguardDrawn() {
5123        synchronized (mLock) {
5124            if (!mAwake || mKeyguardDrawComplete) {
5125                return; // spurious
5126            }
5127
5128            mKeyguardDrawComplete = true;
5129            if (mKeyguardDelegate != null) {
5130                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
5131            }
5132        }
5133
5134        finishScreenTurningOn();
5135    }
5136
5137    // Called on the DisplayManager's DisplayPowerController thread.
5138    @Override
5139    public void screenTurnedOff() {
5140        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
5141
5142        synchronized (mLock) {
5143            mScreenOnEarly = false;
5144            mScreenOnFully = false;
5145            mWindowManagerDrawComplete = false;
5146            mScreenOnListener = null;
5147            updateOrientationListenerLp();
5148        }
5149    }
5150
5151    // Called on the DisplayManager's DisplayPowerController thread.
5152    @Override
5153    public void screenTurningOn(final ScreenOnListener screenOnListener) {
5154        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
5155
5156        synchronized (mLock) {
5157            mScreenOnEarly = true;
5158            mScreenOnFully = false;
5159            mWindowManagerDrawComplete = false;
5160            mScreenOnListener = screenOnListener;
5161            updateOrientationListenerLp();
5162        }
5163
5164        mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
5165                WAITING_FOR_DRAWN_TIMEOUT);
5166        // ... eventually calls finishWindowsDrawn
5167    }
5168
5169    private void finishWindowsDrawn() {
5170        synchronized (mLock) {
5171            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
5172                return; // spurious
5173            }
5174
5175            mWindowManagerDrawComplete = true;
5176        }
5177
5178        finishScreenTurningOn();
5179    }
5180
5181    private void finishScreenTurningOn() {
5182        final ScreenOnListener listener;
5183        final boolean enableScreen;
5184        synchronized (mLock) {
5185            if (DEBUG_WAKEUP) Slog.d(TAG,
5186                    "finishScreenTurningOn: mAwake=" + mAwake
5187                            + ", mScreenOnEarly=" + mScreenOnEarly
5188                            + ", mScreenOnFully=" + mScreenOnFully
5189                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
5190                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
5191
5192            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
5193                    || (mAwake && !mKeyguardDrawComplete)) {
5194                return; // spurious or not ready yet
5195            }
5196
5197            if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
5198            listener = mScreenOnListener;
5199            mScreenOnListener = null;
5200            mScreenOnFully = true;
5201
5202            // Remember the first time we draw the keyguard so we know when we're done with
5203            // the main part of booting and can enable the screen and hide boot messages.
5204            if (!mKeyguardDrawnOnce && mAwake) {
5205                mKeyguardDrawnOnce = true;
5206                enableScreen = true;
5207                if (mBootMessageNeedsHiding) {
5208                    mBootMessageNeedsHiding = false;
5209                    hideBootMessages();
5210                }
5211            } else {
5212                enableScreen = false;
5213            }
5214        }
5215
5216        if (listener != null) {
5217            listener.onScreenOn();
5218        }
5219
5220        if (enableScreen) {
5221            try {
5222                mWindowManager.enableScreenIfNeeded();
5223            } catch (RemoteException unhandled) {
5224            }
5225        }
5226    }
5227
5228    private void handleHideBootMessage() {
5229        synchronized (mLock) {
5230            if (!mKeyguardDrawnOnce) {
5231                mBootMessageNeedsHiding = true;
5232                return; // keyguard hasn't drawn the first time yet, not done booting
5233            }
5234        }
5235
5236        if (mBootMsgDialog != null) {
5237            if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
5238            mBootMsgDialog.dismiss();
5239            mBootMsgDialog = null;
5240        }
5241    }
5242
5243    @Override
5244    public boolean isScreenOn() {
5245        return mScreenOnFully;
5246    }
5247
5248    /** {@inheritDoc} */
5249    @Override
5250    public void enableKeyguard(boolean enabled) {
5251        if (mKeyguardDelegate != null) {
5252            mKeyguardDelegate.setKeyguardEnabled(enabled);
5253        }
5254    }
5255
5256    /** {@inheritDoc} */
5257    @Override
5258    public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
5259        if (mKeyguardDelegate != null) {
5260            mKeyguardDelegate.verifyUnlock(callback);
5261        }
5262    }
5263
5264    private boolean isKeyguardShowingAndNotOccluded() {
5265        if (mKeyguardDelegate == null) return false;
5266        return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
5267    }
5268
5269    /** {@inheritDoc} */
5270    @Override
5271    public boolean isKeyguardLocked() {
5272        return keyguardOn();
5273    }
5274
5275    /** {@inheritDoc} */
5276    @Override
5277    public boolean isKeyguardSecure() {
5278        if (mKeyguardDelegate == null) return false;
5279        return mKeyguardDelegate.isSecure();
5280    }
5281
5282    /** {@inheritDoc} */
5283    @Override
5284    public boolean inKeyguardRestrictedKeyInputMode() {
5285        if (mKeyguardDelegate == null) return false;
5286        return mKeyguardDelegate.isInputRestricted();
5287    }
5288
5289    @Override
5290    public void dismissKeyguardLw() {
5291        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
5292            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
5293            mHandler.post(new Runnable() {
5294                @Override
5295                public void run() {
5296                    // ask the keyguard to prompt the user to authenticate if necessary
5297                    mKeyguardDelegate.dismiss();
5298                }
5299            });
5300        }
5301    }
5302
5303    public void notifyActivityDrawnForKeyguardLw() {
5304        if (mKeyguardDelegate != null) {
5305            mHandler.post(new Runnable() {
5306                @Override
5307                public void run() {
5308                    mKeyguardDelegate.onActivityDrawn();
5309                }
5310            });
5311        }
5312    }
5313
5314    @Override
5315    public boolean isKeyguardDrawnLw() {
5316        synchronized (mLock) {
5317            return mKeyguardDrawnOnce;
5318        }
5319    }
5320
5321    @Override
5322    public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
5323        if (mKeyguardDelegate != null) {
5324            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
5325            mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
5326        }
5327    }
5328
5329    void sendCloseSystemWindows() {
5330        PhoneWindow.sendCloseSystemWindows(mContext, null);
5331    }
5332
5333    void sendCloseSystemWindows(String reason) {
5334        PhoneWindow.sendCloseSystemWindows(mContext, reason);
5335    }
5336
5337    @Override
5338    public int rotationForOrientationLw(int orientation, int lastRotation) {
5339        if (false) {
5340            Slog.v(TAG, "rotationForOrientationLw(orient="
5341                        + orientation + ", last=" + lastRotation
5342                        + "); user=" + mUserRotation + " "
5343                        + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
5344                            ? "USER_ROTATION_LOCKED" : "")
5345                        );
5346        }
5347
5348        if (mForceDefaultOrientation) {
5349            return Surface.ROTATION_0;
5350        }
5351
5352        synchronized (mLock) {
5353            int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
5354            if (sensorRotation < 0) {
5355                sensorRotation = lastRotation;
5356            }
5357
5358            final int preferredRotation;
5359            if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
5360                // Ignore sensor when lid switch is open and rotation is forced.
5361                preferredRotation = mLidOpenRotation;
5362            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
5363                    && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
5364                // Ignore sensor when in car dock unless explicitly enabled.
5365                // This case can override the behavior of NOSENSOR, and can also
5366                // enable 180 degree rotation while docked.
5367                preferredRotation = mCarDockEnablesAccelerometer
5368                        ? sensorRotation : mCarDockRotation;
5369            } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
5370                    || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
5371                    || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
5372                    && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
5373                // Ignore sensor when in desk dock unless explicitly enabled.
5374                // This case can override the behavior of NOSENSOR, and can also
5375                // enable 180 degree rotation while docked.
5376                preferredRotation = mDeskDockEnablesAccelerometer
5377                        ? sensorRotation : mDeskDockRotation;
5378            } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
5379                // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
5380                // Note that the dock orientation overrides the HDMI orientation.
5381                preferredRotation = mDemoHdmiRotation;
5382            } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
5383                    && mUndockedHdmiRotation >= 0) {
5384                // Ignore sensor when plugged into HDMI and an undocked orientation has
5385                // been specified in the configuration (only for legacy devices without
5386                // full multi-display support).
5387                // Note that the dock orientation overrides the HDMI orientation.
5388                preferredRotation = mUndockedHdmiRotation;
5389            } else if (mDemoRotationLock) {
5390                // Ignore sensor when demo rotation lock is enabled.
5391                // Note that the dock orientation and HDMI rotation lock override this.
5392                preferredRotation = mDemoRotation;
5393            } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
5394                // Application just wants to remain locked in the last rotation.
5395                preferredRotation = lastRotation;
5396            } else if (!mSupportAutoRotation) {
5397                // If we don't support auto-rotation then bail out here and ignore
5398                // the sensor and any rotation lock settings.
5399                preferredRotation = -1;
5400            } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
5401                            && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
5402                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
5403                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
5404                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
5405                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
5406                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
5407                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
5408                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
5409                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
5410                // Otherwise, use sensor only if requested by the application or enabled
5411                // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
5412                if (mAllowAllRotations < 0) {
5413                    // Can't read this during init() because the context doesn't
5414                    // have display metrics at that time so we cannot determine
5415                    // tablet vs. phone then.
5416                    mAllowAllRotations = mContext.getResources().getBoolean(
5417                            com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
5418                }
5419                if (sensorRotation != Surface.ROTATION_180
5420                        || mAllowAllRotations == 1
5421                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
5422                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
5423                    preferredRotation = sensorRotation;
5424                } else {
5425                    preferredRotation = lastRotation;
5426                }
5427            } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
5428                    && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
5429                // Apply rotation lock.  Does not apply to NOSENSOR.
5430                // The idea is that the user rotation expresses a weak preference for the direction
5431                // of gravity and as NOSENSOR is never affected by gravity, then neither should
5432                // NOSENSOR be affected by rotation lock (although it will be affected by docks).
5433                preferredRotation = mUserRotation;
5434            } else {
5435                // No overriding preference.
5436                // We will do exactly what the application asked us to do.
5437                preferredRotation = -1;
5438            }
5439
5440            switch (orientation) {
5441                case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
5442                    // Return portrait unless overridden.
5443                    if (isAnyPortrait(preferredRotation)) {
5444                        return preferredRotation;
5445                    }
5446                    return mPortraitRotation;
5447
5448                case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
5449                    // Return landscape unless overridden.
5450                    if (isLandscapeOrSeascape(preferredRotation)) {
5451                        return preferredRotation;
5452                    }
5453                    return mLandscapeRotation;
5454
5455                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
5456                    // Return reverse portrait unless overridden.
5457                    if (isAnyPortrait(preferredRotation)) {
5458                        return preferredRotation;
5459                    }
5460                    return mUpsideDownRotation;
5461
5462                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
5463                    // Return seascape unless overridden.
5464                    if (isLandscapeOrSeascape(preferredRotation)) {
5465                        return preferredRotation;
5466                    }
5467                    return mSeascapeRotation;
5468
5469                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
5470                case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
5471                    // Return either landscape rotation.
5472                    if (isLandscapeOrSeascape(preferredRotation)) {
5473                        return preferredRotation;
5474                    }
5475                    if (isLandscapeOrSeascape(lastRotation)) {
5476                        return lastRotation;
5477                    }
5478                    return mLandscapeRotation;
5479
5480                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
5481                case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
5482                    // Return either portrait rotation.
5483                    if (isAnyPortrait(preferredRotation)) {
5484                        return preferredRotation;
5485                    }
5486                    if (isAnyPortrait(lastRotation)) {
5487                        return lastRotation;
5488                    }
5489                    return mPortraitRotation;
5490
5491                default:
5492                    // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
5493                    // just return the preferred orientation we already calculated.
5494                    if (preferredRotation >= 0) {
5495                        return preferredRotation;
5496                    }
5497                    return Surface.ROTATION_0;
5498            }
5499        }
5500    }
5501
5502    @Override
5503    public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
5504        switch (orientation) {
5505            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
5506            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
5507            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
5508                return isAnyPortrait(rotation);
5509
5510            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
5511            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
5512            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
5513                return isLandscapeOrSeascape(rotation);
5514
5515            default:
5516                return true;
5517        }
5518    }
5519
5520    @Override
5521    public void setRotationLw(int rotation) {
5522        mOrientationListener.setCurrentRotation(rotation);
5523    }
5524
5525    private boolean isLandscapeOrSeascape(int rotation) {
5526        return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
5527    }
5528
5529    private boolean isAnyPortrait(int rotation) {
5530        return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
5531    }
5532
5533    @Override
5534    public int getUserRotationMode() {
5535        return Settings.System.getIntForUser(mContext.getContentResolver(),
5536                Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
5537                        WindowManagerPolicy.USER_ROTATION_FREE :
5538                                WindowManagerPolicy.USER_ROTATION_LOCKED;
5539    }
5540
5541    // User rotation: to be used when all else fails in assigning an orientation to the device
5542    @Override
5543    public void setUserRotationMode(int mode, int rot) {
5544        ContentResolver res = mContext.getContentResolver();
5545
5546        // mUserRotationMode and mUserRotation will be assigned by the content observer
5547        if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
5548            Settings.System.putIntForUser(res,
5549                    Settings.System.USER_ROTATION,
5550                    rot,
5551                    UserHandle.USER_CURRENT);
5552            Settings.System.putIntForUser(res,
5553                    Settings.System.ACCELEROMETER_ROTATION,
5554                    0,
5555                    UserHandle.USER_CURRENT);
5556        } else {
5557            Settings.System.putIntForUser(res,
5558                    Settings.System.ACCELEROMETER_ROTATION,
5559                    1,
5560                    UserHandle.USER_CURRENT);
5561        }
5562    }
5563
5564    @Override
5565    public void setSafeMode(boolean safeMode) {
5566        mSafeMode = safeMode;
5567        performHapticFeedbackLw(null, safeMode
5568                ? HapticFeedbackConstants.SAFE_MODE_ENABLED
5569                : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
5570    }
5571
5572    static long[] getLongIntArray(Resources r, int resid) {
5573        int[] ar = r.getIntArray(resid);
5574        if (ar == null) {
5575            return null;
5576        }
5577        long[] out = new long[ar.length];
5578        for (int i=0; i<ar.length; i++) {
5579            out[i] = ar[i];
5580        }
5581        return out;
5582    }
5583
5584    /** {@inheritDoc} */
5585    @Override
5586    public void systemReady() {
5587        mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
5588        mKeyguardDelegate.onSystemReady();
5589
5590        readCameraLensCoverState();
5591        updateUiMode();
5592        synchronized (mLock) {
5593            updateOrientationListenerLp();
5594            mSystemReady = true;
5595            mHandler.post(new Runnable() {
5596                @Override
5597                public void run() {
5598                    updateSettings();
5599                }
5600            });
5601        }
5602    }
5603
5604    /** {@inheritDoc} */
5605    @Override
5606    public void systemBooted() {
5607        if (mKeyguardDelegate != null) {
5608            mKeyguardDelegate.bindService(mContext);
5609            mKeyguardDelegate.onBootCompleted();
5610        }
5611        synchronized (mLock) {
5612            mSystemBooted = true;
5613        }
5614        wakingUp();
5615        screenTurningOn(null);
5616    }
5617
5618    ProgressDialog mBootMsgDialog = null;
5619
5620    /** {@inheritDoc} */
5621    @Override
5622    public void showBootMessage(final CharSequence msg, final boolean always) {
5623        mHandler.post(new Runnable() {
5624            @Override public void run() {
5625                if (mBootMsgDialog == null) {
5626                    int theme;
5627                    if (mContext.getPackageManager().hasSystemFeature(
5628                            PackageManager.FEATURE_WATCH)) {
5629                        theme = com.android.internal.R.style.Theme_Micro_Dialog_Alert;
5630                    } else if (mContext.getPackageManager().hasSystemFeature(
5631                            PackageManager.FEATURE_TELEVISION)) {
5632                        theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
5633                    } else {
5634                        theme = 0;
5635                    }
5636
5637                    mBootMsgDialog = new ProgressDialog(mContext, theme) {
5638                        // This dialog will consume all events coming in to
5639                        // it, to avoid it trying to do things too early in boot.
5640                        @Override public boolean dispatchKeyEvent(KeyEvent event) {
5641                            return true;
5642                        }
5643                        @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
5644                            return true;
5645                        }
5646                        @Override public boolean dispatchTouchEvent(MotionEvent ev) {
5647                            return true;
5648                        }
5649                        @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
5650                            return true;
5651                        }
5652                        @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
5653                            return true;
5654                        }
5655                        @Override public boolean dispatchPopulateAccessibilityEvent(
5656                                AccessibilityEvent event) {
5657                            return true;
5658                        }
5659                    };
5660                    if (mContext.getPackageManager().isUpgrade()) {
5661                        mBootMsgDialog.setTitle(R.string.android_upgrading_title);
5662                    } else {
5663                        mBootMsgDialog.setTitle(R.string.android_start_title);
5664                    }
5665                    mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
5666                    mBootMsgDialog.setIndeterminate(true);
5667                    mBootMsgDialog.getWindow().setType(
5668                            WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
5669                    mBootMsgDialog.getWindow().addFlags(
5670                            WindowManager.LayoutParams.FLAG_DIM_BEHIND
5671                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
5672                    mBootMsgDialog.getWindow().setDimAmount(1);
5673                    WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
5674                    lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
5675                    mBootMsgDialog.getWindow().setAttributes(lp);
5676                    mBootMsgDialog.setCancelable(false);
5677                    mBootMsgDialog.show();
5678                }
5679                mBootMsgDialog.setMessage(msg);
5680            }
5681        });
5682    }
5683
5684    /** {@inheritDoc} */
5685    @Override
5686    public void hideBootMessages() {
5687        mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
5688    }
5689
5690    /** {@inheritDoc} */
5691    @Override
5692    public void userActivity() {
5693        // ***************************************
5694        // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
5695        // ***************************************
5696        // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
5697        // WITH ITS LOCKS HELD.
5698        //
5699        // This code must be VERY careful about the locks
5700        // it acquires.
5701        // In fact, the current code acquires way too many,
5702        // and probably has lurking deadlocks.
5703
5704        synchronized (mScreenLockTimeout) {
5705            if (mLockScreenTimerActive) {
5706                // reset the timer
5707                mHandler.removeCallbacks(mScreenLockTimeout);
5708                mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
5709            }
5710        }
5711    }
5712
5713    class ScreenLockTimeout implements Runnable {
5714        Bundle options;
5715
5716        @Override
5717        public void run() {
5718            synchronized (this) {
5719                if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
5720                if (mKeyguardDelegate != null) {
5721                    mKeyguardDelegate.doKeyguardTimeout(options);
5722                }
5723                mLockScreenTimerActive = false;
5724                options = null;
5725            }
5726        }
5727
5728        public void setLockOptions(Bundle options) {
5729            this.options = options;
5730        }
5731    }
5732
5733    ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
5734
5735    @Override
5736    public void lockNow(Bundle options) {
5737        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
5738        mHandler.removeCallbacks(mScreenLockTimeout);
5739        if (options != null) {
5740            // In case multiple calls are made to lockNow, we don't wipe out the options
5741            // until the runnable actually executes.
5742            mScreenLockTimeout.setLockOptions(options);
5743        }
5744        mHandler.post(mScreenLockTimeout);
5745    }
5746
5747    private void updateLockScreenTimeout() {
5748        synchronized (mScreenLockTimeout) {
5749            boolean enable = (mAllowLockscreenWhenOn && mAwake &&
5750                    mKeyguardDelegate != null && mKeyguardDelegate.isSecure());
5751            if (mLockScreenTimerActive != enable) {
5752                if (enable) {
5753                    if (localLOGV) Log.v(TAG, "setting lockscreen timer");
5754                    mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
5755                } else {
5756                    if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
5757                    mHandler.removeCallbacks(mScreenLockTimeout);
5758                }
5759                mLockScreenTimerActive = enable;
5760            }
5761        }
5762    }
5763
5764    /** {@inheritDoc} */
5765    @Override
5766    public void enableScreenAfterBoot() {
5767        readLidState();
5768        applyLidSwitchState();
5769        updateRotation(true);
5770    }
5771
5772    private void applyLidSwitchState() {
5773        if (mLidState == LID_CLOSED && mLidControlsSleep) {
5774            mPowerManager.goToSleep(SystemClock.uptimeMillis(),
5775                    PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
5776                    PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
5777        }
5778
5779        synchronized (mLock) {
5780            updateWakeGestureListenerLp();
5781        }
5782    }
5783
5784    void updateUiMode() {
5785        if (mUiModeManager == null) {
5786            mUiModeManager = IUiModeManager.Stub.asInterface(
5787                    ServiceManager.getService(Context.UI_MODE_SERVICE));
5788        }
5789        try {
5790            mUiMode = mUiModeManager.getCurrentModeType();
5791        } catch (RemoteException e) {
5792        }
5793    }
5794
5795    void updateRotation(boolean alwaysSendConfiguration) {
5796        try {
5797            //set orientation on WindowManager
5798            mWindowManager.updateRotation(alwaysSendConfiguration, false);
5799        } catch (RemoteException e) {
5800            // Ignore
5801        }
5802    }
5803
5804    void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
5805        try {
5806            //set orientation on WindowManager
5807            mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
5808        } catch (RemoteException e) {
5809            // Ignore
5810        }
5811    }
5812
5813    /**
5814     * Return an Intent to launch the currently active dock app as home.  Returns
5815     * null if the standard home should be launched, which is the case if any of the following is
5816     * true:
5817     * <ul>
5818     *  <li>The device is not in either car mode or desk mode
5819     *  <li>The device is in car mode but ENABLE_CAR_DOCK_HOME_CAPTURE is false
5820     *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
5821     *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
5822     *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
5823     * </ul>
5824     * @return A dock intent.
5825     */
5826    Intent createHomeDockIntent() {
5827        Intent intent = null;
5828
5829        // What home does is based on the mode, not the dock state.  That
5830        // is, when in car mode you should be taken to car home regardless
5831        // of whether we are actually in a car dock.
5832        if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
5833            if (ENABLE_CAR_DOCK_HOME_CAPTURE) {
5834                intent = mCarDockIntent;
5835            }
5836        } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
5837            if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
5838                intent = mDeskDockIntent;
5839            }
5840        } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
5841                && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
5842                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
5843                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
5844            // Always launch dock home from home when watch is docked, if it exists.
5845            intent = mDeskDockIntent;
5846        }
5847
5848        if (intent == null) {
5849            return null;
5850        }
5851
5852        ActivityInfo ai = null;
5853        ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
5854                intent,
5855                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
5856                mCurrentUserId);
5857        if (info != null) {
5858            ai = info.activityInfo;
5859        }
5860        if (ai != null
5861                && ai.metaData != null
5862                && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
5863            intent = new Intent(intent);
5864            intent.setClassName(ai.packageName, ai.name);
5865            return intent;
5866        }
5867
5868        return null;
5869    }
5870
5871    void startDockOrHome(boolean fromHomeKey) {
5872        awakenDreams();
5873
5874        Intent dock = createHomeDockIntent();
5875        if (dock != null) {
5876            try {
5877                if (fromHomeKey) {
5878                    dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
5879                }
5880                mContext.startActivityAsUser(dock, UserHandle.CURRENT);
5881                return;
5882            } catch (ActivityNotFoundException e) {
5883            }
5884        }
5885
5886        Intent intent;
5887
5888        if (fromHomeKey) {
5889            intent = new Intent(mHomeIntent);
5890            intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
5891        } else {
5892            intent = mHomeIntent;
5893        }
5894
5895        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
5896    }
5897
5898    /**
5899     * goes to the home screen
5900     * @return whether it did anything
5901     */
5902    boolean goHome() {
5903        if (false) {
5904            // This code always brings home to the front.
5905            try {
5906                ActivityManagerNative.getDefault().stopAppSwitches();
5907            } catch (RemoteException e) {
5908            }
5909            sendCloseSystemWindows();
5910            startDockOrHome(false /*fromHomeKey*/);
5911        } else {
5912            // This code brings home to the front or, if it is already
5913            // at the front, puts the device to sleep.
5914            try {
5915                if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
5916                    /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
5917                    Log.d(TAG, "UTS-TEST-MODE");
5918                } else {
5919                    ActivityManagerNative.getDefault().stopAppSwitches();
5920                    sendCloseSystemWindows();
5921                    Intent dock = createHomeDockIntent();
5922                    if (dock != null) {
5923                        int result = ActivityManagerNative.getDefault()
5924                                .startActivityAsUser(null, null, dock,
5925                                        dock.resolveTypeIfNeeded(mContext.getContentResolver()),
5926                                        null, null, 0,
5927                                        ActivityManager.START_FLAG_ONLY_IF_NEEDED,
5928                                        null, null, UserHandle.USER_CURRENT);
5929                        if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
5930                            return false;
5931                        }
5932                    }
5933                }
5934                int result = ActivityManagerNative.getDefault()
5935                        .startActivityAsUser(null, null, mHomeIntent,
5936                                mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
5937                                null, null, 0,
5938                                ActivityManager.START_FLAG_ONLY_IF_NEEDED,
5939                                null, null, UserHandle.USER_CURRENT);
5940                if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
5941                    return false;
5942                }
5943            } catch (RemoteException ex) {
5944                // bummer, the activity manager, which is in this process, is dead
5945            }
5946        }
5947        return true;
5948    }
5949
5950    @Override
5951    public void setCurrentOrientationLw(int newOrientation) {
5952        synchronized (mLock) {
5953            if (newOrientation != mCurrentAppOrientation) {
5954                mCurrentAppOrientation = newOrientation;
5955                updateOrientationListenerLp();
5956            }
5957        }
5958    }
5959
5960    private void performAuditoryFeedbackForAccessibilityIfNeed() {
5961        if (!isGlobalAccessibilityGestureEnabled()) {
5962            return;
5963        }
5964        AudioManager audioManager = (AudioManager) mContext.getSystemService(
5965                Context.AUDIO_SERVICE);
5966        if (audioManager.isSilentMode()) {
5967            return;
5968        }
5969        Ringtone ringTone = RingtoneManager.getRingtone(mContext,
5970                Settings.System.DEFAULT_NOTIFICATION_URI);
5971        ringTone.setStreamType(AudioManager.STREAM_MUSIC);
5972        ringTone.play();
5973    }
5974
5975    private boolean isTheaterModeEnabled() {
5976        return Settings.Global.getInt(mContext.getContentResolver(),
5977                Settings.Global.THEATER_MODE_ON, 0) == 1;
5978    }
5979
5980    private boolean isGlobalAccessibilityGestureEnabled() {
5981        return Settings.Global.getInt(mContext.getContentResolver(),
5982                Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1;
5983    }
5984
5985    @Override
5986    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
5987        if (!mVibrator.hasVibrator()) {
5988            return false;
5989        }
5990        final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
5991                Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
5992        if (hapticsDisabled && !always) {
5993            return false;
5994        }
5995        long[] pattern = null;
5996        switch (effectId) {
5997            case HapticFeedbackConstants.LONG_PRESS:
5998                pattern = mLongPressVibePattern;
5999                break;
6000            case HapticFeedbackConstants.VIRTUAL_KEY:
6001                pattern = mVirtualKeyVibePattern;
6002                break;
6003            case HapticFeedbackConstants.KEYBOARD_TAP:
6004                pattern = mKeyboardTapVibePattern;
6005                break;
6006            case HapticFeedbackConstants.CLOCK_TICK:
6007                pattern = mClockTickVibePattern;
6008                break;
6009            case HapticFeedbackConstants.CALENDAR_DATE:
6010                pattern = mCalendarDateVibePattern;
6011                break;
6012            case HapticFeedbackConstants.SAFE_MODE_DISABLED:
6013                pattern = mSafeModeDisabledVibePattern;
6014                break;
6015            case HapticFeedbackConstants.SAFE_MODE_ENABLED:
6016                pattern = mSafeModeEnabledVibePattern;
6017                break;
6018            default:
6019                return false;
6020        }
6021        int owningUid;
6022        String owningPackage;
6023        if (win != null) {
6024            owningUid = win.getOwningUid();
6025            owningPackage = win.getOwningPackage();
6026        } else {
6027            owningUid = android.os.Process.myUid();
6028            owningPackage = mContext.getOpPackageName();
6029        }
6030        if (pattern.length == 1) {
6031            // One-shot vibration
6032            mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES);
6033        } else {
6034            // Pattern vibration
6035            mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES);
6036        }
6037        return true;
6038    }
6039
6040    @Override
6041    public void keepScreenOnStartedLw() {
6042    }
6043
6044    @Override
6045    public void keepScreenOnStoppedLw() {
6046        if (isKeyguardShowingAndNotOccluded()) {
6047            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
6048        }
6049    }
6050
6051    private int updateSystemUiVisibilityLw() {
6052        // If there is no window focused, there will be nobody to handle the events
6053        // anyway, so just hang on in whatever state we're in until things settle down.
6054        final WindowState win = mFocusedWindow != null ? mFocusedWindow
6055                : mTopFullscreenOpaqueWindowState;
6056        if (win == null) {
6057            return 0;
6058        }
6059        if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) {
6060            // We are updating at a point where the keyguard has gotten
6061            // focus, but we were last in a state where the top window is
6062            // hiding it.  This is probably because the keyguard as been
6063            // shown while the top window was displayed, so we want to ignore
6064            // it here because this is just a very transient change and it
6065            // will quickly lose focus once it correctly gets hidden.
6066            return 0;
6067        }
6068
6069        int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
6070                & ~mResettingSystemUiFlags
6071                & ~mForceClearedSystemUiFlags;
6072        if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
6073            tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
6074        }
6075        tmpVisibility = updateLightStatusBarLw(tmpVisibility);
6076        final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
6077        final int diff = visibility ^ mLastSystemUiFlags;
6078        final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
6079        if (diff == 0 && mLastFocusNeedsMenu == needsMenu
6080                && mFocusedApp == win.getAppToken()) {
6081            return 0;
6082        }
6083        mLastSystemUiFlags = visibility;
6084        mLastFocusNeedsMenu = needsMenu;
6085        mFocusedApp = win.getAppToken();
6086        mHandler.post(new Runnable() {
6087                @Override
6088                public void run() {
6089                    try {
6090                        IStatusBarService statusbar = getStatusBarService();
6091                        if (statusbar != null) {
6092                            statusbar.setSystemUiVisibility(visibility, 0xffffffff, win.toString());
6093                            statusbar.topAppWindowChanged(needsMenu);
6094                        }
6095                    } catch (RemoteException e) {
6096                        // re-acquire status bar service next time it is needed.
6097                        mStatusBarService = null;
6098                    }
6099                }
6100            });
6101        return diff;
6102    }
6103
6104    private int updateLightStatusBarLw(int vis) {
6105        WindowState statusColorWin = isStatusBarKeyguard() && !mHideLockScreen
6106                ? mStatusBar
6107                : mTopFullscreenOpaqueOrDimmingWindowState;
6108
6109        if (statusColorWin != null) {
6110            if (statusColorWin == mTopFullscreenOpaqueWindowState) {
6111                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
6112                // its light flag.
6113                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
6114                vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
6115                        & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
6116            } else if (statusColorWin != null && statusColorWin.isDimming()) {
6117                // Otherwise if it's dimming, clear the light flag.
6118                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
6119            }
6120        }
6121        return vis;
6122    }
6123
6124    private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
6125        // apply translucent bar vis flags
6126        WindowState transWin = isStatusBarKeyguard() && !mHideLockScreen
6127                ? mStatusBar
6128                : mTopFullscreenOpaqueWindowState;
6129        vis = mStatusBarController.applyTranslucentFlagLw(transWin, vis, oldVis);
6130        vis = mNavigationBarController.applyTranslucentFlagLw(transWin, vis, oldVis);
6131
6132        // prevent status bar interaction from clearing certain flags
6133        boolean statusBarHasFocus = win.getAttrs().type == TYPE_STATUS_BAR;
6134        if (statusBarHasFocus && !isStatusBarKeyguard()) {
6135            int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
6136                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
6137                    | View.SYSTEM_UI_FLAG_IMMERSIVE
6138                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
6139                    | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
6140            if (mHideLockScreen) {
6141                flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
6142            }
6143            vis = (vis & ~flags) | (oldVis & flags);
6144        }
6145
6146        if (!areTranslucentBarsAllowed() && transWin != mStatusBar) {
6147            vis &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSLUCENT
6148                    | View.SYSTEM_UI_TRANSPARENT);
6149        }
6150
6151        // update status bar
6152        boolean immersiveSticky =
6153                (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
6154        boolean hideStatusBarWM =
6155                mTopFullscreenOpaqueWindowState != null &&
6156                (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
6157                        & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
6158        boolean hideStatusBarSysui =
6159                (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
6160        boolean hideNavBarSysui =
6161                (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
6162
6163        boolean transientStatusBarAllowed =
6164                mStatusBar != null && (
6165                hideStatusBarWM
6166                || (hideStatusBarSysui && immersiveSticky)
6167                || statusBarHasFocus);
6168
6169        boolean transientNavBarAllowed =
6170                mNavigationBar != null &&
6171                hideNavBarSysui && immersiveSticky;
6172
6173        boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
6174                && !transientStatusBarAllowed && hideStatusBarSysui;
6175        boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
6176                && !transientNavBarAllowed;
6177        if (denyTransientStatus || denyTransientNav) {
6178            // clear the clearable flags instead
6179            clearClearableFlagsLw();
6180            vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
6181        }
6182
6183        vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
6184
6185        // update navigation bar
6186        boolean oldImmersiveMode = isImmersiveMode(oldVis);
6187        boolean newImmersiveMode = isImmersiveMode(vis);
6188        if (win != null && oldImmersiveMode != newImmersiveMode) {
6189            final String pkg = win.getOwningPackage();
6190            mImmersiveModeConfirmation.immersiveModeChanged(pkg, newImmersiveMode,
6191                    isUserSetupComplete());
6192        }
6193
6194        vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
6195
6196        return vis;
6197    }
6198
6199    private void clearClearableFlagsLw() {
6200        int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
6201        if (newVal != mResettingSystemUiFlags) {
6202            mResettingSystemUiFlags = newVal;
6203            mWindowManagerFuncs.reevaluateStatusBarVisibility();
6204        }
6205    }
6206
6207    private boolean isImmersiveMode(int vis) {
6208        final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
6209        return mNavigationBar != null
6210                && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
6211                && (vis & flags) != 0
6212                && canHideNavigationBar();
6213    }
6214
6215    /**
6216     * @return whether the navigation or status bar can be made translucent
6217     *
6218     * This should return true unless touch exploration is not enabled or
6219     * R.boolean.config_enableTranslucentDecor is false.
6220     */
6221    private boolean areTranslucentBarsAllowed() {
6222        return mTranslucentDecorEnabled
6223                && !mAccessibilityManager.isTouchExplorationEnabled();
6224    }
6225
6226    // Use this instead of checking config_showNavigationBar so that it can be consistently
6227    // overridden by qemu.hw.mainkeys in the emulator.
6228    @Override
6229    public boolean hasNavigationBar() {
6230        return mHasNavigationBar;
6231    }
6232
6233    @Override
6234    public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
6235        mLastInputMethodWindow = ime;
6236        mLastInputMethodTargetWindow = target;
6237    }
6238
6239    @Override
6240    public int getInputMethodWindowVisibleHeightLw() {
6241        return mDockBottom - mCurBottom;
6242    }
6243
6244    @Override
6245    public void setCurrentUserLw(int newUserId) {
6246        mCurrentUserId = newUserId;
6247        if (mKeyguardDelegate != null) {
6248            mKeyguardDelegate.setCurrentUser(newUserId);
6249        }
6250        if (mStatusBarService != null) {
6251            try {
6252                mStatusBarService.setCurrentUser(newUserId);
6253            } catch (RemoteException e) {
6254                // oh well
6255            }
6256        }
6257        setLastInputMethodWindowLw(null, null);
6258    }
6259
6260    @Override
6261    public boolean canMagnifyWindow(int windowType) {
6262        switch (windowType) {
6263            case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
6264            case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
6265            case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
6266            case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
6267                return false;
6268            }
6269        }
6270        return true;
6271    }
6272
6273    @Override
6274    public boolean isTopLevelWindow(int windowType) {
6275        if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
6276                && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
6277            return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
6278        }
6279        return true;
6280    }
6281
6282    @Override
6283    public void dump(String prefix, PrintWriter pw, String[] args) {
6284        pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
6285                pw.print(" mSystemReady="); pw.print(mSystemReady);
6286                pw.print(" mSystemBooted="); pw.println(mSystemBooted);
6287        pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
6288                pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
6289                pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
6290                pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
6291        if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
6292                || mForceClearedSystemUiFlags != 0) {
6293            pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
6294                    pw.print(Integer.toHexString(mLastSystemUiFlags));
6295                    pw.print(" mResettingSystemUiFlags=0x");
6296                    pw.print(Integer.toHexString(mResettingSystemUiFlags));
6297                    pw.print(" mForceClearedSystemUiFlags=0x");
6298                    pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
6299        }
6300        if (mLastFocusNeedsMenu) {
6301            pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
6302                    pw.println(mLastFocusNeedsMenu);
6303        }
6304        pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
6305                pw.println(mWakeGestureEnabledSetting);
6306
6307        pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
6308        pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
6309                pw.print(" mDockMode="); pw.print(mDockMode);
6310                pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
6311                pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
6312        pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
6313                pw.print(" mUserRotation="); pw.print(mUserRotation);
6314                pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
6315        pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
6316        pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
6317                pw.print(mCarDockEnablesAccelerometer);
6318                pw.print(" mDeskDockEnablesAccelerometer=");
6319                pw.println(mDeskDockEnablesAccelerometer);
6320        pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
6321                pw.print(mLidKeyboardAccessibility);
6322                pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
6323                pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
6324        pw.print(prefix);
6325                pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
6326                pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
6327        pw.print(prefix);
6328                pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
6329                pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
6330        pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
6331        pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
6332        pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
6333                pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
6334        pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
6335                pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
6336        pw.print(prefix); pw.print("mOrientationSensorEnabled=");
6337                pw.println(mOrientationSensorEnabled);
6338        pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
6339                pw.print(","); pw.print(mOverscanScreenTop);
6340                pw.print(") "); pw.print(mOverscanScreenWidth);
6341                pw.print("x"); pw.println(mOverscanScreenHeight);
6342        if (mOverscanLeft != 0 || mOverscanTop != 0
6343                || mOverscanRight != 0 || mOverscanBottom != 0) {
6344            pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
6345                    pw.print(" top="); pw.print(mOverscanTop);
6346                    pw.print(" right="); pw.print(mOverscanRight);
6347                    pw.print(" bottom="); pw.println(mOverscanBottom);
6348        }
6349        pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
6350                pw.print(mRestrictedOverscanScreenLeft);
6351                pw.print(","); pw.print(mRestrictedOverscanScreenTop);
6352                pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
6353                pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
6354        pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
6355                pw.print(","); pw.print(mUnrestrictedScreenTop);
6356                pw.print(") "); pw.print(mUnrestrictedScreenWidth);
6357                pw.print("x"); pw.println(mUnrestrictedScreenHeight);
6358        pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
6359                pw.print(","); pw.print(mRestrictedScreenTop);
6360                pw.print(") "); pw.print(mRestrictedScreenWidth);
6361                pw.print("x"); pw.println(mRestrictedScreenHeight);
6362        pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
6363                pw.print(","); pw.print(mStableFullscreenTop);
6364                pw.print(")-("); pw.print(mStableFullscreenRight);
6365                pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
6366        pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
6367                pw.print(","); pw.print(mStableTop);
6368                pw.print(")-("); pw.print(mStableRight);
6369                pw.print(","); pw.print(mStableBottom); pw.println(")");
6370        pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
6371                pw.print(","); pw.print(mSystemTop);
6372                pw.print(")-("); pw.print(mSystemRight);
6373                pw.print(","); pw.print(mSystemBottom); pw.println(")");
6374        pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
6375                pw.print(","); pw.print(mCurTop);
6376                pw.print(")-("); pw.print(mCurRight);
6377                pw.print(","); pw.print(mCurBottom); pw.println(")");
6378        pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
6379                pw.print(","); pw.print(mContentTop);
6380                pw.print(")-("); pw.print(mContentRight);
6381                pw.print(","); pw.print(mContentBottom); pw.println(")");
6382        pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft);
6383                pw.print(","); pw.print(mVoiceContentTop);
6384                pw.print(")-("); pw.print(mVoiceContentRight);
6385                pw.print(","); pw.print(mVoiceContentBottom); pw.println(")");
6386        pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
6387                pw.print(","); pw.print(mDockTop);
6388                pw.print(")-("); pw.print(mDockRight);
6389                pw.print(","); pw.print(mDockBottom); pw.println(")");
6390        pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
6391                pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
6392        pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen);
6393                pw.print(" mShowingDream="); pw.print(mShowingDream);
6394                pw.print(" mDreamingLockscreen="); pw.println(mDreamingLockscreen);
6395        if (mLastInputMethodWindow != null) {
6396            pw.print(prefix); pw.print("mLastInputMethodWindow=");
6397                    pw.println(mLastInputMethodWindow);
6398        }
6399        if (mLastInputMethodTargetWindow != null) {
6400            pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
6401                    pw.println(mLastInputMethodTargetWindow);
6402        }
6403        if (mStatusBar != null) {
6404            pw.print(prefix); pw.print("mStatusBar=");
6405                    pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
6406                    pw.println(isStatusBarKeyguard());
6407        }
6408        if (mNavigationBar != null) {
6409            pw.print(prefix); pw.print("mNavigationBar=");
6410                    pw.println(mNavigationBar);
6411        }
6412        if (mFocusedWindow != null) {
6413            pw.print(prefix); pw.print("mFocusedWindow=");
6414                    pw.println(mFocusedWindow);
6415        }
6416        if (mFocusedApp != null) {
6417            pw.print(prefix); pw.print("mFocusedApp=");
6418                    pw.println(mFocusedApp);
6419        }
6420        if (mWinDismissingKeyguard != null) {
6421            pw.print(prefix); pw.print("mWinDismissingKeyguard=");
6422                    pw.println(mWinDismissingKeyguard);
6423        }
6424        if (mTopFullscreenOpaqueWindowState != null) {
6425            pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
6426                    pw.println(mTopFullscreenOpaqueWindowState);
6427        }
6428        if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
6429            pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
6430                    pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
6431        }
6432        if (mForcingShowNavBar) {
6433            pw.print(prefix); pw.print("mForcingShowNavBar=");
6434                    pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
6435                    pw.println(mForcingShowNavBarLayer);
6436        }
6437        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
6438                pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
6439        pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
6440                pw.print(" mForceStatusBarFromKeyguard=");
6441                pw.println(mForceStatusBarFromKeyguard);
6442        pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
6443                pw.print(" mWinDismissingKeyguard="); pw.print(mWinDismissingKeyguard);
6444                pw.print(" mHomePressed="); pw.println(mHomePressed);
6445        pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
6446                pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
6447                pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
6448        pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
6449                pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
6450                pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
6451        pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
6452                pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
6453        pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
6454                pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
6455        pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
6456                pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
6457        pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
6458
6459        mGlobalKeyManager.dump(prefix, pw);
6460        mStatusBarController.dump(pw, prefix);
6461        mNavigationBarController.dump(pw, prefix);
6462        PolicyControl.dump(prefix, pw);
6463
6464        if (mWakeGestureListener != null) {
6465            mWakeGestureListener.dump(pw, prefix);
6466        }
6467        if (mOrientationListener != null) {
6468            mOrientationListener.dump(pw, prefix);
6469        }
6470        if (mBurnInProtectionHelper != null) {
6471            mBurnInProtectionHelper.dump(prefix, pw);
6472        }
6473    }
6474}
6475