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