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