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