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