PhoneWindowManager.java revision 23a44a889317abec536bfff6d73eae788d06e787
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 affectsSystemUi = win.canAffectSystemUiFlags();
5347        if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": affectsSystemUi=" + affectsSystemUi);
5348        applyKeyguardPolicyLw(win, imeTarget);
5349        final int fl = PolicyControl.getWindowFlags(win, attrs);
5350        if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi
5351                && attrs.type == TYPE_INPUT_METHOD) {
5352            mForcingShowNavBar = true;
5353            mForcingShowNavBarLayer = win.getSurfaceLayer();
5354        }
5355        if (attrs.type == TYPE_STATUS_BAR) {
5356            if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
5357                mForceStatusBarFromKeyguard = true;
5358            }
5359            if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
5360                mForceStatusBarTransparent = true;
5361            }
5362        }
5363
5364        boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
5365                && attrs.type < FIRST_SYSTEM_WINDOW;
5366        final int stackId = win.getStackId();
5367        if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi) {
5368            if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
5369                mForceStatusBar = true;
5370            }
5371            if (attrs.type == TYPE_DREAM) {
5372                // If the lockscreen was showing when the dream started then wait
5373                // for the dream to draw before hiding the lockscreen.
5374                if (!mDreamingLockscreen
5375                        || (win.isVisibleLw() && win.hasDrawnLw())) {
5376                    mShowingDream = true;
5377                    appWindow = true;
5378                }
5379            }
5380
5381            // For app windows that are not attached, we decide if all windows in the app they
5382            // represent should be hidden or if we should hide the lockscreen. For attached app
5383            // windows we defer the decision to the window it is attached to.
5384            if (appWindow && attached == null) {
5385                if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
5386                    if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
5387                    mTopFullscreenOpaqueWindowState = win;
5388                    if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5389                        mTopFullscreenOpaqueOrDimmingWindowState = win;
5390                    }
5391                    if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
5392                        mAllowLockscreenWhenOn = true;
5393                    }
5394                }
5395            }
5396        }
5397
5398        // Voice interaction overrides both top fullscreen and top docked.
5399        if (affectsSystemUi && win.getAttrs().type == TYPE_VOICE_INTERACTION) {
5400            if (mTopFullscreenOpaqueWindowState == null) {
5401                mTopFullscreenOpaqueWindowState = win;
5402                if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5403                    mTopFullscreenOpaqueOrDimmingWindowState = win;
5404                }
5405            }
5406            if (mTopDockedOpaqueWindowState == null) {
5407                mTopDockedOpaqueWindowState = win;
5408                if (mTopDockedOpaqueOrDimmingWindowState == null) {
5409                    mTopDockedOpaqueOrDimmingWindowState = win;
5410                }
5411            }
5412        }
5413
5414        // Keep track of the window if it's dimming but not necessarily fullscreen.
5415        if (mTopFullscreenOpaqueOrDimmingWindowState == null && affectsSystemUi
5416                && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
5417            mTopFullscreenOpaqueOrDimmingWindowState = win;
5418        }
5419
5420        // We need to keep track of the top "fullscreen" opaque window for the docked stack
5421        // separately, because both the "real fullscreen" opaque window and the one for the docked
5422        // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
5423        if (mTopDockedOpaqueWindowState == null && affectsSystemUi && appWindow && attached == null
5424                && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
5425            mTopDockedOpaqueWindowState = win;
5426            if (mTopDockedOpaqueOrDimmingWindowState == null) {
5427                mTopDockedOpaqueOrDimmingWindowState = win;
5428            }
5429        }
5430
5431        // Also keep track of any windows that are dimming but not necessarily fullscreen in the
5432        // docked stack.
5433        if (mTopDockedOpaqueOrDimmingWindowState == null && affectsSystemUi && win.isDimming()
5434                && stackId == DOCKED_STACK_ID) {
5435            mTopDockedOpaqueOrDimmingWindowState = win;
5436        }
5437    }
5438
5439    private void applyKeyguardPolicyLw(WindowState win, WindowState imeTarget) {
5440        if (canBeHiddenByKeyguardLw(win)) {
5441            if (shouldBeHiddenByKeyguard(win, imeTarget)) {
5442                win.hideLw(false /* doAnimation */);
5443            } else {
5444                win.showLw(false /* doAnimation */);
5445            }
5446        }
5447    }
5448
5449    private boolean isFullscreen(WindowManager.LayoutParams attrs) {
5450        return attrs.x == 0 && attrs.y == 0
5451                && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
5452                && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
5453    }
5454
5455    /** {@inheritDoc} */
5456    @Override
5457    public int finishPostLayoutPolicyLw() {
5458        int changes = 0;
5459        boolean topIsFullscreen = false;
5460
5461        final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
5462                ? mTopFullscreenOpaqueWindowState.getAttrs()
5463                : null;
5464
5465        // If we are not currently showing a dream then remember the current
5466        // lockscreen state.  We will use this to determine whether the dream
5467        // started while the lockscreen was showing and remember this state
5468        // while the dream is showing.
5469        if (!mShowingDream) {
5470            mDreamingLockscreen = isKeyguardShowingAndNotOccluded();
5471            if (mDreamingSleepTokenNeeded) {
5472                mDreamingSleepTokenNeeded = false;
5473                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
5474            }
5475        } else {
5476            if (!mDreamingSleepTokenNeeded) {
5477                mDreamingSleepTokenNeeded = true;
5478                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget();
5479            }
5480        }
5481
5482        if (mStatusBar != null) {
5483            if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
5484                    + " forcefkg=" + mForceStatusBarFromKeyguard
5485                    + " top=" + mTopFullscreenOpaqueWindowState);
5486            boolean shouldBeTransparent = mForceStatusBarTransparent
5487                    && !mForceStatusBar
5488                    && !mForceStatusBarFromKeyguard;
5489            if (!shouldBeTransparent) {
5490                mStatusBarController.setShowTransparent(false /* transparent */);
5491            } else if (!mStatusBar.isVisibleLw()) {
5492                mStatusBarController.setShowTransparent(true /* transparent */);
5493            }
5494
5495            WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs();
5496            boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT
5497                    && statusBarAttrs.width == MATCH_PARENT;
5498            if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
5499                    || statusBarExpanded) {
5500                if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
5501                if (mStatusBarController.setBarShowingLw(true)) {
5502                    changes |= FINISH_LAYOUT_REDO_LAYOUT;
5503                }
5504                // Maintain fullscreen layout until incoming animation is complete.
5505                topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
5506                // Transient status bar on the lockscreen is not allowed
5507                if ((mForceStatusBarFromKeyguard || statusBarExpanded)
5508                        && mStatusBarController.isTransientShowing()) {
5509                    mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
5510                            mLastSystemUiFlags, mLastSystemUiFlags);
5511                }
5512                if (statusBarExpanded && mNavigationBar != null) {
5513                    if (mNavigationBarController.setBarShowingLw(true)) {
5514                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5515                    }
5516                }
5517            } else if (mTopFullscreenOpaqueWindowState != null) {
5518                final int fl = PolicyControl.getWindowFlags(null, lp);
5519                if (localLOGV) {
5520                    Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
5521                            + " shown position: "
5522                            + mTopFullscreenOpaqueWindowState.getShownPositionLw());
5523                    Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
5524                            + " lp.flags=0x" + Integer.toHexString(fl));
5525                }
5526                topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
5527                        || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
5528                // The subtle difference between the window for mTopFullscreenOpaqueWindowState
5529                // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
5530                // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
5531                // case though.
5532                if (mStatusBarController.isTransientShowing()) {
5533                    if (mStatusBarController.setBarShowingLw(true)) {
5534                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5535                    }
5536                } else if (topIsFullscreen
5537                        && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)
5538                        && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) {
5539                    if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
5540                    if (mStatusBarController.setBarShowingLw(false)) {
5541                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5542                    } else {
5543                        if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
5544                    }
5545                } else {
5546                    if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
5547                    if (mStatusBarController.setBarShowingLw(true)) {
5548                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5549                    }
5550                }
5551            }
5552        }
5553
5554        if (mTopIsFullscreen != topIsFullscreen) {
5555            if (!topIsFullscreen) {
5556                // Force another layout when status bar becomes fully shown.
5557                changes |= FINISH_LAYOUT_REDO_LAYOUT;
5558            }
5559            mTopIsFullscreen = topIsFullscreen;
5560        }
5561
5562        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5563            // If the navigation bar has been hidden or shown, we need to do another
5564            // layout pass to update that window.
5565            changes |= FINISH_LAYOUT_REDO_LAYOUT;
5566        }
5567
5568        if (mShowingDream != mLastShowingDream) {
5569            mLastShowingDream = mShowingDream;
5570            mWindowManagerFuncs.notifyShowingDreamChanged();
5571        }
5572
5573        // update since mAllowLockscreenWhenOn might have changed
5574        updateLockScreenTimeout();
5575        return changes;
5576    }
5577
5578    /**
5579     * Updates the occluded state of the Keyguard.
5580     *
5581     * @return Whether the flags have changed and we have to redo the layout.
5582     */
5583    private boolean setKeyguardOccludedLw(boolean isOccluded, boolean force) {
5584        if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded);
5585        final boolean wasOccluded = mKeyguardOccluded;
5586        final boolean showing = mKeyguardDelegate.isShowing();
5587        final boolean changed = wasOccluded != isOccluded || force;
5588        if (!isOccluded && changed && showing) {
5589            mKeyguardOccluded = false;
5590            mKeyguardDelegate.setOccluded(false, true /* animate */);
5591            if (mStatusBar != null) {
5592                mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
5593                if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
5594                    mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5595                }
5596            }
5597            return true;
5598        } else if (isOccluded && changed && showing) {
5599            mKeyguardOccluded = true;
5600            mKeyguardDelegate.setOccluded(true, false /* animate */);
5601            if (mStatusBar != null) {
5602                mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
5603                mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
5604            }
5605            return true;
5606        } else if (changed) {
5607            mKeyguardOccluded = isOccluded;
5608            mKeyguardDelegate.setOccluded(isOccluded, false /* animate */);
5609            return false;
5610        } else {
5611            return false;
5612        }
5613    }
5614
5615    private boolean isStatusBarKeyguard() {
5616        return mStatusBar != null
5617                && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
5618    }
5619
5620    @Override
5621    public boolean allowAppAnimationsLw() {
5622        if (mShowingDream) {
5623            // If keyguard or dreams is currently visible, no reason to animate behind it.
5624            return false;
5625        }
5626        return true;
5627    }
5628
5629    @Override
5630    public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
5631        mFocusedWindow = newFocus;
5632        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5633            // If the navigation bar has been hidden or shown, we need to do another
5634            // layout pass to update that window.
5635            return FINISH_LAYOUT_REDO_LAYOUT;
5636        }
5637        return 0;
5638    }
5639
5640    /** {@inheritDoc} */
5641    @Override
5642    public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
5643        // lid changed state
5644        final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
5645        if (newLidState == mLidState) {
5646            return;
5647        }
5648
5649        mLidState = newLidState;
5650        applyLidSwitchState();
5651        updateRotation(true);
5652
5653        if (lidOpen) {
5654            wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
5655                    "android.policy:LID");
5656        } else if (!mLidControlsSleep) {
5657            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
5658        }
5659    }
5660
5661    @Override
5662    public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
5663        int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
5664        if (mCameraLensCoverState == lensCoverState) {
5665            return;
5666        }
5667        if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
5668                lensCoverState == CAMERA_LENS_UNCOVERED) {
5669            Intent intent;
5670            final boolean keyguardActive = mKeyguardDelegate == null ? false :
5671                    mKeyguardDelegate.isShowing();
5672            if (keyguardActive) {
5673                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
5674            } else {
5675                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
5676            }
5677            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
5678                    "android.policy:CAMERA_COVER");
5679            startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
5680        }
5681        mCameraLensCoverState = lensCoverState;
5682    }
5683
5684    void setHdmiPlugged(boolean plugged) {
5685        if (mHdmiPlugged != plugged) {
5686            mHdmiPlugged = plugged;
5687            updateRotation(true, true);
5688            Intent intent = new Intent(ACTION_HDMI_PLUGGED);
5689            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
5690            intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
5691            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
5692        }
5693    }
5694
5695    void initializeHdmiState() {
5696        boolean plugged = false;
5697        // watch for HDMI plug messages if the hdmi switch exists
5698        if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
5699            mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
5700
5701            final String filename = "/sys/class/switch/hdmi/state";
5702            FileReader reader = null;
5703            try {
5704                reader = new FileReader(filename);
5705                char[] buf = new char[15];
5706                int n = reader.read(buf);
5707                if (n > 1) {
5708                    plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
5709                }
5710            } catch (IOException ex) {
5711                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5712            } catch (NumberFormatException ex) {
5713                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5714            } finally {
5715                if (reader != null) {
5716                    try {
5717                        reader.close();
5718                    } catch (IOException ex) {
5719                    }
5720                }
5721            }
5722        }
5723        // This dance forces the code in setHdmiPlugged to run.
5724        // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
5725        mHdmiPlugged = !plugged;
5726        setHdmiPlugged(!mHdmiPlugged);
5727    }
5728
5729    final Object mScreenshotLock = new Object();
5730    ServiceConnection mScreenshotConnection = null;
5731
5732    final Runnable mScreenshotTimeout = new Runnable() {
5733        @Override public void run() {
5734            synchronized (mScreenshotLock) {
5735                if (mScreenshotConnection != null) {
5736                    mContext.unbindService(mScreenshotConnection);
5737                    mScreenshotConnection = null;
5738                    notifyScreenshotError();
5739                }
5740            }
5741        }
5742    };
5743
5744    // Assume this is called from the Handler thread.
5745    private void takeScreenshot(final int screenshotType) {
5746        synchronized (mScreenshotLock) {
5747            if (mScreenshotConnection != null) {
5748                return;
5749            }
5750            final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
5751                    SYSUI_SCREENSHOT_SERVICE);
5752            final Intent serviceIntent = new Intent();
5753            serviceIntent.setComponent(serviceComponent);
5754            ServiceConnection conn = new ServiceConnection() {
5755                @Override
5756                public void onServiceConnected(ComponentName name, IBinder service) {
5757                    synchronized (mScreenshotLock) {
5758                        if (mScreenshotConnection != this) {
5759                            return;
5760                        }
5761                        Messenger messenger = new Messenger(service);
5762                        Message msg = Message.obtain(null, screenshotType);
5763                        final ServiceConnection myConn = this;
5764                        Handler h = new Handler(mHandler.getLooper()) {
5765                            @Override
5766                            public void handleMessage(Message msg) {
5767                                synchronized (mScreenshotLock) {
5768                                    if (mScreenshotConnection == myConn) {
5769                                        mContext.unbindService(mScreenshotConnection);
5770                                        mScreenshotConnection = null;
5771                                        mHandler.removeCallbacks(mScreenshotTimeout);
5772                                    }
5773                                }
5774                            }
5775                        };
5776                        msg.replyTo = new Messenger(h);
5777                        msg.arg1 = msg.arg2 = 0;
5778                        if (mStatusBar != null && mStatusBar.isVisibleLw())
5779                            msg.arg1 = 1;
5780                        if (mNavigationBar != null && mNavigationBar.isVisibleLw())
5781                            msg.arg2 = 1;
5782                        try {
5783                            messenger.send(msg);
5784                        } catch (RemoteException e) {
5785                        }
5786                    }
5787                }
5788
5789                @Override
5790                public void onServiceDisconnected(ComponentName name) {
5791                    synchronized (mScreenshotLock) {
5792                        if (mScreenshotConnection != null) {
5793                            mContext.unbindService(mScreenshotConnection);
5794                            mScreenshotConnection = null;
5795                            mHandler.removeCallbacks(mScreenshotTimeout);
5796                            notifyScreenshotError();
5797                        }
5798                    }
5799                }
5800            };
5801            if (mContext.bindServiceAsUser(serviceIntent, conn,
5802                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
5803                    UserHandle.CURRENT)) {
5804                mScreenshotConnection = conn;
5805                mHandler.postDelayed(mScreenshotTimeout, 10000);
5806            }
5807        }
5808    }
5809
5810    /**
5811     * Notifies the screenshot service to show an error.
5812     */
5813    private void notifyScreenshotError() {
5814        // If the service process is killed, then ask it to clean up after itself
5815        final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
5816                SYSUI_SCREENSHOT_ERROR_RECEIVER);
5817        Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
5818        errorIntent.setComponent(errorComponent);
5819        errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
5820                Intent.FLAG_RECEIVER_FOREGROUND);
5821        mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT);
5822    }
5823
5824    /** {@inheritDoc} */
5825    @Override
5826    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
5827        if (!mSystemBooted) {
5828            // If we have not yet booted, don't let key events do anything.
5829            return 0;
5830        }
5831
5832        final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
5833        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
5834        final boolean canceled = event.isCanceled();
5835        final int keyCode = event.getKeyCode();
5836
5837        final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
5838
5839        // If screen is off then we treat the case where the keyguard is open but hidden
5840        // the same as if it were open and in front.
5841        // This will prevent any keys other than the power button from waking the screen
5842        // when the keyguard is hidden by another activity.
5843        final boolean keyguardActive = (mKeyguardDelegate == null ? false :
5844                                            (interactive ?
5845                                                isKeyguardShowingAndNotOccluded() :
5846                                                mKeyguardDelegate.isShowing()));
5847
5848        if (DEBUG_INPUT) {
5849            Log.d(TAG, "interceptKeyTq keycode=" + keyCode
5850                    + " interactive=" + interactive + " keyguardActive=" + keyguardActive
5851                    + " policyFlags=" + Integer.toHexString(policyFlags));
5852        }
5853
5854        // Basic policy based on interactive state.
5855        int result;
5856        boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
5857                || event.isWakeKey();
5858        if (interactive || (isInjected && !isWakeKey)) {
5859            // When the device is interactive or the key is injected pass the
5860            // key to the application.
5861            result = ACTION_PASS_TO_USER;
5862            isWakeKey = false;
5863
5864            if (interactive) {
5865                // If the screen is awake, but the button pressed was the one that woke the device
5866                // then don't pass it to the application
5867                if (keyCode == mPendingWakeKey && !down) {
5868                    result = 0;
5869                }
5870                // Reset the pending key
5871                mPendingWakeKey = PENDING_KEY_NULL;
5872            }
5873        } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
5874            // If we're currently dozing with the screen on and the keyguard showing, pass the key
5875            // to the application but preserve its wake key status to make sure we still move
5876            // from dozing to fully interactive if we would normally go from off to fully
5877            // interactive.
5878            result = ACTION_PASS_TO_USER;
5879            // Since we're dispatching the input, reset the pending key
5880            mPendingWakeKey = PENDING_KEY_NULL;
5881        } else {
5882            // When the screen is off and the key is not injected, determine whether
5883            // to wake the device but don't pass the key to the application.
5884            result = 0;
5885            if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
5886                isWakeKey = false;
5887            }
5888            // Cache the wake key on down event so we can also avoid sending the up event to the app
5889            if (isWakeKey && down) {
5890                mPendingWakeKey = keyCode;
5891            }
5892        }
5893
5894        // If the key would be handled globally, just return the result, don't worry about special
5895        // key processing.
5896        if (isValidGlobalKey(keyCode)
5897                && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
5898            if (isWakeKey) {
5899                wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5900            }
5901            return result;
5902        }
5903
5904        boolean useHapticFeedback = down
5905                && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
5906                && event.getRepeatCount() == 0;
5907
5908        // Handle special keys.
5909        switch (keyCode) {
5910            case KeyEvent.KEYCODE_BACK: {
5911                if (down) {
5912                    interceptBackKeyDown();
5913                } else {
5914                    boolean handled = interceptBackKeyUp(event);
5915
5916                    // Don't pass back press to app if we've already handled it via long press
5917                    if (handled) {
5918                        result &= ~ACTION_PASS_TO_USER;
5919                    }
5920                }
5921                break;
5922            }
5923
5924            case KeyEvent.KEYCODE_VOLUME_DOWN:
5925            case KeyEvent.KEYCODE_VOLUME_UP:
5926            case KeyEvent.KEYCODE_VOLUME_MUTE: {
5927                if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
5928                    if (down) {
5929                        if (interactive && !mScreenshotChordVolumeDownKeyTriggered
5930                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5931                            mScreenshotChordVolumeDownKeyTriggered = true;
5932                            mScreenshotChordVolumeDownKeyTime = event.getDownTime();
5933                            mScreenshotChordVolumeDownKeyConsumed = false;
5934                            cancelPendingPowerKeyAction();
5935                            interceptScreenshotChord();
5936                            interceptAccessibilityShortcutChord();
5937                        }
5938                    } else {
5939                        mScreenshotChordVolumeDownKeyTriggered = false;
5940                        cancelPendingScreenshotChordAction();
5941                        cancelPendingAccessibilityShortcutAction();
5942                    }
5943                } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
5944                    if (down) {
5945                        if (interactive && !mA11yShortcutChordVolumeUpKeyTriggered
5946                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5947                            mA11yShortcutChordVolumeUpKeyTriggered = true;
5948                            mA11yShortcutChordVolumeUpKeyTime = event.getDownTime();
5949                            mA11yShortcutChordVolumeUpKeyConsumed = false;
5950                            cancelPendingPowerKeyAction();
5951                            cancelPendingScreenshotChordAction();
5952                            interceptAccessibilityShortcutChord();
5953                        }
5954                    } else {
5955                        mA11yShortcutChordVolumeUpKeyTriggered = false;
5956                        cancelPendingScreenshotChordAction();
5957                        cancelPendingAccessibilityShortcutAction();
5958                    }
5959                }
5960                if (down) {
5961                    TelecomManager telecomManager = getTelecommService();
5962                    if (telecomManager != null) {
5963                        if (telecomManager.isRinging()) {
5964                            // If an incoming call is ringing, either VOLUME key means
5965                            // "silence ringer".  We handle these keys here, rather than
5966                            // in the InCallScreen, to make sure we'll respond to them
5967                            // even if the InCallScreen hasn't come to the foreground yet.
5968                            // Look for the DOWN event here, to agree with the "fallback"
5969                            // behavior in the InCallScreen.
5970                            Log.i(TAG, "interceptKeyBeforeQueueing:"
5971                                  + " VOLUME key-down while ringing: Silence ringer!");
5972
5973                            // Silence the ringer.  (It's safe to call this
5974                            // even if the ringer has already been silenced.)
5975                            telecomManager.silenceRinger();
5976
5977                            // And *don't* pass this key thru to the current activity
5978                            // (which is probably the InCallScreen.)
5979                            result &= ~ACTION_PASS_TO_USER;
5980                            break;
5981                        }
5982                    }
5983                    int audioMode = AudioManager.MODE_NORMAL;
5984                    try {
5985                        audioMode = getAudioService().getMode();
5986                    } catch (Exception e) {
5987                        Log.e(TAG, "Error getting AudioService in interceptKeyBeforeQueueing.", e);
5988                    }
5989                    boolean isInCall = (telecomManager != null && telecomManager.isInCall()) ||
5990                            audioMode == AudioManager.MODE_IN_COMMUNICATION;
5991                    if (isInCall && (result & ACTION_PASS_TO_USER) == 0) {
5992                        // If we are in call but we decided not to pass the key to
5993                        // the application, just pass it to the session service.
5994                        MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
5995                                event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
5996                        break;
5997                    }
5998
5999                }
6000                if (mUseTvRouting || mHandleVolumeKeysInWM) {
6001                    // Defer special key handlings to
6002                    // {@link interceptKeyBeforeDispatching()}.
6003                    result |= ACTION_PASS_TO_USER;
6004                } else if ((result & ACTION_PASS_TO_USER) == 0) {
6005                    // If we aren't passing to the user and no one else
6006                    // handled it send it to the session manager to
6007                    // figure out.
6008                    MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
6009                            event, AudioManager.USE_DEFAULT_STREAM_TYPE, true);
6010                }
6011                break;
6012            }
6013
6014            case KeyEvent.KEYCODE_ENDCALL: {
6015                result &= ~ACTION_PASS_TO_USER;
6016                if (down) {
6017                    TelecomManager telecomManager = getTelecommService();
6018                    boolean hungUp = false;
6019                    if (telecomManager != null) {
6020                        hungUp = telecomManager.endCall();
6021                    }
6022                    if (interactive && !hungUp) {
6023                        mEndCallKeyHandled = false;
6024                        mHandler.postDelayed(mEndCallLongPress,
6025                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
6026                    } else {
6027                        mEndCallKeyHandled = true;
6028                    }
6029                } else {
6030                    if (!mEndCallKeyHandled) {
6031                        mHandler.removeCallbacks(mEndCallLongPress);
6032                        if (!canceled) {
6033                            if ((mEndcallBehavior
6034                                    & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
6035                                if (goHome()) {
6036                                    break;
6037                                }
6038                            }
6039                            if ((mEndcallBehavior
6040                                    & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
6041                                mPowerManager.goToSleep(event.getEventTime(),
6042                                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
6043                                isWakeKey = false;
6044                            }
6045                        }
6046                    }
6047                }
6048                break;
6049            }
6050
6051            case KeyEvent.KEYCODE_POWER: {
6052                // Any activity on the power button stops the accessibility shortcut
6053                cancelPendingAccessibilityShortcutAction();
6054                result &= ~ACTION_PASS_TO_USER;
6055                isWakeKey = false; // wake-up will be handled separately
6056                if (down) {
6057                    interceptPowerKeyDown(event, interactive);
6058                } else {
6059                    interceptPowerKeyUp(event, interactive, canceled);
6060                }
6061                break;
6062            }
6063
6064            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
6065                // fall through
6066            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
6067                // fall through
6068            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
6069                // fall through
6070            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
6071                result &= ~ACTION_PASS_TO_USER;
6072                interceptSystemNavigationKey(event);
6073                break;
6074            }
6075
6076            case KeyEvent.KEYCODE_SLEEP: {
6077                result &= ~ACTION_PASS_TO_USER;
6078                isWakeKey = false;
6079                if (!mPowerManager.isInteractive()) {
6080                    useHapticFeedback = false; // suppress feedback if already non-interactive
6081                }
6082                if (down) {
6083                    sleepPress(event.getEventTime());
6084                } else {
6085                    sleepRelease(event.getEventTime());
6086                }
6087                break;
6088            }
6089
6090            case KeyEvent.KEYCODE_SOFT_SLEEP: {
6091                result &= ~ACTION_PASS_TO_USER;
6092                isWakeKey = false;
6093                if (!down) {
6094                    mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
6095                }
6096                break;
6097            }
6098
6099            case KeyEvent.KEYCODE_WAKEUP: {
6100                result &= ~ACTION_PASS_TO_USER;
6101                isWakeKey = true;
6102                break;
6103            }
6104
6105            case KeyEvent.KEYCODE_MEDIA_PLAY:
6106            case KeyEvent.KEYCODE_MEDIA_PAUSE:
6107            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6108            case KeyEvent.KEYCODE_HEADSETHOOK:
6109            case KeyEvent.KEYCODE_MUTE:
6110            case KeyEvent.KEYCODE_MEDIA_STOP:
6111            case KeyEvent.KEYCODE_MEDIA_NEXT:
6112            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6113            case KeyEvent.KEYCODE_MEDIA_REWIND:
6114            case KeyEvent.KEYCODE_MEDIA_RECORD:
6115            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6116            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
6117                if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
6118                    // If the global session is active pass all media keys to it
6119                    // instead of the active window.
6120                    result &= ~ACTION_PASS_TO_USER;
6121                }
6122                if ((result & ACTION_PASS_TO_USER) == 0) {
6123                    // Only do this if we would otherwise not pass it to the user. In that
6124                    // case, the PhoneWindow class will do the same thing, except it will
6125                    // only do it if the showing app doesn't process the key on its own.
6126                    // Note that we need to make a copy of the key event here because the
6127                    // original key event will be recycled when we return.
6128                    mBroadcastWakeLock.acquire();
6129                    Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
6130                            new KeyEvent(event));
6131                    msg.setAsynchronous(true);
6132                    msg.sendToTarget();
6133                }
6134                break;
6135            }
6136
6137            case KeyEvent.KEYCODE_CALL: {
6138                if (down) {
6139                    TelecomManager telecomManager = getTelecommService();
6140                    if (telecomManager != null) {
6141                        if (telecomManager.isRinging()) {
6142                            Log.i(TAG, "interceptKeyBeforeQueueing:"
6143                                  + " CALL key-down while ringing: Answer the call!");
6144                            telecomManager.acceptRingingCall();
6145
6146                            // And *don't* pass this key thru to the current activity
6147                            // (which is presumably the InCallScreen.)
6148                            result &= ~ACTION_PASS_TO_USER;
6149                        }
6150                    }
6151                }
6152                break;
6153            }
6154            case KeyEvent.KEYCODE_VOICE_ASSIST: {
6155                // Only do this if we would otherwise not pass it to the user. In that case,
6156                // interceptKeyBeforeDispatching would apply a similar but different policy in
6157                // order to invoke voice assist actions. Note that we need to make a copy of the
6158                // key event here because the original key event will be recycled when we return.
6159                if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
6160                    mBroadcastWakeLock.acquire();
6161                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
6162                            keyguardActive ? 1 : 0, 0);
6163                    msg.setAsynchronous(true);
6164                    msg.sendToTarget();
6165                }
6166                break;
6167            }
6168            case KeyEvent.KEYCODE_WINDOW: {
6169                if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
6170                    if (mPictureInPictureVisible) {
6171                        // Consumes the key only if picture-in-picture is visible to show
6172                        // picture-in-picture control menu. This gives a chance to the foreground
6173                        // activity to customize PIP key behavior.
6174                        if (!down) {
6175                            showPictureInPictureMenu(event);
6176                        }
6177                        result &= ~ACTION_PASS_TO_USER;
6178                    }
6179                }
6180                break;
6181            }
6182        }
6183
6184        if (useHapticFeedback) {
6185            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
6186        }
6187
6188        if (isWakeKey) {
6189            wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
6190        }
6191
6192        return result;
6193    }
6194
6195    /**
6196     * Handle statusbar expansion events.
6197     * @param event
6198     */
6199    private void interceptSystemNavigationKey(KeyEvent event) {
6200        if (event.getAction() == KeyEvent.ACTION_UP) {
6201            if (!mAccessibilityManager.isEnabled()
6202                    || !mAccessibilityManager.sendFingerprintGesture(event.getKeyCode())) {
6203                if (areSystemNavigationKeysEnabled()) {
6204                    IStatusBarService sbar = getStatusBarService();
6205                    if (sbar != null) {
6206                        try {
6207                            sbar.handleSystemNavigationKey(event.getKeyCode());
6208                        } catch (RemoteException e1) {
6209                            // oops, no statusbar. Ignore event.
6210                        }
6211                    }
6212                }
6213            }
6214        }
6215    }
6216
6217    /**
6218     * Returns true if the key can have global actions attached to it.
6219     * We reserve all power management keys for the system since they require
6220     * very careful handling.
6221     */
6222    private static boolean isValidGlobalKey(int keyCode) {
6223        switch (keyCode) {
6224            case KeyEvent.KEYCODE_POWER:
6225            case KeyEvent.KEYCODE_WAKEUP:
6226            case KeyEvent.KEYCODE_SLEEP:
6227                return false;
6228            default:
6229                return true;
6230        }
6231    }
6232
6233    /**
6234     * When the screen is off we ignore some keys that might otherwise typically
6235     * be considered wake keys.  We filter them out here.
6236     *
6237     * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
6238     * is always considered a wake key.
6239     */
6240    private boolean isWakeKeyWhenScreenOff(int keyCode) {
6241        switch (keyCode) {
6242            // ignore volume keys unless docked
6243            case KeyEvent.KEYCODE_VOLUME_UP:
6244            case KeyEvent.KEYCODE_VOLUME_DOWN:
6245            case KeyEvent.KEYCODE_VOLUME_MUTE:
6246                return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
6247
6248            // ignore media and camera keys
6249            case KeyEvent.KEYCODE_MUTE:
6250            case KeyEvent.KEYCODE_HEADSETHOOK:
6251            case KeyEvent.KEYCODE_MEDIA_PLAY:
6252            case KeyEvent.KEYCODE_MEDIA_PAUSE:
6253            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6254            case KeyEvent.KEYCODE_MEDIA_STOP:
6255            case KeyEvent.KEYCODE_MEDIA_NEXT:
6256            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6257            case KeyEvent.KEYCODE_MEDIA_REWIND:
6258            case KeyEvent.KEYCODE_MEDIA_RECORD:
6259            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6260            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
6261            case KeyEvent.KEYCODE_CAMERA:
6262                return false;
6263        }
6264        return true;
6265    }
6266
6267
6268    /** {@inheritDoc} */
6269    @Override
6270    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
6271        if ((policyFlags & FLAG_WAKE) != 0) {
6272            if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
6273                    "android.policy:MOTION")) {
6274                return 0;
6275            }
6276        }
6277
6278        if (shouldDispatchInputWhenNonInteractive(null)) {
6279            return ACTION_PASS_TO_USER;
6280        }
6281
6282        // If we have not passed the action up and we are in theater mode without dreaming,
6283        // there will be no dream to intercept the touch and wake into ambient.  The device should
6284        // wake up in this case.
6285        if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
6286            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
6287                    "android.policy:MOTION");
6288        }
6289
6290        return 0;
6291    }
6292
6293    private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
6294        final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
6295
6296        if (displayOff && !mHasFeatureWatch) {
6297            return false;
6298        }
6299
6300        // Send events to keyguard while the screen is on and it's showing.
6301        if (isKeyguardShowingAndNotOccluded() && !displayOff) {
6302            return true;
6303        }
6304
6305        // Watches handle BACK specially
6306        if (mHasFeatureWatch
6307                && event != null
6308                && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
6309                        || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
6310            return false;
6311        }
6312
6313        // Send events to a dozing dream even if the screen is off since the dream
6314        // is in control of the state of the screen.
6315        IDreamManager dreamManager = getDreamManager();
6316
6317        try {
6318            if (dreamManager != null && dreamManager.isDreaming()) {
6319                return true;
6320            }
6321        } catch (RemoteException e) {
6322            Slog.e(TAG, "RemoteException when checking if dreaming", e);
6323        }
6324
6325        // Otherwise, consume events since the user can't see what is being
6326        // interacted with.
6327        return false;
6328    }
6329
6330    private void dispatchDirectAudioEvent(KeyEvent event) {
6331        if (event.getAction() != KeyEvent.ACTION_DOWN) {
6332            return;
6333        }
6334        int keyCode = event.getKeyCode();
6335        int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
6336                | AudioManager.FLAG_FROM_KEY;
6337        String pkgName = mContext.getOpPackageName();
6338        switch (keyCode) {
6339            case KeyEvent.KEYCODE_VOLUME_UP:
6340                try {
6341                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
6342                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6343                } catch (Exception e) {
6344                    Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
6345                }
6346                break;
6347            case KeyEvent.KEYCODE_VOLUME_DOWN:
6348                try {
6349                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
6350                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6351                } catch (Exception e) {
6352                    Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
6353                }
6354                break;
6355            case KeyEvent.KEYCODE_VOLUME_MUTE:
6356                try {
6357                    if (event.getRepeatCount() == 0) {
6358                        getAudioService().adjustSuggestedStreamVolume(
6359                                AudioManager.ADJUST_TOGGLE_MUTE,
6360                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6361                    }
6362                } catch (Exception e) {
6363                    Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
6364                }
6365                break;
6366        }
6367    }
6368
6369    void dispatchMediaKeyWithWakeLock(KeyEvent event) {
6370        if (DEBUG_INPUT) {
6371            Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
6372        }
6373
6374        if (mHavePendingMediaKeyRepeatWithWakeLock) {
6375            if (DEBUG_INPUT) {
6376                Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
6377            }
6378
6379            mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
6380            mHavePendingMediaKeyRepeatWithWakeLock = false;
6381            mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
6382        }
6383
6384        dispatchMediaKeyWithWakeLockToAudioService(event);
6385
6386        if (event.getAction() == KeyEvent.ACTION_DOWN
6387                && event.getRepeatCount() == 0) {
6388            mHavePendingMediaKeyRepeatWithWakeLock = true;
6389
6390            Message msg = mHandler.obtainMessage(
6391                    MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
6392            msg.setAsynchronous(true);
6393            mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
6394        } else {
6395            mBroadcastWakeLock.release();
6396        }
6397    }
6398
6399    void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
6400        mHavePendingMediaKeyRepeatWithWakeLock = false;
6401
6402        KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
6403                SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6404        if (DEBUG_INPUT) {
6405            Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
6406        }
6407
6408        dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
6409        mBroadcastWakeLock.release();
6410    }
6411
6412    void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
6413        if (mActivityManagerInternal.isSystemReady()) {
6414            MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
6415        }
6416    }
6417
6418    void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
6419        IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
6420                ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
6421        if (dic != null) {
6422            try {
6423                dic.exitIdle("voice-search");
6424            } catch (RemoteException e) {
6425            }
6426        }
6427        Intent voiceIntent =
6428            new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
6429        voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
6430        startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
6431        mBroadcastWakeLock.release();
6432    }
6433
6434    BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
6435        @Override
6436        public void onReceive(Context context, Intent intent) {
6437            if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
6438                mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6439                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
6440            } else {
6441                try {
6442                    IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
6443                            ServiceManager.getService(Context.UI_MODE_SERVICE));
6444                    mUiMode = uiModeService.getCurrentModeType();
6445                } catch (RemoteException e) {
6446                }
6447            }
6448            updateRotation(true);
6449            synchronized (mLock) {
6450                updateOrientationListenerLp();
6451            }
6452        }
6453    };
6454
6455    BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
6456        @Override
6457        public void onReceive(Context context, Intent intent) {
6458            if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
6459                if (mKeyguardDelegate != null) {
6460                    mKeyguardDelegate.onDreamingStarted();
6461                }
6462            } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
6463                if (mKeyguardDelegate != null) {
6464                    mKeyguardDelegate.onDreamingStopped();
6465                }
6466            }
6467        }
6468    };
6469
6470    BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
6471        @Override
6472        public void onReceive(Context context, Intent intent) {
6473            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
6474                // tickle the settings observer: this first ensures that we're
6475                // observing the relevant settings for the newly-active user,
6476                // and then updates our own bookkeeping based on the now-
6477                // current user.
6478                mSettingsObserver.onChange(false);
6479
6480                // force a re-application of focused window sysui visibility.
6481                // the window may never have been shown for this user
6482                // e.g. the keyguard when going through the new-user setup flow
6483                synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6484                    mLastSystemUiFlags = 0;
6485                    updateSystemUiVisibilityLw();
6486                }
6487            }
6488        }
6489    };
6490
6491    private final Runnable mHiddenNavPanic = new Runnable() {
6492        @Override
6493        public void run() {
6494            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6495                if (!isUserSetupComplete()) {
6496                    // Swipe-up for navigation bar is disabled during setup
6497                    return;
6498                }
6499                mPendingPanicGestureUptime = SystemClock.uptimeMillis();
6500                if (!isNavBarEmpty(mLastSystemUiFlags)) {
6501                    mNavigationBarController.showTransient();
6502                }
6503            }
6504        }
6505    };
6506
6507    private void requestTransientBars(WindowState swipeTarget) {
6508        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6509            if (!isUserSetupComplete()) {
6510                // Swipe-up for navigation bar is disabled during setup
6511                return;
6512            }
6513            boolean sb = mStatusBarController.checkShowTransientBarLw();
6514            boolean nb = mNavigationBarController.checkShowTransientBarLw()
6515                    && !isNavBarEmpty(mLastSystemUiFlags);
6516            if (sb || nb) {
6517                // Don't show status bar when swiping on already visible navigation bar
6518                if (!nb && swipeTarget == mNavigationBar) {
6519                    if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
6520                    return;
6521                }
6522                if (sb) mStatusBarController.showTransient();
6523                if (nb) mNavigationBarController.showTransient();
6524                mImmersiveModeConfirmation.confirmCurrentPrompt();
6525                updateSystemUiVisibilityLw();
6526            }
6527        }
6528    }
6529
6530    // Called on the PowerManager's Notifier thread.
6531    @Override
6532    public void startedGoingToSleep(int why) {
6533        if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
6534        mCameraGestureTriggeredDuringGoingToSleep = false;
6535        mGoingToSleep = true;
6536        if (mKeyguardDelegate != null) {
6537            mKeyguardDelegate.onStartedGoingToSleep(why);
6538        }
6539    }
6540
6541    // Called on the PowerManager's Notifier thread.
6542    @Override
6543    public void finishedGoingToSleep(int why) {
6544        EventLog.writeEvent(70000, 0);
6545        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
6546        MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
6547
6548        mGoingToSleep = false;
6549
6550        // We must get this work done here because the power manager will drop
6551        // the wake lock and let the system suspend once this function returns.
6552        synchronized (mLock) {
6553            mAwake = false;
6554            updateWakeGestureListenerLp();
6555            updateOrientationListenerLp();
6556            updateLockScreenTimeout();
6557        }
6558        if (mKeyguardDelegate != null) {
6559            mKeyguardDelegate.onFinishedGoingToSleep(why,
6560                    mCameraGestureTriggeredDuringGoingToSleep);
6561        }
6562        mCameraGestureTriggeredDuringGoingToSleep = false;
6563    }
6564
6565    // Called on the PowerManager's Notifier thread.
6566    @Override
6567    public void startedWakingUp() {
6568        EventLog.writeEvent(70000, 1);
6569        if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
6570
6571        // Since goToSleep performs these functions synchronously, we must
6572        // do the same here.  We cannot post this work to a handler because
6573        // that might cause it to become reordered with respect to what
6574        // may happen in a future call to goToSleep.
6575        synchronized (mLock) {
6576            mAwake = true;
6577
6578            updateWakeGestureListenerLp();
6579            updateOrientationListenerLp();
6580            updateLockScreenTimeout();
6581        }
6582
6583        if (mKeyguardDelegate != null) {
6584            mKeyguardDelegate.onStartedWakingUp();
6585        }
6586    }
6587
6588    // Called on the PowerManager's Notifier thread.
6589    @Override
6590    public void finishedWakingUp() {
6591        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
6592    }
6593
6594    private void wakeUpFromPowerKey(long eventTime) {
6595        wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
6596    }
6597
6598    private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
6599        final boolean theaterModeEnabled = isTheaterModeEnabled();
6600        if (!wakeInTheaterMode && theaterModeEnabled) {
6601            return false;
6602        }
6603
6604        if (theaterModeEnabled) {
6605            Settings.Global.putInt(mContext.getContentResolver(),
6606                    Settings.Global.THEATER_MODE_ON, 0);
6607        }
6608
6609        mPowerManager.wakeUp(wakeTime, reason);
6610        return true;
6611    }
6612
6613    private void finishKeyguardDrawn() {
6614        synchronized (mLock) {
6615            if (!mScreenOnEarly || mKeyguardDrawComplete) {
6616                return; // We are not awake yet or we have already informed of this event.
6617            }
6618
6619            mKeyguardDrawComplete = true;
6620            if (mKeyguardDelegate != null) {
6621                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6622            }
6623            mWindowManagerDrawComplete = false;
6624        }
6625
6626        // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
6627        // as well as enabling the orientation change logic/sensor.
6628        mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
6629                WAITING_FOR_DRAWN_TIMEOUT);
6630    }
6631
6632    // Called on the DisplayManager's DisplayPowerController thread.
6633    @Override
6634    public void screenTurnedOff() {
6635        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
6636
6637        updateScreenOffSleepToken(true);
6638        synchronized (mLock) {
6639            mScreenOnEarly = false;
6640            mScreenOnFully = false;
6641            mKeyguardDrawComplete = false;
6642            mWindowManagerDrawComplete = false;
6643            mScreenOnListener = null;
6644            updateOrientationListenerLp();
6645
6646            if (mKeyguardDelegate != null) {
6647                mKeyguardDelegate.onScreenTurnedOff();
6648            }
6649        }
6650        reportScreenStateToVrManager(false);
6651    }
6652
6653    private long getKeyguardDrawnTimeout() {
6654        final boolean bootCompleted =
6655                LocalServices.getService(SystemServiceManager.class).isBootCompleted();
6656        // Set longer timeout if it has not booted yet to prevent showing empty window.
6657        return bootCompleted ? 1000 : 5000;
6658    }
6659
6660    // Called on the DisplayManager's DisplayPowerController thread.
6661    @Override
6662    public void screenTurningOn(final ScreenOnListener screenOnListener) {
6663        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
6664
6665        updateScreenOffSleepToken(false);
6666        synchronized (mLock) {
6667            mScreenOnEarly = true;
6668            mScreenOnFully = false;
6669            mKeyguardDrawComplete = false;
6670            mWindowManagerDrawComplete = false;
6671            mScreenOnListener = screenOnListener;
6672
6673            if (mKeyguardDelegate != null) {
6674                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6675                mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT,
6676                        getKeyguardDrawnTimeout());
6677                mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
6678            } else {
6679                if (DEBUG_WAKEUP) Slog.d(TAG,
6680                        "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
6681                finishKeyguardDrawn();
6682            }
6683        }
6684    }
6685
6686    // Called on the DisplayManager's DisplayPowerController thread.
6687    @Override
6688    public void screenTurnedOn() {
6689        synchronized (mLock) {
6690            if (mKeyguardDelegate != null) {
6691                mKeyguardDelegate.onScreenTurnedOn();
6692            }
6693        }
6694        reportScreenStateToVrManager(true);
6695    }
6696
6697    @Override
6698    public void screenTurningOff(ScreenOffListener screenOffListener) {
6699        mWindowManagerFuncs.screenTurningOff(screenOffListener);
6700    }
6701
6702    private void reportScreenStateToVrManager(boolean isScreenOn) {
6703        if (mVrManagerInternal == null) {
6704            return;
6705        }
6706        mVrManagerInternal.onScreenStateChanged(isScreenOn);
6707    }
6708
6709    private void finishWindowsDrawn() {
6710        synchronized (mLock) {
6711            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
6712                return; // Screen is not turned on or we did already handle this case earlier.
6713            }
6714
6715            mWindowManagerDrawComplete = true;
6716        }
6717
6718        finishScreenTurningOn();
6719    }
6720
6721    private void finishScreenTurningOn() {
6722        synchronized (mLock) {
6723            // We have just finished drawing screen content. Since the orientation listener
6724            // gets only installed when all windows are drawn, we try to install it again.
6725            updateOrientationListenerLp();
6726        }
6727        final ScreenOnListener listener;
6728        final boolean enableScreen;
6729        synchronized (mLock) {
6730            if (DEBUG_WAKEUP) Slog.d(TAG,
6731                    "finishScreenTurningOn: mAwake=" + mAwake
6732                            + ", mScreenOnEarly=" + mScreenOnEarly
6733                            + ", mScreenOnFully=" + mScreenOnFully
6734                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
6735                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
6736
6737            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
6738                    || (mAwake && !mKeyguardDrawComplete)) {
6739                return; // spurious or not ready yet
6740            }
6741
6742            if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
6743            listener = mScreenOnListener;
6744            mScreenOnListener = null;
6745            mScreenOnFully = true;
6746
6747            // Remember the first time we draw the keyguard so we know when we're done with
6748            // the main part of booting and can enable the screen and hide boot messages.
6749            if (!mKeyguardDrawnOnce && mAwake) {
6750                mKeyguardDrawnOnce = true;
6751                enableScreen = true;
6752                if (mBootMessageNeedsHiding) {
6753                    mBootMessageNeedsHiding = false;
6754                    hideBootMessages();
6755                }
6756            } else {
6757                enableScreen = false;
6758            }
6759        }
6760
6761        if (listener != null) {
6762            listener.onScreenOn();
6763        }
6764
6765        if (enableScreen) {
6766            try {
6767                mWindowManager.enableScreenIfNeeded();
6768            } catch (RemoteException unhandled) {
6769            }
6770        }
6771    }
6772
6773    private void handleHideBootMessage() {
6774        synchronized (mLock) {
6775            if (!mKeyguardDrawnOnce) {
6776                mBootMessageNeedsHiding = true;
6777                return; // keyguard hasn't drawn the first time yet, not done booting
6778            }
6779        }
6780
6781        if (mBootMsgDialog != null) {
6782            if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
6783            mBootMsgDialog.dismiss();
6784            mBootMsgDialog = null;
6785        }
6786    }
6787
6788    @Override
6789    public boolean isScreenOn() {
6790        return mScreenOnFully;
6791    }
6792
6793    /** {@inheritDoc} */
6794    @Override
6795    public void enableKeyguard(boolean enabled) {
6796        if (mKeyguardDelegate != null) {
6797            mKeyguardDelegate.setKeyguardEnabled(enabled);
6798        }
6799    }
6800
6801    /** {@inheritDoc} */
6802    @Override
6803    public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
6804        if (mKeyguardDelegate != null) {
6805            mKeyguardDelegate.verifyUnlock(callback);
6806        }
6807    }
6808
6809    @Override
6810    public boolean isKeyguardShowingAndNotOccluded() {
6811        if (mKeyguardDelegate == null) return false;
6812        return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
6813    }
6814
6815    @Override
6816    public boolean isKeyguardTrustedLw() {
6817        if (mKeyguardDelegate == null) return false;
6818        return mKeyguardDelegate.isTrusted();
6819    }
6820
6821    /** {@inheritDoc} */
6822    @Override
6823    public boolean isKeyguardLocked() {
6824        return keyguardOn();
6825    }
6826
6827    /** {@inheritDoc} */
6828    @Override
6829    public boolean isKeyguardSecure(int userId) {
6830        if (mKeyguardDelegate == null) return false;
6831        return mKeyguardDelegate.isSecure(userId);
6832    }
6833
6834    /** {@inheritDoc} */
6835    @Override
6836    public boolean isKeyguardOccluded() {
6837        if (mKeyguardDelegate == null) return false;
6838        return mKeyguardOccluded;
6839    }
6840
6841    /** {@inheritDoc} */
6842    @Override
6843    public boolean inKeyguardRestrictedKeyInputMode() {
6844        if (mKeyguardDelegate == null) return false;
6845        return mKeyguardDelegate.isInputRestricted();
6846    }
6847
6848    @Override
6849    public void dismissKeyguardLw(IKeyguardDismissCallback callback) {
6850        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
6851            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
6852
6853            // ask the keyguard to prompt the user to authenticate if necessary
6854            mKeyguardDelegate.dismiss(callback);
6855        } else if (callback != null) {
6856            try {
6857                callback.onDismissError();
6858            } catch (RemoteException e) {
6859                Slog.w(TAG, "Failed to call callback", e);
6860            }
6861        }
6862    }
6863
6864    @Override
6865    public boolean isKeyguardDrawnLw() {
6866        synchronized (mLock) {
6867            return mKeyguardDrawnOnce;
6868        }
6869    }
6870
6871    @Override
6872    public boolean isShowingDreamLw() {
6873        return mShowingDream;
6874    }
6875
6876    @Override
6877    public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
6878        if (mKeyguardDelegate != null) {
6879            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
6880            mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
6881        }
6882    }
6883
6884    @Override
6885    public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6886            Rect outInsets) {
6887        outInsets.setEmpty();
6888
6889        // Navigation bar and status bar.
6890        getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
6891        outInsets.top = mStatusBarHeight;
6892    }
6893
6894    @Override
6895    public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6896            Rect outInsets) {
6897        outInsets.setEmpty();
6898
6899        // Only navigation bar
6900        if (mHasNavigationBar) {
6901            int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
6902            if (position == NAV_BAR_BOTTOM) {
6903                outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
6904            } else if (position == NAV_BAR_RIGHT) {
6905                outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
6906            } else if (position == NAV_BAR_LEFT) {
6907                outInsets.left = getNavigationBarWidth(displayRotation, mUiMode);
6908            }
6909        }
6910    }
6911
6912    @Override
6913    public boolean isNavBarForcedShownLw(WindowState windowState) {
6914        return mForceShowSystemBars;
6915    }
6916
6917    @Override
6918    public boolean isDockSideAllowed(int dockSide) {
6919
6920        // We do not allow all dock sides at which the navigation bar touches the docked stack.
6921        if (!mNavigationBarCanMove) {
6922            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT;
6923        } else {
6924            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT;
6925        }
6926    }
6927
6928    void sendCloseSystemWindows() {
6929        PhoneWindow.sendCloseSystemWindows(mContext, null);
6930    }
6931
6932    void sendCloseSystemWindows(String reason) {
6933        PhoneWindow.sendCloseSystemWindows(mContext, reason);
6934    }
6935
6936    @Override
6937    public int rotationForOrientationLw(int orientation, int lastRotation) {
6938        if (false) {
6939            Slog.v(TAG, "rotationForOrientationLw(orient="
6940                        + orientation + ", last=" + lastRotation
6941                        + "); user=" + mUserRotation + " "
6942                        + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
6943                            ? "USER_ROTATION_LOCKED" : "")
6944                        );
6945        }
6946
6947        if (mForceDefaultOrientation) {
6948            return Surface.ROTATION_0;
6949        }
6950
6951        synchronized (mLock) {
6952            int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
6953            if (sensorRotation < 0) {
6954                sensorRotation = lastRotation;
6955            }
6956
6957            final int preferredRotation;
6958            if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
6959                // Ignore sensor when lid switch is open and rotation is forced.
6960                preferredRotation = mLidOpenRotation;
6961            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
6962                    && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
6963                // Ignore sensor when in car dock unless explicitly enabled.
6964                // This case can override the behavior of NOSENSOR, and can also
6965                // enable 180 degree rotation while docked.
6966                preferredRotation = mCarDockEnablesAccelerometer
6967                        ? sensorRotation : mCarDockRotation;
6968            } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
6969                    || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
6970                    || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
6971                    && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
6972                // Ignore sensor when in desk dock unless explicitly enabled.
6973                // This case can override the behavior of NOSENSOR, and can also
6974                // enable 180 degree rotation while docked.
6975                preferredRotation = mDeskDockEnablesAccelerometer
6976                        ? sensorRotation : mDeskDockRotation;
6977            } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
6978                // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
6979                // Note that the dock orientation overrides the HDMI orientation.
6980                preferredRotation = mDemoHdmiRotation;
6981            } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
6982                    && mUndockedHdmiRotation >= 0) {
6983                // Ignore sensor when plugged into HDMI and an undocked orientation has
6984                // been specified in the configuration (only for legacy devices without
6985                // full multi-display support).
6986                // Note that the dock orientation overrides the HDMI orientation.
6987                preferredRotation = mUndockedHdmiRotation;
6988            } else if (mDemoRotationLock) {
6989                // Ignore sensor when demo rotation lock is enabled.
6990                // Note that the dock orientation and HDMI rotation lock override this.
6991                preferredRotation = mDemoRotation;
6992            } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
6993                // Application just wants to remain locked in the last rotation.
6994                preferredRotation = lastRotation;
6995            } else if (!mSupportAutoRotation) {
6996                // If we don't support auto-rotation then bail out here and ignore
6997                // the sensor and any rotation lock settings.
6998                preferredRotation = -1;
6999            } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
7000                            && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
7001                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
7002                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
7003                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
7004                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
7005                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
7006                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
7007                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
7008                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
7009                // Otherwise, use sensor only if requested by the application or enabled
7010                // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
7011                if (mAllowAllRotations < 0) {
7012                    // Can't read this during init() because the context doesn't
7013                    // have display metrics at that time so we cannot determine
7014                    // tablet vs. phone then.
7015                    mAllowAllRotations = mContext.getResources().getBoolean(
7016                            com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
7017                }
7018                if (sensorRotation != Surface.ROTATION_180
7019                        || mAllowAllRotations == 1
7020                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
7021                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
7022                    // In VrMode, we report the sensor as always being in default orientation so:
7023                    // 1) The orientation doesn't change as the user moves their head.
7024                    // 2) 2D apps within VR show in the device's default orientation.
7025                    // This only overwrites the sensor-provided orientation and does not affect any
7026                    // explicit orientation preferences specified by any activities.
7027                    preferredRotation =
7028                            mPersistentVrModeEnabled ? Surface.ROTATION_0 : sensorRotation;
7029                } else {
7030                    preferredRotation = lastRotation;
7031                }
7032            } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
7033                    && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
7034                // Apply rotation lock.  Does not apply to NOSENSOR.
7035                // The idea is that the user rotation expresses a weak preference for the direction
7036                // of gravity and as NOSENSOR is never affected by gravity, then neither should
7037                // NOSENSOR be affected by rotation lock (although it will be affected by docks).
7038                preferredRotation = mUserRotation;
7039            } else {
7040                // No overriding preference.
7041                // We will do exactly what the application asked us to do.
7042                preferredRotation = -1;
7043            }
7044
7045            switch (orientation) {
7046                case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
7047                    // Return portrait unless overridden.
7048                    if (isAnyPortrait(preferredRotation)) {
7049                        return preferredRotation;
7050                    }
7051                    return mPortraitRotation;
7052
7053                case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
7054                    // Return landscape unless overridden.
7055                    if (isLandscapeOrSeascape(preferredRotation)) {
7056                        return preferredRotation;
7057                    }
7058                    return mLandscapeRotation;
7059
7060                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
7061                    // Return reverse portrait unless overridden.
7062                    if (isAnyPortrait(preferredRotation)) {
7063                        return preferredRotation;
7064                    }
7065                    return mUpsideDownRotation;
7066
7067                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
7068                    // Return seascape unless overridden.
7069                    if (isLandscapeOrSeascape(preferredRotation)) {
7070                        return preferredRotation;
7071                    }
7072                    return mSeascapeRotation;
7073
7074                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
7075                case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
7076                    // Return either landscape rotation.
7077                    if (isLandscapeOrSeascape(preferredRotation)) {
7078                        return preferredRotation;
7079                    }
7080                    if (isLandscapeOrSeascape(lastRotation)) {
7081                        return lastRotation;
7082                    }
7083                    return mLandscapeRotation;
7084
7085                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
7086                case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
7087                    // Return either portrait rotation.
7088                    if (isAnyPortrait(preferredRotation)) {
7089                        return preferredRotation;
7090                    }
7091                    if (isAnyPortrait(lastRotation)) {
7092                        return lastRotation;
7093                    }
7094                    return mPortraitRotation;
7095
7096                default:
7097                    // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
7098                    // just return the preferred orientation we already calculated.
7099                    if (preferredRotation >= 0) {
7100                        return preferredRotation;
7101                    }
7102                    return Surface.ROTATION_0;
7103            }
7104        }
7105    }
7106
7107    @Override
7108    public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
7109        switch (orientation) {
7110            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
7111            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
7112            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
7113                return isAnyPortrait(rotation);
7114
7115            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
7116            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
7117            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
7118                return isLandscapeOrSeascape(rotation);
7119
7120            default:
7121                return true;
7122        }
7123    }
7124
7125    @Override
7126    public void setRotationLw(int rotation) {
7127        mOrientationListener.setCurrentRotation(rotation);
7128    }
7129
7130    private boolean isLandscapeOrSeascape(int rotation) {
7131        return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
7132    }
7133
7134    private boolean isAnyPortrait(int rotation) {
7135        return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
7136    }
7137
7138    @Override
7139    public int getUserRotationMode() {
7140        return Settings.System.getIntForUser(mContext.getContentResolver(),
7141                Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
7142                        WindowManagerPolicy.USER_ROTATION_FREE :
7143                                WindowManagerPolicy.USER_ROTATION_LOCKED;
7144    }
7145
7146    // User rotation: to be used when all else fails in assigning an orientation to the device
7147    @Override
7148    public void setUserRotationMode(int mode, int rot) {
7149        ContentResolver res = mContext.getContentResolver();
7150
7151        // mUserRotationMode and mUserRotation will be assigned by the content observer
7152        if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
7153            Settings.System.putIntForUser(res,
7154                    Settings.System.USER_ROTATION,
7155                    rot,
7156                    UserHandle.USER_CURRENT);
7157            Settings.System.putIntForUser(res,
7158                    Settings.System.ACCELEROMETER_ROTATION,
7159                    0,
7160                    UserHandle.USER_CURRENT);
7161        } else {
7162            Settings.System.putIntForUser(res,
7163                    Settings.System.ACCELEROMETER_ROTATION,
7164                    1,
7165                    UserHandle.USER_CURRENT);
7166        }
7167    }
7168
7169    @Override
7170    public void setSafeMode(boolean safeMode) {
7171        mSafeMode = safeMode;
7172        performHapticFeedbackLw(null, safeMode
7173                ? HapticFeedbackConstants.SAFE_MODE_ENABLED
7174                : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
7175    }
7176
7177    static long[] getLongIntArray(Resources r, int resid) {
7178        int[] ar = r.getIntArray(resid);
7179        if (ar == null) {
7180            return null;
7181        }
7182        long[] out = new long[ar.length];
7183        for (int i=0; i<ar.length; i++) {
7184            out[i] = ar[i];
7185        }
7186        return out;
7187    }
7188
7189    private void bindKeyguard() {
7190        synchronized (mLock) {
7191            if (mKeyguardBound) {
7192                return;
7193            }
7194            mKeyguardBound = true;
7195        }
7196        mKeyguardDelegate.bindService(mContext);
7197    }
7198
7199    @Override
7200    public void onSystemUiStarted() {
7201        bindKeyguard();
7202    }
7203
7204    /** {@inheritDoc} */
7205    @Override
7206    public void systemReady() {
7207        // In normal flow, systemReady is called before other system services are ready.
7208        // So it is better not to bind keyguard here.
7209        mKeyguardDelegate.onSystemReady();
7210
7211        mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
7212        if (mVrManagerInternal != null) {
7213            mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
7214        }
7215
7216        readCameraLensCoverState();
7217        updateUiMode();
7218        synchronized (mLock) {
7219            updateOrientationListenerLp();
7220            mSystemReady = true;
7221            mHandler.post(new Runnable() {
7222                @Override
7223                public void run() {
7224                    updateSettings();
7225                }
7226            });
7227            // If this happens, for whatever reason, systemReady came later than systemBooted.
7228            // And keyguard should be already bound from systemBooted
7229            if (mSystemBooted) {
7230                mKeyguardDelegate.onBootCompleted();
7231            }
7232        }
7233
7234        mSystemGestures.systemReady();
7235        mImmersiveModeConfirmation.systemReady();
7236    }
7237
7238    /** {@inheritDoc} */
7239    @Override
7240    public void systemBooted() {
7241        bindKeyguard();
7242        synchronized (mLock) {
7243            mSystemBooted = true;
7244            if (mSystemReady) {
7245                mKeyguardDelegate.onBootCompleted();
7246            }
7247        }
7248        startedWakingUp();
7249        screenTurningOn(null);
7250        screenTurnedOn();
7251    }
7252
7253    @Override
7254    public boolean canDismissBootAnimation() {
7255        synchronized (mLock) {
7256            return mKeyguardDrawComplete;
7257        }
7258    }
7259
7260    ProgressDialog mBootMsgDialog = null;
7261
7262    /** {@inheritDoc} */
7263    @Override
7264    public void showBootMessage(final CharSequence msg, final boolean always) {
7265        mHandler.post(new Runnable() {
7266            @Override public void run() {
7267                if (mBootMsgDialog == null) {
7268                    int theme;
7269                    if (mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK)) {
7270                        theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
7271                    } else {
7272                        theme = 0;
7273                    }
7274
7275                    mBootMsgDialog = new ProgressDialog(mContext, theme) {
7276                        // This dialog will consume all events coming in to
7277                        // it, to avoid it trying to do things too early in boot.
7278                        @Override public boolean dispatchKeyEvent(KeyEvent event) {
7279                            return true;
7280                        }
7281                        @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7282                            return true;
7283                        }
7284                        @Override public boolean dispatchTouchEvent(MotionEvent ev) {
7285                            return true;
7286                        }
7287                        @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
7288                            return true;
7289                        }
7290                        @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
7291                            return true;
7292                        }
7293                        @Override public boolean dispatchPopulateAccessibilityEvent(
7294                                AccessibilityEvent event) {
7295                            return true;
7296                        }
7297                    };
7298                    if (mContext.getPackageManager().isUpgrade()) {
7299                        mBootMsgDialog.setTitle(R.string.android_upgrading_title);
7300                    } else {
7301                        mBootMsgDialog.setTitle(R.string.android_start_title);
7302                    }
7303                    mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
7304                    mBootMsgDialog.setIndeterminate(true);
7305                    mBootMsgDialog.getWindow().setType(
7306                            WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
7307                    mBootMsgDialog.getWindow().addFlags(
7308                            WindowManager.LayoutParams.FLAG_DIM_BEHIND
7309                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
7310                    mBootMsgDialog.getWindow().setDimAmount(1);
7311                    WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
7312                    lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
7313                    mBootMsgDialog.getWindow().setAttributes(lp);
7314                    mBootMsgDialog.setCancelable(false);
7315                    mBootMsgDialog.show();
7316                }
7317                mBootMsgDialog.setMessage(msg);
7318            }
7319        });
7320    }
7321
7322    /** {@inheritDoc} */
7323    @Override
7324    public void hideBootMessages() {
7325        mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
7326    }
7327
7328    /** {@inheritDoc} */
7329    @Override
7330    public void userActivity() {
7331        // ***************************************
7332        // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
7333        // ***************************************
7334        // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
7335        // WITH ITS LOCKS HELD.
7336        //
7337        // This code must be VERY careful about the locks
7338        // it acquires.
7339        // In fact, the current code acquires way too many,
7340        // and probably has lurking deadlocks.
7341
7342        synchronized (mScreenLockTimeout) {
7343            if (mLockScreenTimerActive) {
7344                // reset the timer
7345                mHandler.removeCallbacks(mScreenLockTimeout);
7346                mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7347            }
7348        }
7349    }
7350
7351    class ScreenLockTimeout implements Runnable {
7352        Bundle options;
7353
7354        @Override
7355        public void run() {
7356            synchronized (this) {
7357                if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
7358                if (mKeyguardDelegate != null) {
7359                    mKeyguardDelegate.doKeyguardTimeout(options);
7360                }
7361                mLockScreenTimerActive = false;
7362                options = null;
7363            }
7364        }
7365
7366        public void setLockOptions(Bundle options) {
7367            this.options = options;
7368        }
7369    }
7370
7371    ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
7372
7373    @Override
7374    public void lockNow(Bundle options) {
7375        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
7376        mHandler.removeCallbacks(mScreenLockTimeout);
7377        if (options != null) {
7378            // In case multiple calls are made to lockNow, we don't wipe out the options
7379            // until the runnable actually executes.
7380            mScreenLockTimeout.setLockOptions(options);
7381        }
7382        mHandler.post(mScreenLockTimeout);
7383    }
7384
7385    private void updateLockScreenTimeout() {
7386        synchronized (mScreenLockTimeout) {
7387            boolean enable = (mAllowLockscreenWhenOn && mAwake &&
7388                    mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
7389            if (mLockScreenTimerActive != enable) {
7390                if (enable) {
7391                    if (localLOGV) Log.v(TAG, "setting lockscreen timer");
7392                    mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
7393                    mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7394                } else {
7395                    if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
7396                    mHandler.removeCallbacks(mScreenLockTimeout);
7397                }
7398                mLockScreenTimerActive = enable;
7399            }
7400        }
7401    }
7402
7403    private void updateDreamingSleepToken(boolean acquire) {
7404        if (acquire) {
7405            if (mDreamingSleepToken == null) {
7406                mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream");
7407            }
7408        } else {
7409            if (mDreamingSleepToken != null) {
7410                mDreamingSleepToken.release();
7411                mDreamingSleepToken = null;
7412            }
7413        }
7414    }
7415
7416    private void updateScreenOffSleepToken(boolean acquire) {
7417        if (acquire) {
7418            if (mScreenOffSleepToken == null) {
7419                mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff");
7420            }
7421        } else {
7422            if (mScreenOffSleepToken != null) {
7423                mScreenOffSleepToken.release();
7424                mScreenOffSleepToken = null;
7425            }
7426        }
7427    }
7428
7429    /** {@inheritDoc} */
7430    @Override
7431    public void enableScreenAfterBoot() {
7432        readLidState();
7433        applyLidSwitchState();
7434        updateRotation(true);
7435    }
7436
7437    private void applyLidSwitchState() {
7438        if (mLidState == LID_CLOSED && mLidControlsSleep) {
7439            mPowerManager.goToSleep(SystemClock.uptimeMillis(),
7440                    PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
7441                    PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
7442        } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
7443            mWindowManagerFuncs.lockDeviceNow();
7444        }
7445
7446        synchronized (mLock) {
7447            updateWakeGestureListenerLp();
7448        }
7449    }
7450
7451    void updateUiMode() {
7452        if (mUiModeManager == null) {
7453            mUiModeManager = IUiModeManager.Stub.asInterface(
7454                    ServiceManager.getService(Context.UI_MODE_SERVICE));
7455        }
7456        try {
7457            mUiMode = mUiModeManager.getCurrentModeType();
7458        } catch (RemoteException e) {
7459        }
7460    }
7461
7462    void updateRotation(boolean alwaysSendConfiguration) {
7463        try {
7464            //set orientation on WindowManager
7465            mWindowManager.updateRotation(alwaysSendConfiguration, false);
7466        } catch (RemoteException e) {
7467            // Ignore
7468        }
7469    }
7470
7471    void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
7472        try {
7473            //set orientation on WindowManager
7474            mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
7475        } catch (RemoteException e) {
7476            // Ignore
7477        }
7478    }
7479
7480    /**
7481     * Return an Intent to launch the currently active dock app as home.  Returns
7482     * null if the standard home should be launched, which is the case if any of the following is
7483     * true:
7484     * <ul>
7485     *  <li>The device is not in either car mode or desk mode
7486     *  <li>The device is in car mode but mEnableCarDockHomeCapture is false
7487     *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
7488     *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
7489     *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
7490     * </ul>
7491     * @return A dock intent.
7492     */
7493    Intent createHomeDockIntent() {
7494        Intent intent = null;
7495
7496        // What home does is based on the mode, not the dock state.  That
7497        // is, when in car mode you should be taken to car home regardless
7498        // of whether we are actually in a car dock.
7499        if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
7500            if (mEnableCarDockHomeCapture) {
7501                intent = mCarDockIntent;
7502            }
7503        } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
7504            if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
7505                intent = mDeskDockIntent;
7506            }
7507        } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
7508                && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7509                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
7510                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
7511            // Always launch dock home from home when watch is docked, if it exists.
7512            intent = mDeskDockIntent;
7513        } else if (mUiMode == Configuration.UI_MODE_TYPE_VR_HEADSET) {
7514            if (ENABLE_VR_HEADSET_HOME_CAPTURE) {
7515                intent = mVrHeadsetHomeIntent;
7516            }
7517        }
7518
7519        if (intent == null) {
7520            return null;
7521        }
7522
7523        ActivityInfo ai = null;
7524        ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
7525                intent,
7526                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
7527                mCurrentUserId);
7528        if (info != null) {
7529            ai = info.activityInfo;
7530        }
7531        if (ai != null
7532                && ai.metaData != null
7533                && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
7534            intent = new Intent(intent);
7535            intent.setClassName(ai.packageName, ai.name);
7536            return intent;
7537        }
7538
7539        return null;
7540    }
7541
7542    void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
7543        if (awakenFromDreams) {
7544            awakenDreams();
7545        }
7546
7547        Intent dock = createHomeDockIntent();
7548        if (dock != null) {
7549            try {
7550                if (fromHomeKey) {
7551                    dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7552                }
7553                startActivityAsUser(dock, UserHandle.CURRENT);
7554                return;
7555            } catch (ActivityNotFoundException e) {
7556            }
7557        }
7558
7559        Intent intent;
7560
7561        if (fromHomeKey) {
7562            intent = new Intent(mHomeIntent);
7563            intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7564        } else {
7565            intent = mHomeIntent;
7566        }
7567
7568        startActivityAsUser(intent, UserHandle.CURRENT);
7569    }
7570
7571    /**
7572     * goes to the home screen
7573     * @return whether it did anything
7574     */
7575    boolean goHome() {
7576        if (!isUserSetupComplete()) {
7577            Slog.i(TAG, "Not going home because user setup is in progress.");
7578            return false;
7579        }
7580        if (false) {
7581            // This code always brings home to the front.
7582            try {
7583                ActivityManager.getService().stopAppSwitches();
7584            } catch (RemoteException e) {
7585            }
7586            sendCloseSystemWindows();
7587            startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
7588        } else {
7589            // This code brings home to the front or, if it is already
7590            // at the front, puts the device to sleep.
7591            try {
7592                if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
7593                    /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
7594                    Log.d(TAG, "UTS-TEST-MODE");
7595                } else {
7596                    ActivityManager.getService().stopAppSwitches();
7597                    sendCloseSystemWindows();
7598                    Intent dock = createHomeDockIntent();
7599                    if (dock != null) {
7600                        int result = ActivityManager.getService()
7601                                .startActivityAsUser(null, null, dock,
7602                                        dock.resolveTypeIfNeeded(mContext.getContentResolver()),
7603                                        null, null, 0,
7604                                        ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7605                                        null, null, UserHandle.USER_CURRENT);
7606                        if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7607                            return false;
7608                        }
7609                    }
7610                }
7611                int result = ActivityManager.getService()
7612                        .startActivityAsUser(null, null, mHomeIntent,
7613                                mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
7614                                null, null, 0,
7615                                ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7616                                null, null, UserHandle.USER_CURRENT);
7617                if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7618                    return false;
7619                }
7620            } catch (RemoteException ex) {
7621                // bummer, the activity manager, which is in this process, is dead
7622            }
7623        }
7624        return true;
7625    }
7626
7627    @Override
7628    public void setCurrentOrientationLw(int newOrientation) {
7629        synchronized (mLock) {
7630            if (newOrientation != mCurrentAppOrientation) {
7631                mCurrentAppOrientation = newOrientation;
7632                updateOrientationListenerLp();
7633            }
7634        }
7635    }
7636
7637    private boolean isTheaterModeEnabled() {
7638        return Settings.Global.getInt(mContext.getContentResolver(),
7639                Settings.Global.THEATER_MODE_ON, 0) == 1;
7640    }
7641
7642    private boolean areSystemNavigationKeysEnabled() {
7643        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
7644                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 1, UserHandle.USER_CURRENT) == 1;
7645    }
7646
7647    @Override
7648    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
7649        if (!mVibrator.hasVibrator()) {
7650            return false;
7651        }
7652        final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
7653                Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
7654        if (hapticsDisabled && !always) {
7655            return false;
7656        }
7657
7658        VibrationEffect effect = getVibrationEffect(effectId);
7659        if (effect == null) {
7660            return false;
7661        }
7662
7663        int owningUid;
7664        String owningPackage;
7665        if (win != null) {
7666            owningUid = win.getOwningUid();
7667            owningPackage = win.getOwningPackage();
7668        } else {
7669            owningUid = android.os.Process.myUid();
7670            owningPackage = mContext.getOpPackageName();
7671        }
7672        mVibrator.vibrate(owningUid, owningPackage, effect, VIBRATION_ATTRIBUTES);
7673        return true;
7674    }
7675
7676    private VibrationEffect getVibrationEffect(int effectId) {
7677        long[] pattern;
7678        switch (effectId) {
7679            case HapticFeedbackConstants.VIRTUAL_KEY:
7680                return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
7681            case HapticFeedbackConstants.LONG_PRESS:
7682                pattern = mLongPressVibePattern;
7683                break;
7684            case HapticFeedbackConstants.KEYBOARD_TAP:
7685                return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
7686            case HapticFeedbackConstants.CLOCK_TICK:
7687                pattern = mClockTickVibePattern;
7688                break;
7689            case HapticFeedbackConstants.CALENDAR_DATE:
7690                pattern = mCalendarDateVibePattern;
7691                break;
7692            case HapticFeedbackConstants.SAFE_MODE_DISABLED:
7693                pattern = mSafeModeDisabledVibePattern;
7694                break;
7695            case HapticFeedbackConstants.SAFE_MODE_ENABLED:
7696                pattern = mSafeModeEnabledVibePattern;
7697                break;
7698            case HapticFeedbackConstants.CONTEXT_CLICK:
7699                pattern = mContextClickVibePattern;
7700                break;
7701            default:
7702                return null;
7703        }
7704        if (pattern.length == 0) {
7705            // No vibration
7706            return null;
7707        } else if (pattern.length == 1) {
7708            // One-shot vibration
7709            return VibrationEffect.createOneShot(pattern[0], VibrationEffect.DEFAULT_AMPLITUDE);
7710        } else {
7711            // Pattern vibration
7712            return VibrationEffect.createWaveform(pattern, -1);
7713        }
7714    }
7715
7716    @Override
7717    public void keepScreenOnStartedLw() {
7718    }
7719
7720    @Override
7721    public void keepScreenOnStoppedLw() {
7722        if (isKeyguardShowingAndNotOccluded()) {
7723            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
7724        }
7725    }
7726
7727    private int updateSystemUiVisibilityLw() {
7728        // If there is no window focused, there will be nobody to handle the events
7729        // anyway, so just hang on in whatever state we're in until things settle down.
7730        WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
7731                : mTopFullscreenOpaqueWindowState;
7732        if (winCandidate == null) {
7733            return 0;
7734        }
7735        if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
7736            // The immersive mode confirmation should never affect the system bar visibility,
7737            // otherwise it will unhide the navigation bar and hide itself.
7738            winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState;
7739            if (winCandidate == null) {
7740                return 0;
7741            }
7742        }
7743        final WindowState win = winCandidate;
7744        if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mKeyguardOccluded) {
7745            // We are updating at a point where the keyguard has gotten
7746            // focus, but we were last in a state where the top window is
7747            // hiding it.  This is probably because the keyguard as been
7748            // shown while the top window was displayed, so we want to ignore
7749            // it here because this is just a very transient change and it
7750            // will quickly lose focus once it correctly gets hidden.
7751            return 0;
7752        }
7753
7754        int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
7755                & ~mResettingSystemUiFlags
7756                & ~mForceClearedSystemUiFlags;
7757        if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
7758            tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
7759        }
7760
7761        final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
7762                mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
7763        final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
7764                mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
7765        mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);
7766        mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);
7767        final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
7768        final int diff = visibility ^ mLastSystemUiFlags;
7769        final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
7770        final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
7771        final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
7772        if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
7773                && mFocusedApp == win.getAppToken()
7774                && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
7775                && mLastDockedStackBounds.equals(mDockedStackBounds)) {
7776            return 0;
7777        }
7778        mLastSystemUiFlags = visibility;
7779        mLastFullscreenStackSysUiFlags = fullscreenVisibility;
7780        mLastDockedStackSysUiFlags = dockedVisibility;
7781        mLastFocusNeedsMenu = needsMenu;
7782        mFocusedApp = win.getAppToken();
7783        final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
7784        final Rect dockedStackBounds = new Rect(mDockedStackBounds);
7785        mHandler.post(new Runnable() {
7786                @Override
7787                public void run() {
7788                    StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
7789                    if (statusbar != null) {
7790                        statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
7791                                dockedVisibility, 0xffffffff, fullscreenStackBounds,
7792                                dockedStackBounds, win.toString());
7793                        statusbar.topAppWindowChanged(needsMenu);
7794                    }
7795                }
7796            });
7797        return diff;
7798    }
7799
7800    private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
7801        WindowState statusColorWin = isStatusBarKeyguard() && !mKeyguardOccluded
7802                ? mStatusBar
7803                : opaqueOrDimming;
7804
7805        if (statusColorWin != null) {
7806            if (statusColorWin == opaque) {
7807                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7808                // its light flag.
7809                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7810                vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
7811                        & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7812            } else if (statusColorWin != null && statusColorWin.isDimming()) {
7813                // Otherwise if it's dimming, clear the light flag.
7814                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7815            }
7816        }
7817        return vis;
7818    }
7819
7820    private int updateLightNavigationBarLw(int vis, WindowState opaque,
7821            WindowState opaqueOrDimming) {
7822        final WindowState imeWin = mWindowManagerFuncs.getInputMethodWindowLw();
7823
7824        final WindowState navColorWin;
7825        if (imeWin != null && imeWin.isVisibleLw()) {
7826            navColorWin = imeWin;
7827        } else {
7828            navColorWin = opaqueOrDimming;
7829        }
7830
7831        if (navColorWin != null) {
7832            if (navColorWin == opaque) {
7833                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7834                // its light flag.
7835                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7836                vis |= PolicyControl.getSystemUiVisibility(navColorWin, null)
7837                        & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7838            } else if (navColorWin.isDimming() || navColorWin == imeWin) {
7839                // Otherwise if it's dimming or it's the IME window, clear the light flag.
7840                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7841            }
7842        }
7843        return vis;
7844    }
7845
7846    private boolean drawsSystemBarBackground(WindowState win) {
7847        return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
7848    }
7849
7850    private boolean forcesDrawStatusBarBackground(WindowState win) {
7851        return win == null || (win.getAttrs().privateFlags
7852                & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
7853    }
7854
7855    private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
7856        final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
7857        final boolean freeformStackVisible =
7858                mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
7859        final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
7860
7861        // We need to force system bars when the docked stack is visible, when the freeform stack
7862        // is visible but also when we are resizing for the transitions when docked stack
7863        // visibility changes.
7864        mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
7865        final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
7866
7867        // apply translucent bar vis flags
7868        WindowState fullscreenTransWin = isStatusBarKeyguard() && !mKeyguardOccluded
7869                ? mStatusBar
7870                : mTopFullscreenOpaqueWindowState;
7871        vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7872        vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7873        final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
7874                mTopDockedOpaqueWindowState, 0, 0);
7875
7876        final boolean fullscreenDrawsStatusBarBackground =
7877                (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
7878                        && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
7879                || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
7880        final boolean dockedDrawsStatusBarBackground =
7881                (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
7882                        && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
7883                || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
7884
7885        // prevent status bar interaction from clearing certain flags
7886        int type = win.getAttrs().type;
7887        boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
7888        if (statusBarHasFocus && !isStatusBarKeyguard()) {
7889            int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
7890                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
7891                    | View.SYSTEM_UI_FLAG_IMMERSIVE
7892                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
7893                    | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7894            if (mKeyguardOccluded) {
7895                flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
7896            }
7897            vis = (vis & ~flags) | (oldVis & flags);
7898        }
7899
7900        if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
7901            vis |= View.STATUS_BAR_TRANSPARENT;
7902            vis &= ~View.STATUS_BAR_TRANSLUCENT;
7903        } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
7904                || forceOpaqueStatusBar) {
7905            vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
7906        }
7907
7908        vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
7909
7910        // update status bar
7911        boolean immersiveSticky =
7912                (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7913        final boolean hideStatusBarWM =
7914                mTopFullscreenOpaqueWindowState != null
7915                && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
7916                        & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
7917        final boolean hideStatusBarSysui =
7918                (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
7919        final boolean hideNavBarSysui =
7920                (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
7921
7922        final boolean transientStatusBarAllowed = mStatusBar != null
7923                && (statusBarHasFocus || (!mForceShowSystemBars
7924                        && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
7925
7926        final boolean transientNavBarAllowed = mNavigationBar != null
7927                && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
7928
7929        final long now = SystemClock.uptimeMillis();
7930        final boolean pendingPanic = mPendingPanicGestureUptime != 0
7931                && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
7932        if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
7933            // The user performed the panic gesture recently, we're about to hide the bars,
7934            // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
7935            mPendingPanicGestureUptime = 0;
7936            mStatusBarController.showTransient();
7937            if (!isNavBarEmpty(vis)) {
7938                mNavigationBarController.showTransient();
7939            }
7940        }
7941
7942        final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
7943                && !transientStatusBarAllowed && hideStatusBarSysui;
7944        final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
7945                && !transientNavBarAllowed;
7946        if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
7947            // clear the clearable flags instead
7948            clearClearableFlagsLw();
7949            vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
7950        }
7951
7952        final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
7953        immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7954        final boolean navAllowedHidden = immersive || immersiveSticky;
7955
7956        if (hideNavBarSysui && !navAllowedHidden
7957                && getWindowLayerLw(win) > getWindowLayerFromTypeLw(TYPE_INPUT_CONSUMER)) {
7958            // We can't hide the navbar from this window otherwise the input consumer would not get
7959            // the input events.
7960            vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
7961        }
7962
7963        vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
7964
7965        // update navigation bar
7966        boolean oldImmersiveMode = isImmersiveMode(oldVis);
7967        boolean newImmersiveMode = isImmersiveMode(vis);
7968        if (win != null && oldImmersiveMode != newImmersiveMode) {
7969            final String pkg = win.getOwningPackage();
7970            mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
7971                    isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility()));
7972        }
7973
7974        vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
7975
7976        vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState,
7977                mTopFullscreenOpaqueOrDimmingWindowState);
7978
7979        return vis;
7980    }
7981
7982    /**
7983     * @return the current visibility flags with the nav-bar opacity related flags toggled based
7984     *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
7985     */
7986    private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
7987            boolean freeformStackVisible, boolean isDockedDividerResizing) {
7988        if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
7989            if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
7990                visibility = setNavBarOpaqueFlag(visibility);
7991            }
7992        } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
7993            if (isDockedDividerResizing) {
7994                visibility = setNavBarOpaqueFlag(visibility);
7995            } else if (freeformStackVisible) {
7996                visibility = setNavBarTranslucentFlag(visibility);
7997            } else {
7998                visibility = setNavBarOpaqueFlag(visibility);
7999            }
8000        }
8001
8002        if (!areTranslucentBarsAllowed()) {
8003            visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
8004        }
8005        return visibility;
8006    }
8007
8008    private int setNavBarOpaqueFlag(int visibility) {
8009        return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
8010    }
8011
8012    private int setNavBarTranslucentFlag(int visibility) {
8013        visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
8014        return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
8015    }
8016
8017    private void clearClearableFlagsLw() {
8018        int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
8019        if (newVal != mResettingSystemUiFlags) {
8020            mResettingSystemUiFlags = newVal;
8021            mWindowManagerFuncs.reevaluateStatusBarVisibility();
8022        }
8023    }
8024
8025    private boolean isImmersiveMode(int vis) {
8026        final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
8027        return mNavigationBar != null
8028                && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
8029                && (vis & flags) != 0
8030                && canHideNavigationBar();
8031    }
8032
8033    private static boolean isNavBarEmpty(int systemUiFlags) {
8034        final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
8035                | View.STATUS_BAR_DISABLE_BACK
8036                | View.STATUS_BAR_DISABLE_RECENT);
8037
8038        return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
8039    }
8040
8041    /**
8042     * @return whether the navigation or status bar can be made translucent
8043     *
8044     * This should return true unless touch exploration is not enabled or
8045     * R.boolean.config_enableTranslucentDecor is false.
8046     */
8047    private boolean areTranslucentBarsAllowed() {
8048        return mTranslucentDecorEnabled;
8049    }
8050
8051    // Use this instead of checking config_showNavigationBar so that it can be consistently
8052    // overridden by qemu.hw.mainkeys in the emulator.
8053    @Override
8054    public boolean hasNavigationBar() {
8055        return mHasNavigationBar;
8056    }
8057
8058    @Override
8059    public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
8060        mLastInputMethodWindow = ime;
8061        mLastInputMethodTargetWindow = target;
8062    }
8063
8064    @Override
8065    public void setDismissImeOnBackKeyPressed(boolean newValue) {
8066        mDismissImeOnBackKeyPressed = newValue;
8067    }
8068
8069    @Override
8070    public int getInputMethodWindowVisibleHeightLw() {
8071        return mDockBottom - mCurBottom;
8072    }
8073
8074    @Override
8075    public void setCurrentUserLw(int newUserId) {
8076        mCurrentUserId = newUserId;
8077        if (mKeyguardDelegate != null) {
8078            mKeyguardDelegate.setCurrentUser(newUserId);
8079        }
8080        if (mAccessibilityShortcutController != null) {
8081            mAccessibilityShortcutController.setCurrentUser(newUserId);
8082        }
8083        StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
8084        if (statusBar != null) {
8085            statusBar.setCurrentUser(newUserId);
8086        }
8087        setLastInputMethodWindowLw(null, null);
8088    }
8089
8090    @Override
8091    public void setSwitchingUser(boolean switching) {
8092        mKeyguardDelegate.setSwitchingUser(switching);
8093    }
8094
8095    @Override
8096    public boolean canMagnifyWindow(int windowType) {
8097        switch (windowType) {
8098            case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
8099            case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
8100            case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
8101            case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
8102                return false;
8103            }
8104        }
8105        return true;
8106    }
8107
8108    @Override
8109    public boolean isTopLevelWindow(int windowType) {
8110        if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
8111                && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
8112            return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
8113        }
8114        return true;
8115    }
8116
8117    @Override
8118    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
8119        // For the upside down rotation we don't rotate seamlessly as the navigation
8120        // bar moves position.
8121        // Note most apps (using orientation:sensor or user as opposed to fullSensor)
8122        // will not enter the reverse portrait orientation, so actually the
8123        // orientation won't change at all.
8124        if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
8125            return false;
8126        }
8127        // If the navigation bar can't change sides, then it will
8128        // jump when we change orientations and we don't rotate
8129        // seamlessly.
8130        if (!mNavigationBarCanMove) {
8131            return false;
8132        }
8133        int delta = newRotation - oldRotation;
8134        if (delta < 0) delta += 4;
8135        // Likewise we don't rotate seamlessly for 180 degree rotations
8136        // in this case the surfaces never resize, and our logic to
8137        // revert the transformations on size change will fail. We could
8138        // fix this in the future with the "tagged" frames idea.
8139        if (delta == Surface.ROTATION_180) {
8140            return false;
8141        }
8142
8143        final WindowState w = mTopFullscreenOpaqueWindowState;
8144        if (w != mFocusedWindow) {
8145            return false;
8146        }
8147
8148        // We only enable seamless rotation if the top window has requested
8149        // it and is in the fullscreen opaque state. Seamless rotation
8150        // requires freezing various Surface states and won't work well
8151        // with animations, so we disable it in the animation case for now.
8152        if (w != null && !w.isAnimatingLw() &&
8153                ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) ||
8154                        (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) {
8155            return true;
8156        }
8157        return false;
8158    }
8159
8160    @Override
8161    public void dump(String prefix, PrintWriter pw, String[] args) {
8162        pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
8163                pw.print(" mSystemReady="); pw.print(mSystemReady);
8164                pw.print(" mSystemBooted="); pw.println(mSystemBooted);
8165        pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
8166                pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
8167                pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
8168                pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
8169        if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
8170                || mForceClearedSystemUiFlags != 0) {
8171            pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
8172                    pw.print(Integer.toHexString(mLastSystemUiFlags));
8173                    pw.print(" mResettingSystemUiFlags=0x");
8174                    pw.print(Integer.toHexString(mResettingSystemUiFlags));
8175                    pw.print(" mForceClearedSystemUiFlags=0x");
8176                    pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
8177        }
8178        if (mLastFocusNeedsMenu) {
8179            pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
8180                    pw.println(mLastFocusNeedsMenu);
8181        }
8182        pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
8183                pw.println(mWakeGestureEnabledSetting);
8184
8185        pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
8186        pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
8187                pw.print(" mDockMode="); pw.print(mDockMode);
8188                pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
8189                pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
8190                pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
8191        pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
8192                pw.print(" mUserRotation="); pw.print(mUserRotation);
8193                pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
8194        pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
8195        pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
8196                pw.print(mCarDockEnablesAccelerometer);
8197                pw.print(" mDeskDockEnablesAccelerometer=");
8198                pw.println(mDeskDockEnablesAccelerometer);
8199        pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
8200                pw.print(mLidKeyboardAccessibility);
8201                pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
8202                pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
8203                pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
8204        pw.print(prefix);
8205                pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
8206        pw.print(prefix);
8207                pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
8208                pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
8209        pw.print(prefix);
8210                pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
8211                pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
8212        pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
8213        pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
8214        pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
8215                pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
8216        pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
8217                pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
8218        pw.print(prefix); pw.print("mOrientationSensorEnabled=");
8219                pw.println(mOrientationSensorEnabled);
8220        pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
8221                pw.print(","); pw.print(mOverscanScreenTop);
8222                pw.print(") "); pw.print(mOverscanScreenWidth);
8223                pw.print("x"); pw.println(mOverscanScreenHeight);
8224        if (mOverscanLeft != 0 || mOverscanTop != 0
8225                || mOverscanRight != 0 || mOverscanBottom != 0) {
8226            pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
8227                    pw.print(" top="); pw.print(mOverscanTop);
8228                    pw.print(" right="); pw.print(mOverscanRight);
8229                    pw.print(" bottom="); pw.println(mOverscanBottom);
8230        }
8231        pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
8232                pw.print(mRestrictedOverscanScreenLeft);
8233                pw.print(","); pw.print(mRestrictedOverscanScreenTop);
8234                pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
8235                pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
8236        pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
8237                pw.print(","); pw.print(mUnrestrictedScreenTop);
8238                pw.print(") "); pw.print(mUnrestrictedScreenWidth);
8239                pw.print("x"); pw.println(mUnrestrictedScreenHeight);
8240        pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
8241                pw.print(","); pw.print(mRestrictedScreenTop);
8242                pw.print(") "); pw.print(mRestrictedScreenWidth);
8243                pw.print("x"); pw.println(mRestrictedScreenHeight);
8244        pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
8245                pw.print(","); pw.print(mStableFullscreenTop);
8246                pw.print(")-("); pw.print(mStableFullscreenRight);
8247                pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
8248        pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
8249                pw.print(","); pw.print(mStableTop);
8250                pw.print(")-("); pw.print(mStableRight);
8251                pw.print(","); pw.print(mStableBottom); pw.println(")");
8252        pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
8253                pw.print(","); pw.print(mSystemTop);
8254                pw.print(")-("); pw.print(mSystemRight);
8255                pw.print(","); pw.print(mSystemBottom); pw.println(")");
8256        pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
8257                pw.print(","); pw.print(mCurTop);
8258                pw.print(")-("); pw.print(mCurRight);
8259                pw.print(","); pw.print(mCurBottom); pw.println(")");
8260        pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
8261                pw.print(","); pw.print(mContentTop);
8262                pw.print(")-("); pw.print(mContentRight);
8263                pw.print(","); pw.print(mContentBottom); pw.println(")");
8264        pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft);
8265                pw.print(","); pw.print(mVoiceContentTop);
8266                pw.print(")-("); pw.print(mVoiceContentRight);
8267                pw.print(","); pw.print(mVoiceContentBottom); pw.println(")");
8268        pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
8269                pw.print(","); pw.print(mDockTop);
8270                pw.print(")-("); pw.print(mDockRight);
8271                pw.print(","); pw.print(mDockBottom); pw.println(")");
8272        pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
8273                pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
8274        pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
8275                pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
8276                pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
8277        if (mLastInputMethodWindow != null) {
8278            pw.print(prefix); pw.print("mLastInputMethodWindow=");
8279                    pw.println(mLastInputMethodWindow);
8280        }
8281        if (mLastInputMethodTargetWindow != null) {
8282            pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
8283                    pw.println(mLastInputMethodTargetWindow);
8284        }
8285        pw.print(prefix); pw.print("mDismissImeOnBackKeyPressed=");
8286                pw.println(mDismissImeOnBackKeyPressed);
8287        if (mStatusBar != null) {
8288            pw.print(prefix); pw.print("mStatusBar=");
8289                    pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
8290                    pw.println(isStatusBarKeyguard());
8291        }
8292        if (mNavigationBar != null) {
8293            pw.print(prefix); pw.print("mNavigationBar=");
8294                    pw.println(mNavigationBar);
8295        }
8296        if (mFocusedWindow != null) {
8297            pw.print(prefix); pw.print("mFocusedWindow=");
8298                    pw.println(mFocusedWindow);
8299        }
8300        if (mFocusedApp != null) {
8301            pw.print(prefix); pw.print("mFocusedApp=");
8302                    pw.println(mFocusedApp);
8303        }
8304        if (mTopFullscreenOpaqueWindowState != null) {
8305            pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
8306                    pw.println(mTopFullscreenOpaqueWindowState);
8307        }
8308        if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
8309            pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
8310                    pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
8311        }
8312        if (mForcingShowNavBar) {
8313            pw.print(prefix); pw.print("mForcingShowNavBar=");
8314                    pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
8315                    pw.println(mForcingShowNavBarLayer);
8316        }
8317        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
8318                pw.print(" mKeyguardOccluded="); pw.println(mKeyguardOccluded);
8319                pw.print(" mKeyguardOccludedChanged="); pw.println(mKeyguardOccludedChanged);
8320                pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded);
8321        pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
8322                pw.print(" mForceStatusBarFromKeyguard=");
8323                pw.println(mForceStatusBarFromKeyguard);
8324        pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
8325        pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
8326                pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
8327                pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
8328        pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
8329                pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
8330                pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior);
8331                pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
8332        pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
8333                pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
8334        pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
8335                pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
8336        pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
8337                pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
8338        pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
8339        if (mHasFeatureLeanback) {
8340            pw.print(prefix);
8341            pw.print("mAccessibilityTvKey1Pressed="); pw.println(mAccessibilityTvKey1Pressed);
8342            pw.print(prefix);
8343            pw.print("mAccessibilityTvKey2Pressed="); pw.println(mAccessibilityTvKey2Pressed);
8344            pw.print(prefix);
8345            pw.print("mAccessibilityTvScheduled="); pw.println(mAccessibilityTvScheduled);
8346        }
8347
8348        mGlobalKeyManager.dump(prefix, pw);
8349        mStatusBarController.dump(pw, prefix);
8350        mNavigationBarController.dump(pw, prefix);
8351        PolicyControl.dump(prefix, pw);
8352
8353        if (mWakeGestureListener != null) {
8354            mWakeGestureListener.dump(pw, prefix);
8355        }
8356        if (mOrientationListener != null) {
8357            mOrientationListener.dump(pw, prefix);
8358        }
8359        if (mBurnInProtectionHelper != null) {
8360            mBurnInProtectionHelper.dump(prefix, pw);
8361        }
8362        if (mKeyguardDelegate != null) {
8363            mKeyguardDelegate.dump(prefix, pw);
8364        }
8365    }
8366}
8367