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