PhoneWindowManager.java revision dc2b3be240705b53fa1749cbdaedd0a63931378d
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                if (mHasFeatureLeanback) {
3402                    // Clear flags
3403                    mAccessibilityTvKey2Pressed = down;
3404                }
3405
3406                mHomePressed = false;
3407                if (mHomeConsumed) {
3408                    mHomeConsumed = false;
3409                    return -1;
3410                }
3411
3412                if (canceled) {
3413                    Log.i(TAG, "Ignoring HOME; event canceled.");
3414                    return -1;
3415                }
3416
3417                // Delay handling home if a double-tap is possible.
3418                if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
3419                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
3420                    mHomeDoubleTapPending = true;
3421                    mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
3422                            ViewConfiguration.getDoubleTapTimeout());
3423                    return -1;
3424                }
3425
3426                handleShortPressOnHome();
3427                return -1;
3428            }
3429
3430            // If a system window has focus, then it doesn't make sense
3431            // right now to interact with applications.
3432            WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
3433            if (attrs != null) {
3434                final int type = attrs.type;
3435                if (type == TYPE_KEYGUARD_DIALOG
3436                        || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
3437                    // the "app" is keyguard, so give it the key
3438                    return 0;
3439                }
3440                final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
3441                for (int i=0; i<typeCount; i++) {
3442                    if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
3443                        // don't do anything, but also don't pass it to the app
3444                        return -1;
3445                    }
3446                }
3447            }
3448
3449            // Remember that home is pressed and handle special actions.
3450            if (repeatCount == 0) {
3451                mHomePressed = true;
3452                if (mHomeDoubleTapPending) {
3453                    mHomeDoubleTapPending = false;
3454                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
3455                    handleDoubleTapOnHome();
3456                } else if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
3457                    preloadRecentApps();
3458                }
3459            } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
3460                if (mHasFeatureLeanback) {
3461                    mAccessibilityTvKey2Pressed = down;
3462                    if (interceptAccessibilityGestureTv()) {
3463                        return -1;
3464                    }
3465                }
3466
3467                if (!keyguardOn) {
3468                    handleLongPressOnHome(event.getDeviceId());
3469                }
3470            }
3471            return -1;
3472        } else if (keyCode == KeyEvent.KEYCODE_MENU) {
3473            // Hijack modified menu keys for debugging features
3474            final int chordBug = KeyEvent.META_SHIFT_ON;
3475
3476            if (down && repeatCount == 0) {
3477                if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
3478                    Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
3479                    mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
3480                            null, null, null, 0, null, null);
3481                    return -1;
3482                }
3483            }
3484        } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
3485            if (down) {
3486                if (repeatCount == 0) {
3487                    mSearchKeyShortcutPending = true;
3488                    mConsumeSearchKeyUp = false;
3489                }
3490            } else {
3491                mSearchKeyShortcutPending = false;
3492                if (mConsumeSearchKeyUp) {
3493                    mConsumeSearchKeyUp = false;
3494                    return -1;
3495                }
3496            }
3497            return 0;
3498        } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
3499            if (!keyguardOn) {
3500                if (down && repeatCount == 0) {
3501                    preloadRecentApps();
3502                } else if (!down) {
3503                    toggleRecentApps();
3504                }
3505            }
3506            return -1;
3507        } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) {
3508            if (down) {
3509                IStatusBarService service = getStatusBarService();
3510                if (service != null) {
3511                    try {
3512                        service.expandNotificationsPanel();
3513                    } catch (RemoteException e) {
3514                        // do nothing.
3515                    }
3516                }
3517            }
3518        } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed()
3519                && event.isCtrlPressed()) {
3520            if (down && repeatCount == 0) {
3521                int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION
3522                        : TAKE_SCREENSHOT_FULLSCREEN;
3523                mScreenshotRunnable.setScreenshotType(type);
3524                mHandler.post(mScreenshotRunnable);
3525                return -1;
3526            }
3527        } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
3528            if (down && repeatCount == 0 && !isKeyguardLocked()) {
3529                toggleKeyboardShortcutsMenu(event.getDeviceId());
3530            }
3531        } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
3532            if (down) {
3533                if (repeatCount == 0) {
3534                    mAssistKeyLongPressed = false;
3535                } else if (repeatCount == 1) {
3536                    mAssistKeyLongPressed = true;
3537                    if (!keyguardOn) {
3538                         launchAssistLongPressAction();
3539                    }
3540                }
3541            } else {
3542                if (mAssistKeyLongPressed) {
3543                    mAssistKeyLongPressed = false;
3544                } else {
3545                    if (!keyguardOn) {
3546                        launchAssistAction(null, event.getDeviceId());
3547                    }
3548                }
3549            }
3550            return -1;
3551        } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
3552            if (!down) {
3553                Intent voiceIntent;
3554                if (!keyguardOn) {
3555                    voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
3556                } else {
3557                    IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
3558                            ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
3559                    if (dic != null) {
3560                        try {
3561                            dic.exitIdle("voice-search");
3562                        } catch (RemoteException e) {
3563                        }
3564                    }
3565                    voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
3566                    voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
3567                }
3568                startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
3569            }
3570        } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
3571            if (down && repeatCount == 0) {
3572                mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
3573                mHandler.post(mScreenshotRunnable);
3574            }
3575            return -1;
3576        } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP
3577                || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) {
3578            if (down) {
3579                int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
3580
3581                // Disable autobrightness if it's on
3582                int auto = Settings.System.getIntForUser(
3583                        mContext.getContentResolver(),
3584                        Settings.System.SCREEN_BRIGHTNESS_MODE,
3585                        Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3586                        UserHandle.USER_CURRENT_OR_SELF);
3587                if (auto != 0) {
3588                    Settings.System.putIntForUser(mContext.getContentResolver(),
3589                            Settings.System.SCREEN_BRIGHTNESS_MODE,
3590                            Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3591                            UserHandle.USER_CURRENT_OR_SELF);
3592                }
3593
3594                int min = mPowerManager.getMinimumScreenBrightnessSetting();
3595                int max = mPowerManager.getMaximumScreenBrightnessSetting();
3596                int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction;
3597                int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
3598                        Settings.System.SCREEN_BRIGHTNESS,
3599                        mPowerManager.getDefaultScreenBrightnessSetting(),
3600                        UserHandle.USER_CURRENT_OR_SELF);
3601                brightness += step;
3602                // Make sure we don't go beyond the limits.
3603                brightness = Math.min(max, brightness);
3604                brightness = Math.max(min, brightness);
3605
3606                Settings.System.putIntForUser(mContext.getContentResolver(),
3607                        Settings.System.SCREEN_BRIGHTNESS, brightness,
3608                        UserHandle.USER_CURRENT_OR_SELF);
3609                startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
3610                        UserHandle.CURRENT_OR_SELF);
3611            }
3612            return -1;
3613        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
3614                || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3615                || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
3616            if (mUseTvRouting || mHandleVolumeKeysInWM) {
3617                // On TVs or when the configuration is enabled, volume keys never
3618                // go to the foreground app.
3619                dispatchDirectAudioEvent(event);
3620                return -1;
3621            }
3622
3623            // If the device is in Vr mode, drop the volume keys and don't
3624            // forward it to the application/dispatch the audio event.
3625            if (mPersistentVrModeEnabled) {
3626                return -1;
3627            }
3628        } else if (keyCode == KeyEvent.KEYCODE_TAB && event.isMetaPressed()) {
3629            // Pass through keyboard navigation keys.
3630            return 0;
3631        } else if (mHasFeatureLeanback && interceptBugreportGestureTv(keyCode, down)) {
3632            return -1;
3633        } else if (mHasFeatureLeanback && keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
3634            mAccessibilityTvKey1Pressed = down;
3635            if (interceptAccessibilityGestureTv()) {
3636                return -1;
3637            }
3638        }
3639
3640        // Toggle Caps Lock on META-ALT.
3641        boolean actionTriggered = false;
3642        if (KeyEvent.isModifierKey(keyCode)) {
3643            if (!mPendingCapsLockToggle) {
3644                // Start tracking meta state for combo.
3645                mInitialMetaState = mMetaState;
3646                mPendingCapsLockToggle = true;
3647            } else if (event.getAction() == KeyEvent.ACTION_UP) {
3648                int altOnMask = mMetaState & KeyEvent.META_ALT_MASK;
3649                int metaOnMask = mMetaState & KeyEvent.META_META_MASK;
3650
3651                // Check for Caps Lock toggle
3652                if ((metaOnMask != 0) && (altOnMask != 0)) {
3653                    // Check if nothing else is pressed
3654                    if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) {
3655                        // Handle Caps Lock Toggle
3656                        mInputManagerInternal.toggleCapsLock(event.getDeviceId());
3657                        actionTriggered = true;
3658                    }
3659                }
3660
3661                // Always stop tracking when key goes up.
3662                mPendingCapsLockToggle = false;
3663            }
3664        }
3665        // Store current meta state to be able to evaluate it later.
3666        mMetaState = metaState;
3667
3668        if (actionTriggered) {
3669            return -1;
3670        }
3671
3672        if (KeyEvent.isMetaKey(keyCode)) {
3673            if (down) {
3674                mPendingMetaAction = true;
3675            } else if (mPendingMetaAction) {
3676                launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId());
3677            }
3678            return -1;
3679        }
3680
3681        // Shortcuts are invoked through Search+key, so intercept those here
3682        // Any printing key that is chorded with Search should be consumed
3683        // even if no shortcut was invoked.  This prevents text from being
3684        // inadvertently inserted when using a keyboard that has built-in macro
3685        // shortcut keys (that emit Search+x) and some of them are not registered.
3686        if (mSearchKeyShortcutPending) {
3687            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3688            if (kcm.isPrintingKey(keyCode)) {
3689                mConsumeSearchKeyUp = true;
3690                mSearchKeyShortcutPending = false;
3691                if (down && repeatCount == 0 && !keyguardOn) {
3692                    Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
3693                    if (shortcutIntent != null) {
3694                        shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3695                        try {
3696                            startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3697                            dismissKeyboardShortcutsMenu();
3698                        } catch (ActivityNotFoundException ex) {
3699                            Slog.w(TAG, "Dropping shortcut key combination because "
3700                                    + "the activity to which it is registered was not found: "
3701                                    + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);
3702                        }
3703                    } else {
3704                        Slog.i(TAG, "Dropping unregistered shortcut key combination: "
3705                                + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));
3706                    }
3707                }
3708                return -1;
3709            }
3710        }
3711
3712        // Invoke shortcuts using Meta.
3713        if (down && repeatCount == 0 && !keyguardOn
3714                && (metaState & KeyEvent.META_META_ON) != 0) {
3715            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3716            if (kcm.isPrintingKey(keyCode)) {
3717                Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
3718                        metaState & ~(KeyEvent.META_META_ON
3719                                | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
3720                if (shortcutIntent != null) {
3721                    shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3722                    try {
3723                        startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3724                        dismissKeyboardShortcutsMenu();
3725                    } catch (ActivityNotFoundException ex) {
3726                        Slog.w(TAG, "Dropping shortcut key combination because "
3727                                + "the activity to which it is registered was not found: "
3728                                + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
3729                    }
3730                    return -1;
3731                }
3732            }
3733        }
3734
3735        // Handle application launch keys.
3736        if (down && repeatCount == 0 && !keyguardOn) {
3737            String category = sApplicationLaunchKeyCategories.get(keyCode);
3738            if (category != null) {
3739                Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
3740                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3741                try {
3742                    startActivityAsUser(intent, UserHandle.CURRENT);
3743                    dismissKeyboardShortcutsMenu();
3744                } catch (ActivityNotFoundException ex) {
3745                    Slog.w(TAG, "Dropping application launch key because "
3746                            + "the activity to which it is registered was not found: "
3747                            + "keyCode=" + keyCode + ", category=" + category, ex);
3748                }
3749                return -1;
3750            }
3751        }
3752
3753        // Display task switcher for ALT-TAB.
3754        if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
3755            if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
3756                final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
3757                if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
3758                    mRecentAppsHeldModifiers = shiftlessModifiers;
3759                    showRecentApps(true, false);
3760                    return -1;
3761                }
3762            }
3763        } else if (!down && mRecentAppsHeldModifiers != 0
3764                && (metaState & mRecentAppsHeldModifiers) == 0) {
3765            mRecentAppsHeldModifiers = 0;
3766            hideRecentApps(true, false);
3767        }
3768
3769        // Handle input method switching.
3770        if (down && repeatCount == 0
3771                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3772                        || (keyCode == KeyEvent.KEYCODE_SPACE
3773                                && (metaState & KeyEvent.META_META_MASK) != 0))) {
3774            final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0;
3775            mWindowManagerFuncs.switchInputMethod(forwardDirection);
3776            return -1;
3777        }
3778        if (mLanguageSwitchKeyPressed && !down
3779                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3780                        || keyCode == KeyEvent.KEYCODE_SPACE)) {
3781            mLanguageSwitchKeyPressed = false;
3782            return -1;
3783        }
3784
3785        if (isValidGlobalKey(keyCode)
3786                && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
3787            return -1;
3788        }
3789
3790        if (down) {
3791            long shortcutCode = keyCode;
3792            if (event.isCtrlPressed()) {
3793                shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
3794            }
3795
3796            if (event.isAltPressed()) {
3797                shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
3798            }
3799
3800            if (event.isShiftPressed()) {
3801                shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
3802            }
3803
3804            if (event.isMetaPressed()) {
3805                shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE;
3806            }
3807
3808            IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode);
3809            if (shortcutService != null) {
3810                try {
3811                    if (isUserSetupComplete()) {
3812                        shortcutService.notifyShortcutKeyPressed(shortcutCode);
3813                    }
3814                } catch (RemoteException e) {
3815                    mShortcutKeyServices.delete(shortcutCode);
3816                }
3817                return -1;
3818            }
3819        }
3820
3821        // Reserve all the META modifier combos for system behavior
3822        if ((metaState & KeyEvent.META_META_ON) != 0) {
3823            return -1;
3824        }
3825
3826        // Let the application handle the key.
3827        return 0;
3828    }
3829
3830    /**
3831     * TV only: recognizes a remote control gesture for capturing a bug report.
3832     */
3833    private boolean interceptBugreportGestureTv(int keyCode, boolean down) {
3834        // The bugreport capture chord is a long press on DPAD CENTER and BACK simultaneously.
3835        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
3836            mBugreportTvKey1Pressed = down;
3837        } else if (keyCode == KeyEvent.KEYCODE_BACK) {
3838            mBugreportTvKey2Pressed = down;
3839        }
3840
3841        if (mBugreportTvKey1Pressed && mBugreportTvKey2Pressed) {
3842            if (!mBugreportTvScheduled) {
3843                mBugreportTvScheduled = true;
3844                Message msg = Message.obtain(mHandler, MSG_BUGREPORT_TV);
3845                msg.setAsynchronous(true);
3846                mHandler.sendMessageDelayed(msg, BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS);
3847            }
3848        } else if (mBugreportTvScheduled) {
3849            mHandler.removeMessages(MSG_BUGREPORT_TV);
3850            mBugreportTvScheduled = false;
3851        }
3852
3853        return mBugreportTvScheduled;
3854    }
3855
3856    /**
3857     * TV only: recognizes a remote control gesture as Accessibility shortcut.
3858     * Shortcut: Long press (HOME + DPAD_CENTER)
3859     */
3860    private boolean interceptAccessibilityGestureTv() {
3861        if (mAccessibilityTvKey1Pressed && mAccessibilityTvKey2Pressed) {
3862            if (!mAccessibilityTvScheduled) {
3863                mAccessibilityTvScheduled = true;
3864                Message msg = Message.obtain(mHandler, MSG_ACCESSIBILITY_TV);
3865                msg.setAsynchronous(true);
3866                mHandler.sendMessage(msg);
3867            }
3868        } else if (mAccessibilityTvScheduled) {
3869            mHandler.removeMessages(MSG_ACCESSIBILITY_TV);
3870            mAccessibilityTvScheduled = false;
3871        }
3872        return mAccessibilityTvScheduled;
3873    }
3874
3875    private void takeBugreport() {
3876        if ("1".equals(SystemProperties.get("ro.debuggable"))
3877                || Settings.Global.getInt(mContext.getContentResolver(),
3878                        Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) == 1) {
3879            try {
3880                ActivityManager.getService()
3881                        .requestBugReport(ActivityManager.BUGREPORT_OPTION_INTERACTIVE);
3882            } catch (RemoteException e) {
3883                Slog.e(TAG, "Error taking bugreport", e);
3884            }
3885        }
3886    }
3887
3888    /** {@inheritDoc} */
3889    @Override
3890    public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
3891        // Note: This method is only called if the initial down was unhandled.
3892        if (DEBUG_INPUT) {
3893            Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
3894                    + ", flags=" + event.getFlags()
3895                    + ", keyCode=" + event.getKeyCode()
3896                    + ", scanCode=" + event.getScanCode()
3897                    + ", metaState=" + event.getMetaState()
3898                    + ", repeatCount=" + event.getRepeatCount()
3899                    + ", policyFlags=" + policyFlags);
3900        }
3901
3902        KeyEvent fallbackEvent = null;
3903        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3904            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3905            final int keyCode = event.getKeyCode();
3906            final int metaState = event.getMetaState();
3907            final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
3908                    && event.getRepeatCount() == 0;
3909
3910            // Check for fallback actions specified by the key character map.
3911            final FallbackAction fallbackAction;
3912            if (initialDown) {
3913                fallbackAction = kcm.getFallbackAction(keyCode, metaState);
3914            } else {
3915                fallbackAction = mFallbackActions.get(keyCode);
3916            }
3917
3918            if (fallbackAction != null) {
3919                if (DEBUG_INPUT) {
3920                    Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode
3921                            + " metaState=" + Integer.toHexString(fallbackAction.metaState));
3922                }
3923
3924                final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
3925                fallbackEvent = KeyEvent.obtain(
3926                        event.getDownTime(), event.getEventTime(),
3927                        event.getAction(), fallbackAction.keyCode,
3928                        event.getRepeatCount(), fallbackAction.metaState,
3929                        event.getDeviceId(), event.getScanCode(),
3930                        flags, event.getSource(), null);
3931
3932                if (!interceptFallback(win, fallbackEvent, policyFlags)) {
3933                    fallbackEvent.recycle();
3934                    fallbackEvent = null;
3935                }
3936
3937                if (initialDown) {
3938                    mFallbackActions.put(keyCode, fallbackAction);
3939                } else if (event.getAction() == KeyEvent.ACTION_UP) {
3940                    mFallbackActions.remove(keyCode);
3941                    fallbackAction.recycle();
3942                }
3943            }
3944        }
3945
3946        if (DEBUG_INPUT) {
3947            if (fallbackEvent == null) {
3948                Slog.d(TAG, "No fallback.");
3949            } else {
3950                Slog.d(TAG, "Performing fallback: " + fallbackEvent);
3951            }
3952        }
3953        return fallbackEvent;
3954    }
3955
3956    private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
3957        int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
3958        if ((actions & ACTION_PASS_TO_USER) != 0) {
3959            long delayMillis = interceptKeyBeforeDispatching(
3960                    win, fallbackEvent, policyFlags);
3961            if (delayMillis == 0) {
3962                return true;
3963            }
3964        }
3965        return false;
3966    }
3967
3968    @Override
3969    public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
3970            throws RemoteException {
3971        synchronized (mLock) {
3972            IShortcutService service = mShortcutKeyServices.get(shortcutCode);
3973            if (service != null && service.asBinder().pingBinder()) {
3974                throw new RemoteException("Key already exists.");
3975            }
3976
3977            mShortcutKeyServices.put(shortcutCode, shortcutService);
3978        }
3979    }
3980
3981    @Override
3982    public void onKeyguardOccludedChangedLw(boolean occluded) {
3983        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
3984            mPendingKeyguardOccluded = occluded;
3985            mKeyguardOccludedChanged = true;
3986        } else {
3987            setKeyguardOccludedLw(occluded, false /* force */);
3988        }
3989    }
3990
3991    private int handleStartTransitionForKeyguardLw(int transit, @Nullable Animation anim) {
3992        if (mKeyguardOccludedChanged) {
3993            if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded="
3994                    + mPendingKeyguardOccluded);
3995            mKeyguardOccludedChanged = false;
3996            if (setKeyguardOccludedLw(mPendingKeyguardOccluded, false /* force */)) {
3997                return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER;
3998            }
3999        }
4000        if (AppTransition.isKeyguardGoingAwayTransit(transit)) {
4001            if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation");
4002            final long startTime = anim != null
4003                    ? SystemClock.uptimeMillis() + anim.getStartOffset()
4004                    : SystemClock.uptimeMillis();
4005            final long duration = anim != null
4006                    ? anim.getDuration()
4007                    : 0;
4008            startKeyguardExitAnimation(startTime, duration);
4009        }
4010        return 0;
4011    }
4012
4013    private void launchAssistLongPressAction() {
4014        performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
4015        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
4016
4017        // launch the search activity
4018        Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
4019        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
4020        try {
4021            // TODO: This only stops the factory-installed search manager.
4022            // Need to formalize an API to handle others
4023            SearchManager searchManager = getSearchManager();
4024            if (searchManager != null) {
4025                searchManager.stopSearch();
4026            }
4027            startActivityAsUser(intent, UserHandle.CURRENT);
4028        } catch (ActivityNotFoundException e) {
4029            Slog.w(TAG, "No activity to handle assist long press action.", e);
4030        }
4031    }
4032
4033    private void launchAssistAction(String hint, int deviceId) {
4034        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
4035        if (!isUserSetupComplete()) {
4036            // Disable opening assist window during setup
4037            return;
4038        }
4039        Bundle args = null;
4040        if (deviceId > Integer.MIN_VALUE) {
4041            args = new Bundle();
4042            args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
4043        }
4044        if ((mContext.getResources().getConfiguration().uiMode
4045                & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
4046            // On TV, use legacy handling until assistants are implemented in the proper way.
4047            ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
4048                    .launchLegacyAssist(hint, UserHandle.myUserId(), args);
4049        } else {
4050            if (hint != null) {
4051                if (args == null) {
4052                    args = new Bundle();
4053                }
4054                args.putBoolean(hint, true);
4055            }
4056            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4057            if (statusbar != null) {
4058                statusbar.startAssist(args);
4059            }
4060        }
4061    }
4062
4063    private void startActivityAsUser(Intent intent, UserHandle handle) {
4064        if (isUserSetupComplete()) {
4065            mContext.startActivityAsUser(intent, handle);
4066        } else {
4067            Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent);
4068        }
4069    }
4070
4071    private SearchManager getSearchManager() {
4072        if (mSearchManager == null) {
4073            mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
4074        }
4075        return mSearchManager;
4076    }
4077
4078    private void preloadRecentApps() {
4079        mPreloadedRecentApps = true;
4080        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4081        if (statusbar != null) {
4082            statusbar.preloadRecentApps();
4083        }
4084    }
4085
4086    private void cancelPreloadRecentApps() {
4087        if (mPreloadedRecentApps) {
4088            mPreloadedRecentApps = false;
4089            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4090            if (statusbar != null) {
4091                statusbar.cancelPreloadRecentApps();
4092            }
4093        }
4094    }
4095
4096    private void toggleRecentApps() {
4097        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
4098        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4099        if (statusbar != null) {
4100            statusbar.toggleRecentApps();
4101        }
4102    }
4103
4104    @Override
4105    public void showRecentApps(boolean fromHome) {
4106        mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
4107        mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget();
4108    }
4109
4110    private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
4111        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
4112        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4113        if (statusbar != null) {
4114            statusbar.showRecentApps(triggeredFromAltTab, fromHome);
4115        }
4116    }
4117
4118    private void toggleKeyboardShortcutsMenu(int deviceId) {
4119        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4120        if (statusbar != null) {
4121            statusbar.toggleKeyboardShortcutsMenu(deviceId);
4122        }
4123    }
4124
4125    private void dismissKeyboardShortcutsMenu() {
4126        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4127        if (statusbar != null) {
4128            statusbar.dismissKeyboardShortcutsMenu();
4129        }
4130    }
4131
4132    private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
4133        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
4134        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4135        if (statusbar != null) {
4136            statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
4137        }
4138    }
4139
4140    void launchHomeFromHotKey() {
4141        launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/);
4142    }
4143
4144    /**
4145     * A home key -> launch home action was detected.  Take the appropriate action
4146     * given the situation with the keyguard.
4147     */
4148    void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) {
4149        if (respectKeyguard) {
4150            if (isKeyguardShowingAndNotOccluded()) {
4151                // don't launch home if keyguard showing
4152                return;
4153            }
4154
4155            if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) {
4156                // when in keyguard restricted mode, must first verify unlock
4157                // before launching home
4158                mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
4159                    @Override
4160                    public void onKeyguardExitResult(boolean success) {
4161                        if (success) {
4162                            try {
4163                                ActivityManager.getService().stopAppSwitches();
4164                            } catch (RemoteException e) {
4165                            }
4166                            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
4167                            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
4168                        }
4169                    }
4170                });
4171                return;
4172            }
4173        }
4174
4175        // no keyguard stuff to worry about, just launch home!
4176        try {
4177            ActivityManager.getService().stopAppSwitches();
4178        } catch (RemoteException e) {
4179        }
4180        if (mRecentsVisible) {
4181            // Hide Recents and notify it to launch Home
4182            if (awakenFromDreams) {
4183                awakenDreams();
4184            }
4185            hideRecentApps(false, true);
4186        } else {
4187            // Otherwise, just launch Home
4188            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
4189            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
4190        }
4191    }
4192
4193    private final Runnable mClearHideNavigationFlag = new Runnable() {
4194        @Override
4195        public void run() {
4196            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
4197                // Clear flags.
4198                mForceClearedSystemUiFlags &=
4199                        ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
4200            }
4201            mWindowManagerFuncs.reevaluateStatusBarVisibility();
4202        }
4203    };
4204
4205    /**
4206     * Input handler used while nav bar is hidden.  Captures any touch on the screen,
4207     * to determine when the nav bar should be shown and prevent applications from
4208     * receiving those touches.
4209     */
4210    final class HideNavInputEventReceiver extends InputEventReceiver {
4211        public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
4212            super(inputChannel, looper);
4213        }
4214
4215        @Override
4216        public void onInputEvent(InputEvent event, int displayId) {
4217            boolean handled = false;
4218            try {
4219                if (event instanceof MotionEvent
4220                        && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
4221                    final MotionEvent motionEvent = (MotionEvent)event;
4222                    if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
4223                        // When the user taps down, we re-show the nav bar.
4224                        boolean changed = false;
4225                        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
4226                            if (mInputConsumer == null) {
4227                                return;
4228                            }
4229                            // Any user activity always causes us to show the
4230                            // navigation controls, if they had been hidden.
4231                            // We also clear the low profile and only content
4232                            // flags so that tapping on the screen will atomically
4233                            // restore all currently hidden screen decorations.
4234                            int newVal = mResettingSystemUiFlags |
4235                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
4236                                    View.SYSTEM_UI_FLAG_LOW_PROFILE |
4237                                    View.SYSTEM_UI_FLAG_FULLSCREEN;
4238                            if (mResettingSystemUiFlags != newVal) {
4239                                mResettingSystemUiFlags = newVal;
4240                                changed = true;
4241                            }
4242                            // We don't allow the system's nav bar to be hidden
4243                            // again for 1 second, to prevent applications from
4244                            // spamming us and keeping it from being shown.
4245                            newVal = mForceClearedSystemUiFlags |
4246                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
4247                            if (mForceClearedSystemUiFlags != newVal) {
4248                                mForceClearedSystemUiFlags = newVal;
4249                                changed = true;
4250                                mHandler.postDelayed(mClearHideNavigationFlag, 1000);
4251                            }
4252                        }
4253                        if (changed) {
4254                            mWindowManagerFuncs.reevaluateStatusBarVisibility();
4255                        }
4256                    }
4257                }
4258            } finally {
4259                finishInputEvent(event, handled);
4260            }
4261        }
4262    }
4263
4264    @Override
4265    public void setRecentsVisibilityLw(boolean visible) {
4266        mRecentsVisible = visible;
4267    }
4268
4269    @Override
4270    public void setPipVisibilityLw(boolean visible) {
4271        mPictureInPictureVisible = visible;
4272    }
4273
4274    @Override
4275    public int adjustSystemUiVisibilityLw(int visibility) {
4276        mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4277        mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4278
4279        // Reset any bits in mForceClearingStatusBarVisibility that
4280        // are now clear.
4281        mResettingSystemUiFlags &= visibility;
4282        // Clear any bits in the new visibility that are currently being
4283        // force cleared, before reporting it.
4284        return visibility & ~mResettingSystemUiFlags
4285                & ~mForceClearedSystemUiFlags;
4286    }
4287
4288    @Override
4289    public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
4290            int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets,
4291            Rect outStableInsets, Rect outOutsets) {
4292        final int fl = PolicyControl.getWindowFlags(null, attrs);
4293        final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
4294        final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
4295
4296        final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
4297        if (useOutsets) {
4298            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
4299            if (outset > 0) {
4300                if (displayRotation == Surface.ROTATION_0) {
4301                    outOutsets.bottom += outset;
4302                } else if (displayRotation == Surface.ROTATION_90) {
4303                    outOutsets.right += outset;
4304                } else if (displayRotation == Surface.ROTATION_180) {
4305                    outOutsets.top += outset;
4306                } else if (displayRotation == Surface.ROTATION_270) {
4307                    outOutsets.left += outset;
4308                }
4309            }
4310        }
4311
4312        if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4313                == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4314            int availRight, availBottom;
4315            if (canHideNavigationBar() &&
4316                    (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
4317                availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4318                availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4319            } else {
4320                availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
4321                availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4322            }
4323            if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4324                if ((fl & FLAG_FULLSCREEN) != 0) {
4325                    outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop,
4326                            availRight - mStableFullscreenRight,
4327                            availBottom - mStableFullscreenBottom);
4328                } else {
4329                    outContentInsets.set(mStableLeft, mStableTop,
4330                            availRight - mStableRight, availBottom - mStableBottom);
4331                }
4332            } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
4333                outContentInsets.setEmpty();
4334            } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
4335                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
4336                outContentInsets.set(mCurLeft, mCurTop,
4337                        availRight - mCurRight, availBottom - mCurBottom);
4338            } else {
4339                outContentInsets.set(mCurLeft, mCurTop,
4340                        availRight - mCurRight, availBottom - mCurBottom);
4341            }
4342
4343            outStableInsets.set(mStableLeft, mStableTop,
4344                    availRight - mStableRight, availBottom - mStableBottom);
4345            if (taskBounds != null) {
4346                calculateRelevantTaskInsets(taskBounds, outContentInsets,
4347                        displayWidth, displayHeight);
4348                calculateRelevantTaskInsets(taskBounds, outStableInsets,
4349                        displayWidth, displayHeight);
4350            }
4351            return mForceShowSystemBars;
4352        }
4353        outContentInsets.setEmpty();
4354        outStableInsets.setEmpty();
4355        return mForceShowSystemBars;
4356    }
4357
4358    /**
4359     * For any given task bounds, the insets relevant for these bounds given the insets relevant
4360     * for the entire display.
4361     */
4362    private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth,
4363            int displayHeight) {
4364        mTmpRect.set(0, 0, displayWidth, displayHeight);
4365        mTmpRect.inset(inOutInsets);
4366        mTmpRect.intersect(taskBounds);
4367        int leftInset = mTmpRect.left - taskBounds.left;
4368        int topInset = mTmpRect.top - taskBounds.top;
4369        int rightInset = taskBounds.right - mTmpRect.right;
4370        int bottomInset = taskBounds.bottom - mTmpRect.bottom;
4371        inOutInsets.set(leftInset, topInset, rightInset, bottomInset);
4372    }
4373
4374    private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
4375        return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
4376                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
4377    }
4378
4379    /** {@inheritDoc} */
4380    @Override
4381    public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
4382                              int displayRotation, int uiMode) {
4383        mDisplayRotation = displayRotation;
4384        final int overscanLeft, overscanTop, overscanRight, overscanBottom;
4385        if (isDefaultDisplay) {
4386            switch (displayRotation) {
4387                case Surface.ROTATION_90:
4388                    overscanLeft = mOverscanTop;
4389                    overscanTop = mOverscanRight;
4390                    overscanRight = mOverscanBottom;
4391                    overscanBottom = mOverscanLeft;
4392                    break;
4393                case Surface.ROTATION_180:
4394                    overscanLeft = mOverscanRight;
4395                    overscanTop = mOverscanBottom;
4396                    overscanRight = mOverscanLeft;
4397                    overscanBottom = mOverscanTop;
4398                    break;
4399                case Surface.ROTATION_270:
4400                    overscanLeft = mOverscanBottom;
4401                    overscanTop = mOverscanLeft;
4402                    overscanRight = mOverscanTop;
4403                    overscanBottom = mOverscanRight;
4404                    break;
4405                default:
4406                    overscanLeft = mOverscanLeft;
4407                    overscanTop = mOverscanTop;
4408                    overscanRight = mOverscanRight;
4409                    overscanBottom = mOverscanBottom;
4410                    break;
4411            }
4412        } else {
4413            overscanLeft = 0;
4414            overscanTop = 0;
4415            overscanRight = 0;
4416            overscanBottom = 0;
4417        }
4418        mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0;
4419        mOverscanScreenTop = mRestrictedOverscanScreenTop = 0;
4420        mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth;
4421        mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight;
4422        mSystemLeft = 0;
4423        mSystemTop = 0;
4424        mSystemRight = displayWidth;
4425        mSystemBottom = displayHeight;
4426        mUnrestrictedScreenLeft = overscanLeft;
4427        mUnrestrictedScreenTop = overscanTop;
4428        mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight;
4429        mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom;
4430        mRestrictedScreenLeft = mUnrestrictedScreenLeft;
4431        mRestrictedScreenTop = mUnrestrictedScreenTop;
4432        mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth;
4433        mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight;
4434        mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft
4435                = mCurLeft = mUnrestrictedScreenLeft;
4436        mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop
4437                = mCurTop = mUnrestrictedScreenTop;
4438        mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight
4439                = mCurRight = displayWidth - overscanRight;
4440        mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom
4441                = mCurBottom = displayHeight - overscanBottom;
4442        mDockLayer = 0x10000000;
4443        mStatusBarLayer = -1;
4444
4445        // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
4446        final Rect pf = mTmpParentFrame;
4447        final Rect df = mTmpDisplayFrame;
4448        final Rect of = mTmpOverscanFrame;
4449        final Rect vf = mTmpVisibleFrame;
4450        final Rect dcf = mTmpDecorFrame;
4451        pf.left = df.left = of.left = vf.left = mDockLeft;
4452        pf.top = df.top = of.top = vf.top = mDockTop;
4453        pf.right = df.right = of.right = vf.right = mDockRight;
4454        pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom;
4455        dcf.setEmpty();  // Decor frame N/A for system bars.
4456
4457        if (isDefaultDisplay) {
4458            // For purposes of putting out fake window up to steal focus, we will
4459            // drive nav being hidden only by whether it is requested.
4460            final int sysui = mLastSystemUiFlags;
4461            boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
4462            boolean navTranslucent = (sysui
4463                    & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
4464            boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
4465            boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
4466            boolean navAllowedHidden = immersive || immersiveSticky;
4467            navTranslucent &= !immersiveSticky;  // transient trumps translucent
4468            boolean isKeyguardShowing = isStatusBarKeyguard() && !mKeyguardOccluded;
4469            if (!isKeyguardShowing) {
4470                navTranslucent &= areTranslucentBarsAllowed();
4471            }
4472            boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null
4473                    && mStatusBar.getAttrs().height == MATCH_PARENT
4474                    && mStatusBar.getAttrs().width == MATCH_PARENT;
4475
4476            // When the navigation bar isn't visible, we put up a fake
4477            // input window to catch all touch events.  This way we can
4478            // detect when the user presses anywhere to bring back the nav
4479            // bar and ensure the application doesn't see the event.
4480            if (navVisible || navAllowedHidden) {
4481                if (mInputConsumer != null) {
4482                    mHandler.sendMessage(
4483                            mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
4484                    mInputConsumer = null;
4485                }
4486            } else if (mInputConsumer == null) {
4487                mInputConsumer = mWindowManagerFuncs.createInputConsumer(mHandler.getLooper(),
4488                        INPUT_CONSUMER_NAVIGATION,
4489                        (channel, looper) -> new HideNavInputEventReceiver(channel, looper));
4490                // As long as mInputConsumer is active, hover events are not dispatched to the app
4491                // and the pointer icon is likely to become stale. Hide it to avoid confusion.
4492                InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL);
4493            }
4494
4495            // For purposes of positioning and showing the nav bar, if we have
4496            // decided that it can't be hidden (because of the screen aspect ratio),
4497            // then take that into account.
4498            navVisible |= !canHideNavigationBar();
4499
4500            boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight,
4501                    displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom, dcf, navVisible, navTranslucent,
4502                    navAllowedHidden, statusBarExpandedNotKeyguard);
4503            if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
4504                    mDockLeft, mDockTop, mDockRight, mDockBottom));
4505            updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing);
4506            if (updateSysUiVisibility) {
4507                updateSystemUiVisibilityLw();
4508            }
4509        }
4510    }
4511
4512    private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui,
4513            boolean isKeyguardShowing) {
4514        // decide where the status bar goes ahead of time
4515        if (mStatusBar != null) {
4516            // apply any navigation bar insets
4517            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4518            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4519            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4520            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
4521                    + mUnrestrictedScreenTop;
4522            vf.left = mStableLeft;
4523            vf.top = mStableTop;
4524            vf.right = mStableRight;
4525            vf.bottom = mStableBottom;
4526
4527            mStatusBarLayer = mStatusBar.getSurfaceLayer();
4528
4529            // Let the status bar determine its size.
4530            mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
4531                    vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
4532                    dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */);
4533
4534            // For layout, the status bar is always at the top with our fixed height.
4535            mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
4536
4537            boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
4538            boolean statusBarTranslucent = (sysui
4539                    & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
4540            if (!isKeyguardShowing) {
4541                statusBarTranslucent &= areTranslucentBarsAllowed();
4542            }
4543
4544            // If the status bar is hidden, we don't want to cause
4545            // windows behind it to scroll.
4546            if (mStatusBar.isVisibleLw() && !statusBarTransient) {
4547                // Status bar may go away, so the screen area it occupies
4548                // is available to apps but just covering them when the
4549                // status bar is visible.
4550                mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
4551
4552                mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4553                mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4554                mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4555                mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4556
4557                if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " +
4558                        String.format(
4559                                "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
4560                                mDockLeft, mDockTop, mDockRight, mDockBottom,
4561                                mContentLeft, mContentTop, mContentRight, mContentBottom,
4562                                mCurLeft, mCurTop, mCurRight, mCurBottom));
4563            }
4564            if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
4565                    && !statusBarTransient && !statusBarTranslucent
4566                    && !mStatusBarController.wasRecentlyTranslucent()) {
4567                // If the opaque status bar is currently requested to be visible,
4568                // and not in the process of animating on or off, then
4569                // we can tell the app that it is covered by it.
4570                mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
4571            }
4572            if (mStatusBarController.checkHiddenLw()) {
4573                return true;
4574            }
4575        }
4576        return false;
4577    }
4578
4579    private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation,
4580            int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf,
4581            boolean navVisible, boolean navTranslucent, boolean navAllowedHidden,
4582            boolean statusBarExpandedNotKeyguard) {
4583        if (mNavigationBar != null) {
4584            boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
4585            // Force the navigation bar to its appropriate place and
4586            // size.  We need to do this directly, instead of relying on
4587            // it to bubble up from the nav bar, because this needs to
4588            // change atomically with screen rotations.
4589            mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight,
4590                    displayRotation);
4591            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
4592                // It's a system nav bar or a portrait screen; nav bar goes on bottom.
4593                int top = displayHeight - overscanBottom
4594                        - getNavigationBarHeight(displayRotation, uiMode);
4595                mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
4596                mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
4597                if (transientNavBarShowing) {
4598                    mNavigationBarController.setBarShowingLw(true);
4599                } else if (navVisible) {
4600                    mNavigationBarController.setBarShowingLw(true);
4601                    mDockBottom = mTmpNavigationFrame.top;
4602                    mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
4603                    mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
4604                } else {
4605                    // We currently want to hide the navigation UI - unless we expanded the status
4606                    // bar.
4607                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4608                }
4609                if (navVisible && !navTranslucent && !navAllowedHidden
4610                        && !mNavigationBar.isAnimatingLw()
4611                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4612                    // If the opaque nav bar is currently requested to be visible,
4613                    // and not in the process of animating on or off, then
4614                    // we can tell the app that it is covered by it.
4615                    mSystemBottom = mTmpNavigationFrame.top;
4616                }
4617            } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4618                // Landscape screen; nav bar goes to the right.
4619                int left = displayWidth - overscanRight
4620                        - getNavigationBarWidth(displayRotation, uiMode);
4621                mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
4622                mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
4623                if (transientNavBarShowing) {
4624                    mNavigationBarController.setBarShowingLw(true);
4625                } else if (navVisible) {
4626                    mNavigationBarController.setBarShowingLw(true);
4627                    mDockRight = mTmpNavigationFrame.left;
4628                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4629                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4630                } else {
4631                    // We currently want to hide the navigation UI - unless we expanded the status
4632                    // bar.
4633                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4634                }
4635                if (navVisible && !navTranslucent && !navAllowedHidden
4636                        && !mNavigationBar.isAnimatingLw()
4637                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4638                    // If the nav bar is currently requested to be visible,
4639                    // and not in the process of animating on or off, then
4640                    // we can tell the app that it is covered by it.
4641                    mSystemRight = mTmpNavigationFrame.left;
4642                }
4643            } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4644                // Seascape screen; nav bar goes to the left.
4645                int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode);
4646                mTmpNavigationFrame.set(overscanLeft, 0, right, displayHeight);
4647                mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right;
4648                if (transientNavBarShowing) {
4649                    mNavigationBarController.setBarShowingLw(true);
4650                } else if (navVisible) {
4651                    mNavigationBarController.setBarShowingLw(true);
4652                    mDockLeft = mTmpNavigationFrame.right;
4653                    // TODO: not so sure about those:
4654                    mRestrictedScreenLeft = mRestrictedOverscanScreenLeft = mDockLeft;
4655                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4656                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4657                } else {
4658                    // We currently want to hide the navigation UI - unless we expanded the status
4659                    // bar.
4660                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4661                }
4662                if (navVisible && !navTranslucent && !navAllowedHidden
4663                        && !mNavigationBar.isAnimatingLw()
4664                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4665                    // If the nav bar is currently requested to be visible,
4666                    // and not in the process of animating on or off, then
4667                    // we can tell the app that it is covered by it.
4668                    mSystemLeft = mTmpNavigationFrame.right;
4669                }
4670            }
4671            // Make sure the content and current rectangles are updated to
4672            // account for the restrictions from the navigation bar.
4673            mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4674            mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4675            mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4676            mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4677            mStatusBarLayer = mNavigationBar.getSurfaceLayer();
4678            // And compute the final frame.
4679            mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
4680                    mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
4681                    mTmpNavigationFrame, mTmpNavigationFrame);
4682            if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
4683            if (mNavigationBarController.checkHiddenLw()) {
4684                return true;
4685            }
4686        }
4687        return false;
4688    }
4689
4690    private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
4691        if (mNavigationBarCanMove && displayWidth > displayHeight) {
4692            if (displayRotation == Surface.ROTATION_270) {
4693                return NAV_BAR_LEFT;
4694            } else {
4695                return NAV_BAR_RIGHT;
4696            }
4697        }
4698        return NAV_BAR_BOTTOM;
4699    }
4700
4701    /** {@inheritDoc} */
4702    @Override
4703    public int getSystemDecorLayerLw() {
4704        if (mStatusBar != null && mStatusBar.isVisibleLw()) {
4705            return mStatusBar.getSurfaceLayer();
4706        }
4707
4708        if (mNavigationBar != null && mNavigationBar.isVisibleLw()) {
4709            return mNavigationBar.getSurfaceLayer();
4710        }
4711
4712        return 0;
4713    }
4714
4715    @Override
4716    public void getContentRectLw(Rect r) {
4717        r.set(mContentLeft, mContentTop, mContentRight, mContentBottom);
4718    }
4719
4720    void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
4721            boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
4722        if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
4723            // Here's a special case: if this attached window is a panel that is
4724            // above the dock window, and the window it is attached to is below
4725            // the dock window, then the frames we computed for the window it is
4726            // attached to can not be used because the dock is effectively part
4727            // of the underlying window and the attached window is floating on top
4728            // of the whole thing.  So, we ignore the attached window and explicitly
4729            // compute the frames that would be appropriate without the dock.
4730            df.left = of.left = cf.left = vf.left = mDockLeft;
4731            df.top = of.top = cf.top = vf.top = mDockTop;
4732            df.right = of.right = cf.right = vf.right = mDockRight;
4733            df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom;
4734        } else {
4735            // The effective display frame of the attached window depends on
4736            // whether it is taking care of insetting its content.  If not,
4737            // we need to use the parent's content frame so that the entire
4738            // window is positioned within that content.  Otherwise we can use
4739            // the overscan frame and let the attached window take care of
4740            // positioning its content appropriately.
4741            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4742                // Set the content frame of the attached window to the parent's decor frame
4743                // (same as content frame when IME isn't present) if specifically requested by
4744                // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
4745                // Otherwise, use the overscan frame.
4746                cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
4747                        ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
4748            } else {
4749                // If the window is resizing, then we want to base the content
4750                // frame on our attached content frame to resize...  however,
4751                // things can be tricky if the attached window is NOT in resize
4752                // mode, in which case its content frame will be larger.
4753                // Ungh.  So to deal with that, make sure the content frame
4754                // we end up using is not covering the IM dock.
4755                cf.set(attached.getContentFrameLw());
4756                if (attached.isVoiceInteraction()) {
4757                    if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft;
4758                    if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop;
4759                    if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight;
4760                    if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom;
4761                } else if (attached.getSurfaceLayer() < mDockLayer) {
4762                    if (cf.left < mContentLeft) cf.left = mContentLeft;
4763                    if (cf.top < mContentTop) cf.top = mContentTop;
4764                    if (cf.right > mContentRight) cf.right = mContentRight;
4765                    if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
4766                }
4767            }
4768            df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
4769            of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
4770            vf.set(attached.getVisibleFrameLw());
4771        }
4772        // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
4773        // window should be positioned relative to its parent or the entire
4774        // screen.
4775        pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
4776                ? attached.getFrameLw() : df);
4777    }
4778
4779    private void applyStableConstraints(int sysui, int fl, Rect r) {
4780        if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4781            // If app is requesting a stable layout, don't let the
4782            // content insets go below the stable values.
4783            if ((fl & FLAG_FULLSCREEN) != 0) {
4784                if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft;
4785                if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop;
4786                if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight;
4787                if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom;
4788            } else {
4789                if (r.left < mStableLeft) r.left = mStableLeft;
4790                if (r.top < mStableTop) r.top = mStableTop;
4791                if (r.right > mStableRight) r.right = mStableRight;
4792                if (r.bottom > mStableBottom) r.bottom = mStableBottom;
4793            }
4794        }
4795    }
4796
4797    private boolean canReceiveInput(WindowState win) {
4798        boolean notFocusable =
4799                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
4800        boolean altFocusableIm =
4801                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
4802        boolean notFocusableForIm = notFocusable ^ altFocusableIm;
4803        return !notFocusableForIm;
4804    }
4805
4806    /** {@inheritDoc} */
4807    @Override
4808    public void layoutWindowLw(WindowState win, WindowState attached) {
4809        // We've already done the navigation bar and status bar. If the status bar can receive
4810        // input, we need to layout it again to accomodate for the IME window.
4811        if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) {
4812            return;
4813        }
4814        final WindowManager.LayoutParams attrs = win.getAttrs();
4815        final boolean isDefaultDisplay = win.isDefaultDisplay();
4816        final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
4817                (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
4818        if (needsToOffsetInputMethodTarget) {
4819            if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
4820            offsetInputMethodWindowLw(mLastInputMethodWindow);
4821        }
4822
4823        final int fl = PolicyControl.getWindowFlags(win, attrs);
4824        final int pfl = attrs.privateFlags;
4825        final int sim = attrs.softInputMode;
4826        final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
4827
4828        final Rect pf = mTmpParentFrame;
4829        final Rect df = mTmpDisplayFrame;
4830        final Rect of = mTmpOverscanFrame;
4831        final Rect cf = mTmpContentFrame;
4832        final Rect vf = mTmpVisibleFrame;
4833        final Rect dcf = mTmpDecorFrame;
4834        final Rect sf = mTmpStableFrame;
4835        Rect osf = null;
4836        dcf.setEmpty();
4837
4838        final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
4839                && mNavigationBar != null && mNavigationBar.isVisibleLw());
4840
4841        final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
4842
4843        if (isDefaultDisplay) {
4844            sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom);
4845        } else {
4846            sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom);
4847        }
4848
4849        if (!isDefaultDisplay) {
4850            if (attached != null) {
4851                // If this window is attached to another, our display
4852                // frame is the same as the one we are attached to.
4853                setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4854            } else {
4855                // Give the window full screen.
4856                pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4857                pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4858                pf.right = df.right = of.right = cf.right
4859                        = mOverscanScreenLeft + mOverscanScreenWidth;
4860                pf.bottom = df.bottom = of.bottom = cf.bottom
4861                        = mOverscanScreenTop + mOverscanScreenHeight;
4862            }
4863        } else if (attrs.type == TYPE_INPUT_METHOD) {
4864            pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
4865            pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
4866            pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
4867            // IM dock windows layout below the nav bar...
4868            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4869            // ...with content insets above the nav bar
4870            cf.bottom = vf.bottom = mStableBottom;
4871            if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
4872                // The status bar forces the navigation bar while it's visible. Make sure the IME
4873                // avoids the navigation bar in that case.
4874                if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4875                    pf.right = df.right = of.right = cf.right = vf.right = mStableRight;
4876                } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4877                    pf.left = df.left = of.left = cf.left = vf.left = mStableLeft;
4878                }
4879            }
4880            // IM dock windows always go to the bottom of the screen.
4881            attrs.gravity = Gravity.BOTTOM;
4882            mDockLayer = win.getSurfaceLayer();
4883        } else if (attrs.type == TYPE_VOICE_INTERACTION) {
4884            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4885            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4886            pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4887            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4888            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4889                cf.left = mDockLeft;
4890                cf.top = mDockTop;
4891                cf.right = mDockRight;
4892                cf.bottom = mDockBottom;
4893            } else {
4894                cf.left = mContentLeft;
4895                cf.top = mContentTop;
4896                cf.right = mContentRight;
4897                cf.bottom = mContentBottom;
4898            }
4899            if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4900                vf.left = mCurLeft;
4901                vf.top = mCurTop;
4902                vf.right = mCurRight;
4903                vf.bottom = mCurBottom;
4904            } else {
4905                vf.set(cf);
4906            }
4907        } else if (attrs.type == TYPE_WALLPAPER) {
4908           layoutWallpaper(win, pf, df, of, cf);
4909        } else if (win == mStatusBar) {
4910            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4911            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4912            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4913            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop;
4914            cf.left = vf.left = mStableLeft;
4915            cf.top = vf.top = mStableTop;
4916            cf.right = vf.right = mStableRight;
4917            vf.bottom = mStableBottom;
4918
4919            if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
4920                cf.bottom = mContentBottom;
4921            } else {
4922                cf.bottom = mDockBottom;
4923                vf.bottom = mContentBottom;
4924            }
4925        } else {
4926
4927            // Default policy decor for the default display
4928            dcf.left = mSystemLeft;
4929            dcf.top = mSystemTop;
4930            dcf.right = mSystemRight;
4931            dcf.bottom = mSystemBottom;
4932            final boolean inheritTranslucentDecor = (attrs.privateFlags
4933                    & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0;
4934            final boolean isAppWindow =
4935                    attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW &&
4936                    attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
4937            final boolean topAtRest =
4938                    win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
4939            if (isAppWindow && !inheritTranslucentDecor && !topAtRest) {
4940                if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
4941                        && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0
4942                        && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
4943                        && (fl & WindowManager.LayoutParams.
4944                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
4945                        && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) {
4946                    // Ensure policy decor includes status bar
4947                    dcf.top = mStableTop;
4948                }
4949                if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0
4950                        && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
4951                        && (fl & WindowManager.LayoutParams.
4952                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
4953                    // Ensure policy decor includes navigation bar
4954                    dcf.bottom = mStableBottom;
4955                    dcf.right = mStableRight;
4956                }
4957            }
4958
4959            if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4960                    == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4961                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
4962                            + "): IN_SCREEN, INSET_DECOR");
4963                // This is the case for a normal activity window: we want it
4964                // to cover all of the screen space, and it can take care of
4965                // moving its contents to account for screen decorations that
4966                // intrude into that space.
4967                if (attached != null) {
4968                    // If this window is attached to another, our display
4969                    // frame is the same as the one we are attached to.
4970                    setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4971                } else {
4972                    if (attrs.type == TYPE_STATUS_BAR_PANEL
4973                            || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
4974                        // Status bar panels are the only windows who can go on top of
4975                        // the status bar.  They are protected by the STATUS_BAR_SERVICE
4976                        // permission, so they have the same privileges as the status
4977                        // bar itself.
4978                        //
4979                        // However, they should still dodge the navigation bar if it exists.
4980
4981                        pf.left = df.left = of.left = hasNavBar
4982                                ? mDockLeft : mUnrestrictedScreenLeft;
4983                        pf.top = df.top = of.top = mUnrestrictedScreenTop;
4984                        pf.right = df.right = of.right = hasNavBar
4985                                ? mRestrictedScreenLeft+mRestrictedScreenWidth
4986                                : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4987                        pf.bottom = df.bottom = of.bottom = hasNavBar
4988                                ? mRestrictedScreenTop+mRestrictedScreenHeight
4989                                : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4990
4991                        if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4992                                        "Laying out status bar window: (%d,%d - %d,%d)",
4993                                        pf.left, pf.top, pf.right, pf.bottom));
4994                    } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4995                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4996                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4997                        // Asking to layout into the overscan region, so give it that pure
4998                        // unrestricted area.
4999                        pf.left = df.left = of.left = mOverscanScreenLeft;
5000                        pf.top = df.top = of.top = mOverscanScreenTop;
5001                        pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth;
5002                        pf.bottom = df.bottom = of.bottom = mOverscanScreenTop
5003                                + mOverscanScreenHeight;
5004                    } else if (canHideNavigationBar()
5005                            && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
5006                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
5007                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
5008                        // Asking for layout as if the nav bar is hidden, lets the
5009                        // application extend into the unrestricted overscan screen area.  We
5010                        // only do this for application windows to ensure no window that
5011                        // can be above the nav bar can do this.
5012                        pf.left = df.left = mOverscanScreenLeft;
5013                        pf.top = df.top = mOverscanScreenTop;
5014                        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
5015                        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
5016                        // We need to tell the app about where the frame inside the overscan
5017                        // is, so it can inset its content by that amount -- it didn't ask
5018                        // to actually extend itself into the overscan region.
5019                        of.left = mUnrestrictedScreenLeft;
5020                        of.top = mUnrestrictedScreenTop;
5021                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5022                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5023                    } else {
5024                        pf.left = df.left = mRestrictedOverscanScreenLeft;
5025                        pf.top = df.top = mRestrictedOverscanScreenTop;
5026                        pf.right = df.right = mRestrictedOverscanScreenLeft
5027                                + mRestrictedOverscanScreenWidth;
5028                        pf.bottom = df.bottom = mRestrictedOverscanScreenTop
5029                                + mRestrictedOverscanScreenHeight;
5030                        // We need to tell the app about where the frame inside the overscan
5031                        // is, so it can inset its content by that amount -- it didn't ask
5032                        // to actually extend itself into the overscan region.
5033                        of.left = mUnrestrictedScreenLeft;
5034                        of.top = mUnrestrictedScreenTop;
5035                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5036                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5037                    }
5038
5039                    if ((fl & FLAG_FULLSCREEN) == 0) {
5040                        if (win.isVoiceInteraction()) {
5041                            cf.left = mVoiceContentLeft;
5042                            cf.top = mVoiceContentTop;
5043                            cf.right = mVoiceContentRight;
5044                            cf.bottom = mVoiceContentBottom;
5045                        } else {
5046                            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5047                                cf.left = mDockLeft;
5048                                cf.top = mDockTop;
5049                                cf.right = mDockRight;
5050                                cf.bottom = mDockBottom;
5051                            } else {
5052                                cf.left = mContentLeft;
5053                                cf.top = mContentTop;
5054                                cf.right = mContentRight;
5055                                cf.bottom = mContentBottom;
5056                            }
5057                        }
5058                    } else {
5059                        // Full screen windows are always given a layout that is as if the
5060                        // status bar and other transient decors are gone.  This is to avoid
5061                        // bad states when moving from a window that is not hding the
5062                        // status bar to one that is.
5063                        cf.left = mRestrictedScreenLeft;
5064                        cf.top = mRestrictedScreenTop;
5065                        cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
5066                        cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight;
5067                    }
5068                    applyStableConstraints(sysUiFl, fl, cf);
5069                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5070                        vf.left = mCurLeft;
5071                        vf.top = mCurTop;
5072                        vf.right = mCurRight;
5073                        vf.bottom = mCurBottom;
5074                    } else {
5075                        vf.set(cf);
5076                    }
5077                }
5078            } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
5079                    & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
5080                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
5081                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5082                        "): IN_SCREEN");
5083                // A window that has requested to fill the entire screen just
5084                // gets everything, period.
5085                if (attrs.type == TYPE_STATUS_BAR_PANEL
5086                        || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
5087                    pf.left = df.left = of.left = cf.left = hasNavBar
5088                            ? mDockLeft : mUnrestrictedScreenLeft;
5089                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
5090                    pf.right = df.right = of.right = cf.right = hasNavBar
5091                            ? mRestrictedScreenLeft + mRestrictedScreenWidth
5092                            : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5093                    pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar
5094                            ? mRestrictedScreenTop + mRestrictedScreenHeight
5095                            : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5096                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
5097                            "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
5098                            pf.left, pf.top, pf.right, pf.bottom));
5099                } else if (attrs.type == TYPE_VOLUME_OVERLAY) {
5100                    // Volume overlay covers everything, including the status and navbar
5101                    pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
5102                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
5103                    pf.right = df.right = of.right = cf.right =
5104                            mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5105                    pf.bottom = df.bottom = of.bottom = cf.bottom =
5106                            mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5107                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
5108                                    "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
5109                                    pf.left, pf.top, pf.right, pf.bottom));
5110                } else if (attrs.type == TYPE_NAVIGATION_BAR
5111                        || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
5112                    // The navigation bar has Real Ultimate Power.
5113                    pf.left = df.left = of.left = mUnrestrictedScreenLeft;
5114                    pf.top = df.top = of.top = mUnrestrictedScreenTop;
5115                    pf.right = df.right = of.right = mUnrestrictedScreenLeft
5116                            + mUnrestrictedScreenWidth;
5117                    pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop
5118                            + mUnrestrictedScreenHeight;
5119                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
5120                                    "Laying out navigation bar window: (%d,%d - %d,%d)",
5121                                    pf.left, pf.top, pf.right, pf.bottom));
5122                } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
5123                                || attrs.type == TYPE_BOOT_PROGRESS
5124                                || attrs.type == TYPE_SCREENSHOT)
5125                        && ((fl & FLAG_FULLSCREEN) != 0)) {
5126                    // Fullscreen secure system overlays get what they ask for. Screenshot region
5127                    // selection overlay should also expand to full screen.
5128                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
5129                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
5130                    pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
5131                            + mOverscanScreenWidth;
5132                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
5133                            + mOverscanScreenHeight;
5134                } else if (attrs.type == TYPE_BOOT_PROGRESS) {
5135                    // Boot progress screen always covers entire display.
5136                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
5137                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
5138                    pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
5139                            + mOverscanScreenWidth;
5140                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
5141                            + mOverscanScreenHeight;
5142                } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
5143                        && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
5144                        && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
5145                    // Asking to layout into the overscan region, so give it that pure
5146                    // unrestricted area.
5147                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
5148                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
5149                    pf.right = df.right = of.right = cf.right
5150                            = mOverscanScreenLeft + mOverscanScreenWidth;
5151                    pf.bottom = df.bottom = of.bottom = cf.bottom
5152                            = mOverscanScreenTop + mOverscanScreenHeight;
5153                } else if (canHideNavigationBar()
5154                        && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
5155                        && (attrs.type == TYPE_STATUS_BAR
5156                            || attrs.type == TYPE_TOAST
5157                            || attrs.type == TYPE_DOCK_DIVIDER
5158                            || attrs.type == TYPE_VOICE_INTERACTION_STARTING
5159                            || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
5160                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
5161                    // Asking for layout as if the nav bar is hidden, lets the
5162                    // application extend into the unrestricted screen area.  We
5163                    // only do this for application windows (or toasts) to ensure no window that
5164                    // can be above the nav bar can do this.
5165                    // XXX This assumes that an app asking for this will also
5166                    // ask for layout in only content.  We can't currently figure out
5167                    // what the screen would be if only laying out to hide the nav bar.
5168                    pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
5169                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
5170                    pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft
5171                            + mUnrestrictedScreenWidth;
5172                    pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
5173                            + mUnrestrictedScreenHeight;
5174                } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
5175                    pf.left = df.left = of.left = mRestrictedScreenLeft;
5176                    pf.top = df.top = of.top  = mRestrictedScreenTop;
5177                    pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
5178                    pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop
5179                            + mRestrictedScreenHeight;
5180                    if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5181                        cf.left = mDockLeft;
5182                        cf.top = mDockTop;
5183                        cf.right = mDockRight;
5184                        cf.bottom = mDockBottom;
5185                    } else {
5186                        cf.left = mContentLeft;
5187                        cf.top = mContentTop;
5188                        cf.right = mContentRight;
5189                        cf.bottom = mContentBottom;
5190                    }
5191                } else {
5192                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
5193                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
5194                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
5195                            + mRestrictedScreenWidth;
5196                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
5197                            + mRestrictedScreenHeight;
5198                }
5199
5200                applyStableConstraints(sysUiFl, fl, cf);
5201
5202                if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5203                    vf.left = mCurLeft;
5204                    vf.top = mCurTop;
5205                    vf.right = mCurRight;
5206                    vf.bottom = mCurBottom;
5207                } else {
5208                    vf.set(cf);
5209                }
5210            } else if (attached != null) {
5211                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5212                        "): attached to " + attached);
5213                // A child window should be placed inside of the same visible
5214                // frame that its parent had.
5215                setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf);
5216            } else {
5217                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5218                        "): normal window");
5219                // Otherwise, a normal window must be placed inside the content
5220                // of all screen decorations.
5221                if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) {
5222                    // Status bar panels and the volume dialog are the only windows who can go on
5223                    // top of the status bar.  They are protected by the STATUS_BAR_SERVICE
5224                    // permission, so they have the same privileges as the status
5225                    // bar itself.
5226                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
5227                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
5228                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
5229                            + mRestrictedScreenWidth;
5230                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
5231                            + mRestrictedScreenHeight;
5232                } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) {
5233                    // These dialogs are stable to interim decor changes.
5234                    pf.left = df.left = of.left = cf.left = mStableLeft;
5235                    pf.top = df.top = of.top = cf.top = mStableTop;
5236                    pf.right = df.right = of.right = cf.right = mStableRight;
5237                    pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom;
5238                } else {
5239                    pf.left = mContentLeft;
5240                    pf.top = mContentTop;
5241                    pf.right = mContentRight;
5242                    pf.bottom = mContentBottom;
5243                    if (win.isVoiceInteraction()) {
5244                        df.left = of.left = cf.left = mVoiceContentLeft;
5245                        df.top = of.top = cf.top = mVoiceContentTop;
5246                        df.right = of.right = cf.right = mVoiceContentRight;
5247                        df.bottom = of.bottom = cf.bottom = mVoiceContentBottom;
5248                    } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5249                        df.left = of.left = cf.left = mDockLeft;
5250                        df.top = of.top = cf.top = mDockTop;
5251                        df.right = of.right = cf.right = mDockRight;
5252                        df.bottom = of.bottom = cf.bottom = mDockBottom;
5253                    } else {
5254                        df.left = of.left = cf.left = mContentLeft;
5255                        df.top = of.top = cf.top = mContentTop;
5256                        df.right = of.right = cf.right = mContentRight;
5257                        df.bottom = of.bottom = cf.bottom = mContentBottom;
5258                    }
5259                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5260                        vf.left = mCurLeft;
5261                        vf.top = mCurTop;
5262                        vf.right = mCurRight;
5263                        vf.bottom = mCurBottom;
5264                    } else {
5265                        vf.set(cf);
5266                    }
5267                }
5268            }
5269        }
5270
5271        // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
5272        // Also, we don't allow windows in multi-window mode to extend out of the screen.
5273        if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR
5274                && !win.isInMultiWindowMode()) {
5275            df.left = df.top = -10000;
5276            df.right = df.bottom = 10000;
5277            if (attrs.type != TYPE_WALLPAPER) {
5278                of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
5279                of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
5280            }
5281        }
5282
5283        // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we
5284        // need to provide information to the clients that want to pretend that you can draw there.
5285        // We only want to apply outsets to certain types of windows. For example, we never want to
5286        // apply the outsets to floating dialogs, because they wouldn't make sense there.
5287        final boolean useOutsets = shouldUseOutsets(attrs, fl);
5288        if (isDefaultDisplay && useOutsets) {
5289            osf = mTmpOutsetFrame;
5290            osf.set(cf.left, cf.top, cf.right, cf.bottom);
5291            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
5292            if (outset > 0) {
5293                int rotation = mDisplayRotation;
5294                if (rotation == Surface.ROTATION_0) {
5295                    osf.bottom += outset;
5296                } else if (rotation == Surface.ROTATION_90) {
5297                    osf.right += outset;
5298                } else if (rotation == Surface.ROTATION_180) {
5299                    osf.top -= outset;
5300                } else if (rotation == Surface.ROTATION_270) {
5301                    osf.left -= outset;
5302                }
5303                if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset
5304                        + " with rotation " + rotation + ", result: " + osf);
5305            }
5306        }
5307
5308        if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
5309                + ": sim=#" + Integer.toHexString(sim)
5310                + " attach=" + attached + " type=" + attrs.type
5311                + String.format(" flags=0x%08x", fl)
5312                + " pf=" + pf.toShortString() + " df=" + df.toShortString()
5313                + " of=" + of.toShortString()
5314                + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
5315                + " dcf=" + dcf.toShortString()
5316                + " sf=" + sf.toShortString()
5317                + " osf=" + (osf == null ? "null" : osf.toShortString()));
5318
5319        win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf);
5320
5321        // Dock windows carve out the bottom of the screen, so normal windows
5322        // can't appear underneath them.
5323        if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleLw()
5324                && !win.getGivenInsetsPendingLw()) {
5325            setLastInputMethodWindowLw(null, null);
5326            offsetInputMethodWindowLw(win);
5327        }
5328        if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleLw()
5329                && !win.getGivenInsetsPendingLw()) {
5330            offsetVoiceInputWindowLw(win);
5331        }
5332    }
5333
5334    private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) {
5335
5336        // The wallpaper also has Real Ultimate Power, but we want to tell
5337        // it about the overscan area.
5338        pf.left = df.left = mOverscanScreenLeft;
5339        pf.top = df.top = mOverscanScreenTop;
5340        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
5341        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
5342        of.left = cf.left = mUnrestrictedScreenLeft;
5343        of.top = cf.top = mUnrestrictedScreenTop;
5344        of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5345        of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5346    }
5347
5348    private void offsetInputMethodWindowLw(WindowState win) {
5349        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5350        top += win.getGivenContentInsetsLw().top;
5351        if (mContentBottom > top) {
5352            mContentBottom = top;
5353        }
5354        if (mVoiceContentBottom > top) {
5355            mVoiceContentBottom = top;
5356        }
5357        top = win.getVisibleFrameLw().top;
5358        top += win.getGivenVisibleInsetsLw().top;
5359        if (mCurBottom > top) {
5360            mCurBottom = top;
5361        }
5362        if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
5363                + mDockBottom + " mContentBottom="
5364                + mContentBottom + " mCurBottom=" + mCurBottom);
5365    }
5366
5367    private void offsetVoiceInputWindowLw(WindowState win) {
5368        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5369        top += win.getGivenContentInsetsLw().top;
5370        if (mVoiceContentBottom > top) {
5371            mVoiceContentBottom = top;
5372        }
5373    }
5374
5375    /** {@inheritDoc} */
5376    @Override
5377    public void finishLayoutLw() {
5378        return;
5379    }
5380
5381    /** {@inheritDoc} */
5382    @Override
5383    public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
5384        mTopFullscreenOpaqueWindowState = null;
5385        mTopFullscreenOpaqueOrDimmingWindowState = null;
5386        mTopDockedOpaqueWindowState = null;
5387        mTopDockedOpaqueOrDimmingWindowState = null;
5388        mForceStatusBar = false;
5389        mForceStatusBarFromKeyguard = false;
5390        mForceStatusBarTransparent = false;
5391        mForcingShowNavBar = false;
5392        mForcingShowNavBarLayer = -1;
5393
5394        mAllowLockscreenWhenOn = false;
5395        mShowingDream = false;
5396        mWindowSleepTokenNeeded = false;
5397    }
5398
5399    /** {@inheritDoc} */
5400    @Override
5401    public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
5402            WindowState attached, WindowState imeTarget) {
5403        final boolean affectsSystemUi = win.canAffectSystemUiFlags();
5404        if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": affectsSystemUi=" + affectsSystemUi);
5405        applyKeyguardPolicyLw(win, imeTarget);
5406        final int fl = PolicyControl.getWindowFlags(win, attrs);
5407        if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi
5408                && attrs.type == TYPE_INPUT_METHOD) {
5409            mForcingShowNavBar = true;
5410            mForcingShowNavBarLayer = win.getSurfaceLayer();
5411        }
5412        if (attrs.type == TYPE_STATUS_BAR) {
5413            if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
5414                mForceStatusBarFromKeyguard = true;
5415            }
5416            if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
5417                mForceStatusBarTransparent = true;
5418            }
5419        }
5420
5421        boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
5422                && attrs.type < FIRST_SYSTEM_WINDOW;
5423        final int stackId = win.getStackId();
5424        if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi) {
5425            if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
5426                mForceStatusBar = true;
5427            }
5428            if (attrs.type == TYPE_DREAM) {
5429                // If the lockscreen was showing when the dream started then wait
5430                // for the dream to draw before hiding the lockscreen.
5431                if (!mDreamingLockscreen
5432                        || (win.isVisibleLw() && win.hasDrawnLw())) {
5433                    mShowingDream = true;
5434                    appWindow = true;
5435                }
5436            }
5437
5438            // For app windows that are not attached, we decide if all windows in the app they
5439            // represent should be hidden or if we should hide the lockscreen. For attached app
5440            // windows we defer the decision to the window it is attached to.
5441            if (appWindow && attached == null) {
5442                if (attrs.isFullscreen() && StackId.normallyFullscreenWindows(stackId)) {
5443                    if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
5444                    mTopFullscreenOpaqueWindowState = win;
5445                    if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5446                        mTopFullscreenOpaqueOrDimmingWindowState = win;
5447                    }
5448                    if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
5449                        mAllowLockscreenWhenOn = true;
5450                    }
5451                }
5452            }
5453        }
5454
5455        // Voice interaction overrides both top fullscreen and top docked.
5456        if (affectsSystemUi && win.getAttrs().type == TYPE_VOICE_INTERACTION) {
5457            if (mTopFullscreenOpaqueWindowState == null) {
5458                mTopFullscreenOpaqueWindowState = win;
5459                if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5460                    mTopFullscreenOpaqueOrDimmingWindowState = win;
5461                }
5462            }
5463            if (mTopDockedOpaqueWindowState == null) {
5464                mTopDockedOpaqueWindowState = win;
5465                if (mTopDockedOpaqueOrDimmingWindowState == null) {
5466                    mTopDockedOpaqueOrDimmingWindowState = win;
5467                }
5468            }
5469        }
5470
5471        // Keep track of the window if it's dimming but not necessarily fullscreen.
5472        if (mTopFullscreenOpaqueOrDimmingWindowState == null && affectsSystemUi
5473                && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
5474            mTopFullscreenOpaqueOrDimmingWindowState = win;
5475        }
5476
5477        // We need to keep track of the top "fullscreen" opaque window for the docked stack
5478        // separately, because both the "real fullscreen" opaque window and the one for the docked
5479        // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
5480        if (mTopDockedOpaqueWindowState == null && affectsSystemUi && appWindow && attached == null
5481                && attrs.isFullscreen() && stackId == DOCKED_STACK_ID) {
5482            mTopDockedOpaqueWindowState = win;
5483            if (mTopDockedOpaqueOrDimmingWindowState == null) {
5484                mTopDockedOpaqueOrDimmingWindowState = win;
5485            }
5486        }
5487
5488        // Also keep track of any windows that are dimming but not necessarily fullscreen in the
5489        // docked stack.
5490        if (mTopDockedOpaqueOrDimmingWindowState == null && affectsSystemUi && win.isDimming()
5491                && stackId == DOCKED_STACK_ID) {
5492            mTopDockedOpaqueOrDimmingWindowState = win;
5493        }
5494
5495        // Take note if a window wants to acquire a sleep token.
5496        if (win.isVisibleLw() && (attrs.privateFlags & PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN) != 0
5497                && win.canAcquireSleepToken()) {
5498            mWindowSleepTokenNeeded = true;
5499        }
5500    }
5501
5502    private void applyKeyguardPolicyLw(WindowState win, WindowState imeTarget) {
5503        if (canBeHiddenByKeyguardLw(win)) {
5504            if (shouldBeHiddenByKeyguard(win, imeTarget)) {
5505                win.hideLw(false /* doAnimation */);
5506            } else {
5507                win.showLw(false /* doAnimation */);
5508            }
5509        }
5510    }
5511
5512    /** {@inheritDoc} */
5513    @Override
5514    public int finishPostLayoutPolicyLw() {
5515        int changes = 0;
5516        boolean topIsFullscreen = false;
5517
5518        final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
5519                ? mTopFullscreenOpaqueWindowState.getAttrs()
5520                : null;
5521
5522        // If we are not currently showing a dream then remember the current
5523        // lockscreen state.  We will use this to determine whether the dream
5524        // started while the lockscreen was showing and remember this state
5525        // while the dream is showing.
5526        if (!mShowingDream) {
5527            mDreamingLockscreen = isKeyguardShowingAndNotOccluded();
5528            if (mDreamingSleepTokenNeeded) {
5529                mDreamingSleepTokenNeeded = false;
5530                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
5531            }
5532        } else {
5533            if (!mDreamingSleepTokenNeeded) {
5534                mDreamingSleepTokenNeeded = true;
5535                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget();
5536            }
5537        }
5538
5539        if (mStatusBar != null) {
5540            if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
5541                    + " forcefkg=" + mForceStatusBarFromKeyguard
5542                    + " top=" + mTopFullscreenOpaqueWindowState);
5543            boolean shouldBeTransparent = mForceStatusBarTransparent
5544                    && !mForceStatusBar
5545                    && !mForceStatusBarFromKeyguard;
5546            if (!shouldBeTransparent) {
5547                mStatusBarController.setShowTransparent(false /* transparent */);
5548            } else if (!mStatusBar.isVisibleLw()) {
5549                mStatusBarController.setShowTransparent(true /* transparent */);
5550            }
5551
5552            WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs();
5553            boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT
5554                    && statusBarAttrs.width == MATCH_PARENT;
5555            boolean topAppHidesStatusBar = topAppHidesStatusBar();
5556            if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
5557                    || statusBarExpanded) {
5558                if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
5559                if (mStatusBarController.setBarShowingLw(true)) {
5560                    changes |= FINISH_LAYOUT_REDO_LAYOUT;
5561                }
5562                // Maintain fullscreen layout until incoming animation is complete.
5563                topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
5564                // Transient status bar on the lockscreen is not allowed
5565                if ((mForceStatusBarFromKeyguard || statusBarExpanded)
5566                        && mStatusBarController.isTransientShowing()) {
5567                    mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
5568                            mLastSystemUiFlags, mLastSystemUiFlags);
5569                }
5570                if (statusBarExpanded && mNavigationBar != null) {
5571                    if (mNavigationBarController.setBarShowingLw(true)) {
5572                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5573                    }
5574                }
5575            } else if (mTopFullscreenOpaqueWindowState != null) {
5576                topIsFullscreen = topAppHidesStatusBar;
5577                // The subtle difference between the window for mTopFullscreenOpaqueWindowState
5578                // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
5579                // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
5580                // case though.
5581                if (mStatusBarController.isTransientShowing()) {
5582                    if (mStatusBarController.setBarShowingLw(true)) {
5583                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5584                    }
5585                } else if (topIsFullscreen
5586                        && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)
5587                        && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) {
5588                    if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
5589                    if (mStatusBarController.setBarShowingLw(false)) {
5590                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5591                    } else {
5592                        if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
5593                    }
5594                } else {
5595                    if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
5596                    if (mStatusBarController.setBarShowingLw(true)) {
5597                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5598                    }
5599                    topAppHidesStatusBar = false;
5600                }
5601            }
5602            mStatusBarController.setTopAppHidesStatusBar(topAppHidesStatusBar);
5603        }
5604
5605        if (mTopIsFullscreen != topIsFullscreen) {
5606            if (!topIsFullscreen) {
5607                // Force another layout when status bar becomes fully shown.
5608                changes |= FINISH_LAYOUT_REDO_LAYOUT;
5609            }
5610            mTopIsFullscreen = topIsFullscreen;
5611        }
5612
5613        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5614            // If the navigation bar has been hidden or shown, we need to do another
5615            // layout pass to update that window.
5616            changes |= FINISH_LAYOUT_REDO_LAYOUT;
5617        }
5618
5619        if (mShowingDream != mLastShowingDream) {
5620            mLastShowingDream = mShowingDream;
5621            mWindowManagerFuncs.notifyShowingDreamChanged();
5622        }
5623
5624        updateWindowSleepToken();
5625
5626        // update since mAllowLockscreenWhenOn might have changed
5627        updateLockScreenTimeout();
5628        return changes;
5629    }
5630
5631    private void updateWindowSleepToken() {
5632        if (mWindowSleepTokenNeeded && !mLastWindowSleepTokenNeeded) {
5633            mHandler.removeCallbacks(mReleaseSleepTokenRunnable);
5634            mHandler.post(mAcquireSleepTokenRunnable);
5635        } else if (!mWindowSleepTokenNeeded && mLastWindowSleepTokenNeeded) {
5636            mHandler.removeCallbacks(mAcquireSleepTokenRunnable);
5637            mHandler.post(mReleaseSleepTokenRunnable);
5638        }
5639        mLastWindowSleepTokenNeeded = mWindowSleepTokenNeeded;
5640    }
5641
5642    /**
5643     * @return Whether the top app should hide the statusbar based on the top fullscreen opaque
5644     *         window.
5645     */
5646    private boolean topAppHidesStatusBar() {
5647        if (mTopFullscreenOpaqueWindowState == null) {
5648            return false;
5649        }
5650        final int fl = PolicyControl.getWindowFlags(null,
5651                mTopFullscreenOpaqueWindowState.getAttrs());
5652        if (localLOGV) {
5653            Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
5654                    + " shown position: "
5655                    + mTopFullscreenOpaqueWindowState.getShownPositionLw());
5656            Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
5657                    + " lp.flags=0x" + Integer.toHexString(fl));
5658        }
5659        return (fl & LayoutParams.FLAG_FULLSCREEN) != 0
5660                || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
5661    }
5662
5663    /**
5664     * Updates the occluded state of the Keyguard.
5665     *
5666     * @return Whether the flags have changed and we have to redo the layout.
5667     */
5668    private boolean setKeyguardOccludedLw(boolean isOccluded, boolean force) {
5669        if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded);
5670        final boolean wasOccluded = mKeyguardOccluded;
5671        final boolean showing = mKeyguardDelegate.isShowing();
5672        final boolean changed = wasOccluded != isOccluded || force;
5673        if (!isOccluded && changed && showing) {
5674            mKeyguardOccluded = false;
5675            mKeyguardDelegate.setOccluded(false, true /* animate */);
5676            if (mStatusBar != null) {
5677                mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
5678                if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
5679                    mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5680                }
5681            }
5682            return true;
5683        } else if (isOccluded && changed && showing) {
5684            mKeyguardOccluded = true;
5685            mKeyguardDelegate.setOccluded(true, false /* animate */);
5686            if (mStatusBar != null) {
5687                mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
5688                mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
5689            }
5690            return true;
5691        } else if (changed) {
5692            mKeyguardOccluded = isOccluded;
5693            mKeyguardDelegate.setOccluded(isOccluded, false /* animate */);
5694            return false;
5695        } else {
5696            return false;
5697        }
5698    }
5699
5700    private boolean isStatusBarKeyguard() {
5701        return mStatusBar != null
5702                && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
5703    }
5704
5705    @Override
5706    public boolean allowAppAnimationsLw() {
5707        if (mShowingDream) {
5708            // If keyguard or dreams is currently visible, no reason to animate behind it.
5709            return false;
5710        }
5711        return true;
5712    }
5713
5714    @Override
5715    public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
5716        mFocusedWindow = newFocus;
5717        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5718            // If the navigation bar has been hidden or shown, we need to do another
5719            // layout pass to update that window.
5720            return FINISH_LAYOUT_REDO_LAYOUT;
5721        }
5722        return 0;
5723    }
5724
5725    /** {@inheritDoc} */
5726    @Override
5727    public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
5728        // lid changed state
5729        final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
5730        if (newLidState == mLidState) {
5731            return;
5732        }
5733
5734        mLidState = newLidState;
5735        applyLidSwitchState();
5736        updateRotation(true);
5737
5738        if (lidOpen) {
5739            wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
5740                    "android.policy:LID");
5741        } else if (!mLidControlsSleep) {
5742            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
5743        }
5744    }
5745
5746    @Override
5747    public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
5748        int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
5749        if (mCameraLensCoverState == lensCoverState) {
5750            return;
5751        }
5752        if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
5753                lensCoverState == CAMERA_LENS_UNCOVERED) {
5754            Intent intent;
5755            final boolean keyguardActive = mKeyguardDelegate == null ? false :
5756                    mKeyguardDelegate.isShowing();
5757            if (keyguardActive) {
5758                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
5759            } else {
5760                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
5761            }
5762            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
5763                    "android.policy:CAMERA_COVER");
5764            startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
5765        }
5766        mCameraLensCoverState = lensCoverState;
5767    }
5768
5769    void setHdmiPlugged(boolean plugged) {
5770        if (mHdmiPlugged != plugged) {
5771            mHdmiPlugged = plugged;
5772            updateRotation(true, true);
5773            Intent intent = new Intent(ACTION_HDMI_PLUGGED);
5774            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
5775            intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
5776            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
5777        }
5778    }
5779
5780    void initializeHdmiState() {
5781        boolean plugged = false;
5782        // watch for HDMI plug messages if the hdmi switch exists
5783        if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
5784            mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
5785
5786            final String filename = "/sys/class/switch/hdmi/state";
5787            FileReader reader = null;
5788            try {
5789                reader = new FileReader(filename);
5790                char[] buf = new char[15];
5791                int n = reader.read(buf);
5792                if (n > 1) {
5793                    plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
5794                }
5795            } catch (IOException ex) {
5796                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5797            } catch (NumberFormatException ex) {
5798                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5799            } finally {
5800                if (reader != null) {
5801                    try {
5802                        reader.close();
5803                    } catch (IOException ex) {
5804                    }
5805                }
5806            }
5807        }
5808        // This dance forces the code in setHdmiPlugged to run.
5809        // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
5810        mHdmiPlugged = !plugged;
5811        setHdmiPlugged(!mHdmiPlugged);
5812    }
5813
5814    final Object mScreenshotLock = new Object();
5815    ServiceConnection mScreenshotConnection = null;
5816
5817    final Runnable mScreenshotTimeout = new Runnable() {
5818        @Override public void run() {
5819            synchronized (mScreenshotLock) {
5820                if (mScreenshotConnection != null) {
5821                    mContext.unbindService(mScreenshotConnection);
5822                    mScreenshotConnection = null;
5823                    notifyScreenshotError();
5824                }
5825            }
5826        }
5827    };
5828
5829    // Assume this is called from the Handler thread.
5830    private void takeScreenshot(final int screenshotType) {
5831        synchronized (mScreenshotLock) {
5832            if (mScreenshotConnection != null) {
5833                return;
5834            }
5835            final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
5836                    SYSUI_SCREENSHOT_SERVICE);
5837            final Intent serviceIntent = new Intent();
5838            serviceIntent.setComponent(serviceComponent);
5839            ServiceConnection conn = new ServiceConnection() {
5840                @Override
5841                public void onServiceConnected(ComponentName name, IBinder service) {
5842                    synchronized (mScreenshotLock) {
5843                        if (mScreenshotConnection != this) {
5844                            return;
5845                        }
5846                        Messenger messenger = new Messenger(service);
5847                        Message msg = Message.obtain(null, screenshotType);
5848                        final ServiceConnection myConn = this;
5849                        Handler h = new Handler(mHandler.getLooper()) {
5850                            @Override
5851                            public void handleMessage(Message msg) {
5852                                synchronized (mScreenshotLock) {
5853                                    if (mScreenshotConnection == myConn) {
5854                                        mContext.unbindService(mScreenshotConnection);
5855                                        mScreenshotConnection = null;
5856                                        mHandler.removeCallbacks(mScreenshotTimeout);
5857                                    }
5858                                }
5859                            }
5860                        };
5861                        msg.replyTo = new Messenger(h);
5862                        msg.arg1 = msg.arg2 = 0;
5863                        if (mStatusBar != null && mStatusBar.isVisibleLw())
5864                            msg.arg1 = 1;
5865                        if (mNavigationBar != null && mNavigationBar.isVisibleLw())
5866                            msg.arg2 = 1;
5867                        try {
5868                            messenger.send(msg);
5869                        } catch (RemoteException e) {
5870                        }
5871                    }
5872                }
5873
5874                @Override
5875                public void onServiceDisconnected(ComponentName name) {
5876                    synchronized (mScreenshotLock) {
5877                        if (mScreenshotConnection != null) {
5878                            mContext.unbindService(mScreenshotConnection);
5879                            mScreenshotConnection = null;
5880                            mHandler.removeCallbacks(mScreenshotTimeout);
5881                            notifyScreenshotError();
5882                        }
5883                    }
5884                }
5885            };
5886            if (mContext.bindServiceAsUser(serviceIntent, conn,
5887                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
5888                    UserHandle.CURRENT)) {
5889                mScreenshotConnection = conn;
5890                mHandler.postDelayed(mScreenshotTimeout, 10000);
5891            }
5892        }
5893    }
5894
5895    /**
5896     * Notifies the screenshot service to show an error.
5897     */
5898    private void notifyScreenshotError() {
5899        // If the service process is killed, then ask it to clean up after itself
5900        final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
5901                SYSUI_SCREENSHOT_ERROR_RECEIVER);
5902        Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
5903        errorIntent.setComponent(errorComponent);
5904        errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
5905                Intent.FLAG_RECEIVER_FOREGROUND);
5906        mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT);
5907    }
5908
5909    /** {@inheritDoc} */
5910    @Override
5911    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
5912        if (!mSystemBooted) {
5913            // If we have not yet booted, don't let key events do anything.
5914            return 0;
5915        }
5916
5917        final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
5918        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
5919        final boolean canceled = event.isCanceled();
5920        final int keyCode = event.getKeyCode();
5921
5922        final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
5923
5924        // If screen is off then we treat the case where the keyguard is open but hidden
5925        // the same as if it were open and in front.
5926        // This will prevent any keys other than the power button from waking the screen
5927        // when the keyguard is hidden by another activity.
5928        final boolean keyguardActive = (mKeyguardDelegate == null ? false :
5929                                            (interactive ?
5930                                                isKeyguardShowingAndNotOccluded() :
5931                                                mKeyguardDelegate.isShowing()));
5932
5933        if (DEBUG_INPUT) {
5934            Log.d(TAG, "interceptKeyTq keycode=" + keyCode
5935                    + " interactive=" + interactive + " keyguardActive=" + keyguardActive
5936                    + " policyFlags=" + Integer.toHexString(policyFlags));
5937        }
5938
5939        // Basic policy based on interactive state.
5940        int result;
5941        boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
5942                || event.isWakeKey();
5943        if (interactive || (isInjected && !isWakeKey)) {
5944            // When the device is interactive or the key is injected pass the
5945            // key to the application.
5946            result = ACTION_PASS_TO_USER;
5947            isWakeKey = false;
5948
5949            if (interactive) {
5950                // If the screen is awake, but the button pressed was the one that woke the device
5951                // then don't pass it to the application
5952                if (keyCode == mPendingWakeKey && !down) {
5953                    result = 0;
5954                }
5955                // Reset the pending key
5956                mPendingWakeKey = PENDING_KEY_NULL;
5957            }
5958        } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
5959            // If we're currently dozing with the screen on and the keyguard showing, pass the key
5960            // to the application but preserve its wake key status to make sure we still move
5961            // from dozing to fully interactive if we would normally go from off to fully
5962            // interactive.
5963            result = ACTION_PASS_TO_USER;
5964            // Since we're dispatching the input, reset the pending key
5965            mPendingWakeKey = PENDING_KEY_NULL;
5966        } else {
5967            // When the screen is off and the key is not injected, determine whether
5968            // to wake the device but don't pass the key to the application.
5969            result = 0;
5970            if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
5971                isWakeKey = false;
5972            }
5973            // Cache the wake key on down event so we can also avoid sending the up event to the app
5974            if (isWakeKey && down) {
5975                mPendingWakeKey = keyCode;
5976            }
5977        }
5978
5979        // If the key would be handled globally, just return the result, don't worry about special
5980        // key processing.
5981        if (isValidGlobalKey(keyCode)
5982                && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
5983            if (isWakeKey) {
5984                wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5985            }
5986            return result;
5987        }
5988
5989        boolean useHapticFeedback = down
5990                && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
5991                && event.getRepeatCount() == 0;
5992
5993        // Handle special keys.
5994        switch (keyCode) {
5995            case KeyEvent.KEYCODE_BACK: {
5996                if (down) {
5997                    interceptBackKeyDown();
5998                } else {
5999                    boolean handled = interceptBackKeyUp(event);
6000
6001                    // Don't pass back press to app if we've already handled it via long press
6002                    if (handled) {
6003                        result &= ~ACTION_PASS_TO_USER;
6004                    }
6005                }
6006                break;
6007            }
6008
6009            case KeyEvent.KEYCODE_VOLUME_DOWN:
6010            case KeyEvent.KEYCODE_VOLUME_UP:
6011            case KeyEvent.KEYCODE_VOLUME_MUTE: {
6012                if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
6013                    if (down) {
6014                        if (interactive && !mScreenshotChordVolumeDownKeyTriggered
6015                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
6016                            mScreenshotChordVolumeDownKeyTriggered = true;
6017                            mScreenshotChordVolumeDownKeyTime = event.getDownTime();
6018                            mScreenshotChordVolumeDownKeyConsumed = false;
6019                            cancelPendingPowerKeyAction();
6020                            interceptScreenshotChord();
6021                            interceptAccessibilityShortcutChord();
6022                        }
6023                    } else {
6024                        mScreenshotChordVolumeDownKeyTriggered = false;
6025                        cancelPendingScreenshotChordAction();
6026                        cancelPendingAccessibilityShortcutAction();
6027                    }
6028                } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
6029                    if (down) {
6030                        if (interactive && !mA11yShortcutChordVolumeUpKeyTriggered
6031                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
6032                            mA11yShortcutChordVolumeUpKeyTriggered = true;
6033                            mA11yShortcutChordVolumeUpKeyTime = event.getDownTime();
6034                            mA11yShortcutChordVolumeUpKeyConsumed = false;
6035                            cancelPendingPowerKeyAction();
6036                            cancelPendingScreenshotChordAction();
6037                            interceptAccessibilityShortcutChord();
6038                        }
6039                    } else {
6040                        mA11yShortcutChordVolumeUpKeyTriggered = false;
6041                        cancelPendingScreenshotChordAction();
6042                        cancelPendingAccessibilityShortcutAction();
6043                    }
6044                }
6045                if (down) {
6046                    sendSystemKeyToStatusBarAsync(event.getKeyCode());
6047
6048                    TelecomManager telecomManager = getTelecommService();
6049                    if (telecomManager != null) {
6050                        if (telecomManager.isRinging()) {
6051                            // If an incoming call is ringing, either VOLUME key means
6052                            // "silence ringer".  We handle these keys here, rather than
6053                            // in the InCallScreen, to make sure we'll respond to them
6054                            // even if the InCallScreen hasn't come to the foreground yet.
6055                            // Look for the DOWN event here, to agree with the "fallback"
6056                            // behavior in the InCallScreen.
6057                            Log.i(TAG, "interceptKeyBeforeQueueing:"
6058                                  + " VOLUME key-down while ringing: Silence ringer!");
6059
6060                            // Silence the ringer.  (It's safe to call this
6061                            // even if the ringer has already been silenced.)
6062                            telecomManager.silenceRinger();
6063
6064                            // And *don't* pass this key thru to the current activity
6065                            // (which is probably the InCallScreen.)
6066                            result &= ~ACTION_PASS_TO_USER;
6067                            break;
6068                        }
6069                    }
6070                    int audioMode = AudioManager.MODE_NORMAL;
6071                    try {
6072                        audioMode = getAudioService().getMode();
6073                    } catch (Exception e) {
6074                        Log.e(TAG, "Error getting AudioService in interceptKeyBeforeQueueing.", e);
6075                    }
6076                    boolean isInCall = (telecomManager != null && telecomManager.isInCall()) ||
6077                            audioMode == AudioManager.MODE_IN_COMMUNICATION;
6078                    if (isInCall && (result & ACTION_PASS_TO_USER) == 0) {
6079                        // If we are in call but we decided not to pass the key to
6080                        // the application, just pass it to the session service.
6081                        MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
6082                                event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
6083                        break;
6084                    }
6085                }
6086                if (mUseTvRouting || mHandleVolumeKeysInWM) {
6087                    // Defer special key handlings to
6088                    // {@link interceptKeyBeforeDispatching()}.
6089                    result |= ACTION_PASS_TO_USER;
6090                } else if ((result & ACTION_PASS_TO_USER) == 0) {
6091                    // If we aren't passing to the user and no one else
6092                    // handled it send it to the session manager to
6093                    // figure out.
6094                    MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
6095                            event, AudioManager.USE_DEFAULT_STREAM_TYPE, true);
6096                }
6097                break;
6098            }
6099
6100            case KeyEvent.KEYCODE_ENDCALL: {
6101                result &= ~ACTION_PASS_TO_USER;
6102                if (down) {
6103                    TelecomManager telecomManager = getTelecommService();
6104                    boolean hungUp = false;
6105                    if (telecomManager != null) {
6106                        hungUp = telecomManager.endCall();
6107                    }
6108                    if (interactive && !hungUp) {
6109                        mEndCallKeyHandled = false;
6110                        mHandler.postDelayed(mEndCallLongPress,
6111                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
6112                    } else {
6113                        mEndCallKeyHandled = true;
6114                    }
6115                } else {
6116                    if (!mEndCallKeyHandled) {
6117                        mHandler.removeCallbacks(mEndCallLongPress);
6118                        if (!canceled) {
6119                            if ((mEndcallBehavior
6120                                    & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
6121                                if (goHome()) {
6122                                    break;
6123                                }
6124                            }
6125                            if ((mEndcallBehavior
6126                                    & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
6127                                goToSleep(event.getEventTime(),
6128                                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
6129                                isWakeKey = false;
6130                            }
6131                        }
6132                    }
6133                }
6134                break;
6135            }
6136
6137            case KeyEvent.KEYCODE_POWER: {
6138                // Any activity on the power button stops the accessibility shortcut
6139                cancelPendingAccessibilityShortcutAction();
6140                result &= ~ACTION_PASS_TO_USER;
6141                isWakeKey = false; // wake-up will be handled separately
6142                if (down) {
6143                    interceptPowerKeyDown(event, interactive);
6144                } else {
6145                    interceptPowerKeyUp(event, interactive, canceled);
6146                }
6147                break;
6148            }
6149
6150            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
6151                // fall through
6152            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
6153                // fall through
6154            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
6155                // fall through
6156            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
6157                result &= ~ACTION_PASS_TO_USER;
6158                interceptSystemNavigationKey(event);
6159                break;
6160            }
6161
6162            case KeyEvent.KEYCODE_SLEEP: {
6163                result &= ~ACTION_PASS_TO_USER;
6164                isWakeKey = false;
6165                if (!mPowerManager.isInteractive()) {
6166                    useHapticFeedback = false; // suppress feedback if already non-interactive
6167                }
6168                if (down) {
6169                    sleepPress(event.getEventTime());
6170                } else {
6171                    sleepRelease(event.getEventTime());
6172                }
6173                break;
6174            }
6175
6176            case KeyEvent.KEYCODE_SOFT_SLEEP: {
6177                result &= ~ACTION_PASS_TO_USER;
6178                isWakeKey = false;
6179                if (!down) {
6180                    mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
6181                }
6182                break;
6183            }
6184
6185            case KeyEvent.KEYCODE_WAKEUP: {
6186                result &= ~ACTION_PASS_TO_USER;
6187                isWakeKey = true;
6188                break;
6189            }
6190
6191            case KeyEvent.KEYCODE_MEDIA_PLAY:
6192            case KeyEvent.KEYCODE_MEDIA_PAUSE:
6193            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6194            case KeyEvent.KEYCODE_HEADSETHOOK:
6195            case KeyEvent.KEYCODE_MUTE:
6196            case KeyEvent.KEYCODE_MEDIA_STOP:
6197            case KeyEvent.KEYCODE_MEDIA_NEXT:
6198            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6199            case KeyEvent.KEYCODE_MEDIA_REWIND:
6200            case KeyEvent.KEYCODE_MEDIA_RECORD:
6201            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6202            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
6203                if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
6204                    // If the global session is active pass all media keys to it
6205                    // instead of the active window.
6206                    result &= ~ACTION_PASS_TO_USER;
6207                }
6208                if ((result & ACTION_PASS_TO_USER) == 0) {
6209                    // Only do this if we would otherwise not pass it to the user. In that
6210                    // case, the PhoneWindow class will do the same thing, except it will
6211                    // only do it if the showing app doesn't process the key on its own.
6212                    // Note that we need to make a copy of the key event here because the
6213                    // original key event will be recycled when we return.
6214                    mBroadcastWakeLock.acquire();
6215                    Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
6216                            new KeyEvent(event));
6217                    msg.setAsynchronous(true);
6218                    msg.sendToTarget();
6219                }
6220                break;
6221            }
6222
6223            case KeyEvent.KEYCODE_CALL: {
6224                if (down) {
6225                    TelecomManager telecomManager = getTelecommService();
6226                    if (telecomManager != null) {
6227                        if (telecomManager.isRinging()) {
6228                            Log.i(TAG, "interceptKeyBeforeQueueing:"
6229                                  + " CALL key-down while ringing: Answer the call!");
6230                            telecomManager.acceptRingingCall();
6231
6232                            // And *don't* pass this key thru to the current activity
6233                            // (which is presumably the InCallScreen.)
6234                            result &= ~ACTION_PASS_TO_USER;
6235                        }
6236                    }
6237                }
6238                break;
6239            }
6240            case KeyEvent.KEYCODE_VOICE_ASSIST: {
6241                // Only do this if we would otherwise not pass it to the user. In that case,
6242                // interceptKeyBeforeDispatching would apply a similar but different policy in
6243                // order to invoke voice assist actions. Note that we need to make a copy of the
6244                // key event here because the original key event will be recycled when we return.
6245                if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
6246                    mBroadcastWakeLock.acquire();
6247                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
6248                            keyguardActive ? 1 : 0, 0);
6249                    msg.setAsynchronous(true);
6250                    msg.sendToTarget();
6251                }
6252                break;
6253            }
6254            case KeyEvent.KEYCODE_WINDOW: {
6255                if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
6256                    if (mPictureInPictureVisible) {
6257                        // Consumes the key only if picture-in-picture is visible to show
6258                        // picture-in-picture control menu. This gives a chance to the foreground
6259                        // activity to customize PIP key behavior.
6260                        if (!down) {
6261                            showPictureInPictureMenu(event);
6262                        }
6263                        result &= ~ACTION_PASS_TO_USER;
6264                    }
6265                }
6266                break;
6267            }
6268        }
6269
6270        if (useHapticFeedback) {
6271            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
6272        }
6273
6274        if (isWakeKey) {
6275            wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
6276        }
6277
6278        return result;
6279    }
6280
6281    /**
6282     * Handle statusbar expansion events.
6283     * @param event
6284     */
6285    private void interceptSystemNavigationKey(KeyEvent event) {
6286        if (event.getAction() == KeyEvent.ACTION_UP) {
6287            if (!mAccessibilityManager.isEnabled()
6288                    || !mAccessibilityManager.sendFingerprintGesture(event.getKeyCode())) {
6289                if (areSystemNavigationKeysEnabled()) {
6290                    sendSystemKeyToStatusBarAsync(event.getKeyCode());
6291                }
6292            }
6293        }
6294    }
6295
6296    /**
6297     * Notify the StatusBar that a system key was pressed.
6298     */
6299    private void sendSystemKeyToStatusBar(int keyCode) {
6300        IStatusBarService statusBar = getStatusBarService();
6301        if (statusBar != null) {
6302            try {
6303                statusBar.handleSystemKey(keyCode);
6304            } catch (RemoteException e) {
6305                // Oh well.
6306            }
6307        }
6308    }
6309
6310    /**
6311     * Notify the StatusBar that a system key was pressed without blocking the current thread.
6312     */
6313    private void sendSystemKeyToStatusBarAsync(int keyCode) {
6314        Message message = mHandler.obtainMessage(MSG_SYSTEM_KEY_PRESS, keyCode, 0);
6315        message.setAsynchronous(true);
6316        mHandler.sendMessage(message);
6317    }
6318
6319    /**
6320     * Returns true if the key can have global actions attached to it.
6321     * We reserve all power management keys for the system since they require
6322     * very careful handling.
6323     */
6324    private static boolean isValidGlobalKey(int keyCode) {
6325        switch (keyCode) {
6326            case KeyEvent.KEYCODE_POWER:
6327            case KeyEvent.KEYCODE_WAKEUP:
6328            case KeyEvent.KEYCODE_SLEEP:
6329                return false;
6330            default:
6331                return true;
6332        }
6333    }
6334
6335    /**
6336     * When the screen is off we ignore some keys that might otherwise typically
6337     * be considered wake keys.  We filter them out here.
6338     *
6339     * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
6340     * is always considered a wake key.
6341     */
6342    private boolean isWakeKeyWhenScreenOff(int keyCode) {
6343        switch (keyCode) {
6344            // ignore volume keys unless docked
6345            case KeyEvent.KEYCODE_VOLUME_UP:
6346            case KeyEvent.KEYCODE_VOLUME_DOWN:
6347            case KeyEvent.KEYCODE_VOLUME_MUTE:
6348                return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
6349
6350            // ignore media and camera keys
6351            case KeyEvent.KEYCODE_MUTE:
6352            case KeyEvent.KEYCODE_HEADSETHOOK:
6353            case KeyEvent.KEYCODE_MEDIA_PLAY:
6354            case KeyEvent.KEYCODE_MEDIA_PAUSE:
6355            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6356            case KeyEvent.KEYCODE_MEDIA_STOP:
6357            case KeyEvent.KEYCODE_MEDIA_NEXT:
6358            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6359            case KeyEvent.KEYCODE_MEDIA_REWIND:
6360            case KeyEvent.KEYCODE_MEDIA_RECORD:
6361            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6362            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
6363            case KeyEvent.KEYCODE_CAMERA:
6364                return false;
6365        }
6366        return true;
6367    }
6368
6369
6370    /** {@inheritDoc} */
6371    @Override
6372    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
6373        if ((policyFlags & FLAG_WAKE) != 0) {
6374            if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
6375                    "android.policy:MOTION")) {
6376                return 0;
6377            }
6378        }
6379
6380        if (shouldDispatchInputWhenNonInteractive(null)) {
6381            return ACTION_PASS_TO_USER;
6382        }
6383
6384        // If we have not passed the action up and we are in theater mode without dreaming,
6385        // there will be no dream to intercept the touch and wake into ambient.  The device should
6386        // wake up in this case.
6387        if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
6388            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
6389                    "android.policy:MOTION");
6390        }
6391
6392        return 0;
6393    }
6394
6395    private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
6396        final boolean displayOff = (mDisplay == null || mDisplay.getState() == STATE_OFF);
6397
6398        if (displayOff && !mHasFeatureWatch) {
6399            return false;
6400        }
6401
6402        // Send events to keyguard while the screen is on and it's showing.
6403        if (isKeyguardShowingAndNotOccluded() && !displayOff) {
6404            return true;
6405        }
6406
6407        // Watches handle BACK specially
6408        if (mHasFeatureWatch
6409                && event != null
6410                && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
6411                        || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
6412            return false;
6413        }
6414
6415        // Send events to a dozing dream even if the screen is off since the dream
6416        // is in control of the state of the screen.
6417        IDreamManager dreamManager = getDreamManager();
6418
6419        try {
6420            if (dreamManager != null && dreamManager.isDreaming()) {
6421                return true;
6422            }
6423        } catch (RemoteException e) {
6424            Slog.e(TAG, "RemoteException when checking if dreaming", e);
6425        }
6426
6427        // Otherwise, consume events since the user can't see what is being
6428        // interacted with.
6429        return false;
6430    }
6431
6432    private void dispatchDirectAudioEvent(KeyEvent event) {
6433        if (event.getAction() != KeyEvent.ACTION_DOWN) {
6434            return;
6435        }
6436        int keyCode = event.getKeyCode();
6437        int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
6438                | AudioManager.FLAG_FROM_KEY;
6439        String pkgName = mContext.getOpPackageName();
6440        switch (keyCode) {
6441            case KeyEvent.KEYCODE_VOLUME_UP:
6442                try {
6443                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
6444                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6445                } catch (Exception e) {
6446                    Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
6447                }
6448                break;
6449            case KeyEvent.KEYCODE_VOLUME_DOWN:
6450                try {
6451                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
6452                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6453                } catch (Exception e) {
6454                    Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
6455                }
6456                break;
6457            case KeyEvent.KEYCODE_VOLUME_MUTE:
6458                try {
6459                    if (event.getRepeatCount() == 0) {
6460                        getAudioService().adjustSuggestedStreamVolume(
6461                                AudioManager.ADJUST_TOGGLE_MUTE,
6462                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6463                    }
6464                } catch (Exception e) {
6465                    Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
6466                }
6467                break;
6468        }
6469    }
6470
6471    void dispatchMediaKeyWithWakeLock(KeyEvent event) {
6472        if (DEBUG_INPUT) {
6473            Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
6474        }
6475
6476        if (mHavePendingMediaKeyRepeatWithWakeLock) {
6477            if (DEBUG_INPUT) {
6478                Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
6479            }
6480
6481            mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
6482            mHavePendingMediaKeyRepeatWithWakeLock = false;
6483            mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
6484        }
6485
6486        dispatchMediaKeyWithWakeLockToAudioService(event);
6487
6488        if (event.getAction() == KeyEvent.ACTION_DOWN
6489                && event.getRepeatCount() == 0) {
6490            mHavePendingMediaKeyRepeatWithWakeLock = true;
6491
6492            Message msg = mHandler.obtainMessage(
6493                    MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
6494            msg.setAsynchronous(true);
6495            mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
6496        } else {
6497            mBroadcastWakeLock.release();
6498        }
6499    }
6500
6501    void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
6502        mHavePendingMediaKeyRepeatWithWakeLock = false;
6503
6504        KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
6505                SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6506        if (DEBUG_INPUT) {
6507            Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
6508        }
6509
6510        dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
6511        mBroadcastWakeLock.release();
6512    }
6513
6514    void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
6515        if (mActivityManagerInternal.isSystemReady()) {
6516            MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
6517        }
6518    }
6519
6520    void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
6521        IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
6522                ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
6523        if (dic != null) {
6524            try {
6525                dic.exitIdle("voice-search");
6526            } catch (RemoteException e) {
6527            }
6528        }
6529        Intent voiceIntent =
6530            new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
6531        voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
6532        startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
6533        mBroadcastWakeLock.release();
6534    }
6535
6536    BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
6537        @Override
6538        public void onReceive(Context context, Intent intent) {
6539            if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
6540                mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6541                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
6542            } else {
6543                try {
6544                    IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
6545                            ServiceManager.getService(Context.UI_MODE_SERVICE));
6546                    mUiMode = uiModeService.getCurrentModeType();
6547                } catch (RemoteException e) {
6548                }
6549            }
6550            updateRotation(true);
6551            synchronized (mLock) {
6552                updateOrientationListenerLp();
6553            }
6554        }
6555    };
6556
6557    BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
6558        @Override
6559        public void onReceive(Context context, Intent intent) {
6560            if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
6561                if (mKeyguardDelegate != null) {
6562                    mKeyguardDelegate.onDreamingStarted();
6563                }
6564            } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
6565                if (mKeyguardDelegate != null) {
6566                    mKeyguardDelegate.onDreamingStopped();
6567                }
6568            }
6569        }
6570    };
6571
6572    BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
6573        @Override
6574        public void onReceive(Context context, Intent intent) {
6575            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
6576                // tickle the settings observer: this first ensures that we're
6577                // observing the relevant settings for the newly-active user,
6578                // and then updates our own bookkeeping based on the now-
6579                // current user.
6580                mSettingsObserver.onChange(false);
6581
6582                // force a re-application of focused window sysui visibility.
6583                // the window may never have been shown for this user
6584                // e.g. the keyguard when going through the new-user setup flow
6585                synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6586                    mLastSystemUiFlags = 0;
6587                    updateSystemUiVisibilityLw();
6588                }
6589            }
6590        }
6591    };
6592
6593    private final Runnable mHiddenNavPanic = new Runnable() {
6594        @Override
6595        public void run() {
6596            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6597                if (!isUserSetupComplete()) {
6598                    // Swipe-up for navigation bar is disabled during setup
6599                    return;
6600                }
6601                mPendingPanicGestureUptime = SystemClock.uptimeMillis();
6602                if (!isNavBarEmpty(mLastSystemUiFlags)) {
6603                    mNavigationBarController.showTransient();
6604                }
6605            }
6606        }
6607    };
6608
6609    private void requestTransientBars(WindowState swipeTarget) {
6610        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6611            if (!isUserSetupComplete()) {
6612                // Swipe-up for navigation bar is disabled during setup
6613                return;
6614            }
6615            boolean sb = mStatusBarController.checkShowTransientBarLw();
6616            boolean nb = mNavigationBarController.checkShowTransientBarLw()
6617                    && !isNavBarEmpty(mLastSystemUiFlags);
6618            if (sb || nb) {
6619                // Don't show status bar when swiping on already visible navigation bar
6620                if (!nb && swipeTarget == mNavigationBar) {
6621                    if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
6622                    return;
6623                }
6624                if (sb) mStatusBarController.showTransient();
6625                if (nb) mNavigationBarController.showTransient();
6626                mImmersiveModeConfirmation.confirmCurrentPrompt();
6627                updateSystemUiVisibilityLw();
6628            }
6629        }
6630    }
6631
6632    // Called on the PowerManager's Notifier thread.
6633    @Override
6634    public void startedGoingToSleep(int why) {
6635        if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
6636
6637        mGoingToSleep = true;
6638        mRequestedOrGoingToSleep = true;
6639
6640        if (mKeyguardDelegate != null) {
6641            mKeyguardDelegate.onStartedGoingToSleep(why);
6642        }
6643    }
6644
6645    // Called on the PowerManager's Notifier thread.
6646    @Override
6647    public void finishedGoingToSleep(int why) {
6648        EventLog.writeEvent(70000, 0);
6649        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
6650        MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
6651
6652        mGoingToSleep = false;
6653        mRequestedOrGoingToSleep = false;
6654
6655        // We must get this work done here because the power manager will drop
6656        // the wake lock and let the system suspend once this function returns.
6657        synchronized (mLock) {
6658            mAwake = false;
6659            updateWakeGestureListenerLp();
6660            updateOrientationListenerLp();
6661            updateLockScreenTimeout();
6662        }
6663        if (mKeyguardDelegate != null) {
6664            mKeyguardDelegate.onFinishedGoingToSleep(why,
6665                    mCameraGestureTriggeredDuringGoingToSleep);
6666        }
6667        mCameraGestureTriggeredDuringGoingToSleep = false;
6668    }
6669
6670    // Called on the PowerManager's Notifier thread.
6671    @Override
6672    public void startedWakingUp() {
6673        EventLog.writeEvent(70000, 1);
6674        if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
6675
6676        // Since goToSleep performs these functions synchronously, we must
6677        // do the same here.  We cannot post this work to a handler because
6678        // that might cause it to become reordered with respect to what
6679        // may happen in a future call to goToSleep.
6680        synchronized (mLock) {
6681            mAwake = true;
6682
6683            updateWakeGestureListenerLp();
6684            updateOrientationListenerLp();
6685            updateLockScreenTimeout();
6686        }
6687
6688        if (mKeyguardDelegate != null) {
6689            mKeyguardDelegate.onStartedWakingUp();
6690        }
6691    }
6692
6693    // Called on the PowerManager's Notifier thread.
6694    @Override
6695    public void finishedWakingUp() {
6696        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
6697
6698        if (mKeyguardDelegate != null) {
6699            mKeyguardDelegate.onFinishedWakingUp();
6700        }
6701    }
6702
6703    private void wakeUpFromPowerKey(long eventTime) {
6704        wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
6705    }
6706
6707    private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
6708        final boolean theaterModeEnabled = isTheaterModeEnabled();
6709        if (!wakeInTheaterMode && theaterModeEnabled) {
6710            return false;
6711        }
6712
6713        if (theaterModeEnabled) {
6714            Settings.Global.putInt(mContext.getContentResolver(),
6715                    Settings.Global.THEATER_MODE_ON, 0);
6716        }
6717
6718        mPowerManager.wakeUp(wakeTime, reason);
6719        return true;
6720    }
6721
6722    private void finishKeyguardDrawn() {
6723        synchronized (mLock) {
6724            if (!mScreenOnEarly || mKeyguardDrawComplete) {
6725                return; // We are not awake yet or we have already informed of this event.
6726            }
6727
6728            mKeyguardDrawComplete = true;
6729            if (mKeyguardDelegate != null) {
6730                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6731            }
6732            mWindowManagerDrawComplete = false;
6733        }
6734
6735        // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
6736        // as well as enabling the orientation change logic/sensor.
6737        mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
6738                WAITING_FOR_DRAWN_TIMEOUT);
6739    }
6740
6741    // Called on the DisplayManager's DisplayPowerController thread.
6742    @Override
6743    public void screenTurnedOff() {
6744        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
6745
6746        updateScreenOffSleepToken(true);
6747        synchronized (mLock) {
6748            mScreenOnEarly = false;
6749            mScreenOnFully = false;
6750            mKeyguardDrawComplete = false;
6751            mWindowManagerDrawComplete = false;
6752            mScreenOnListener = null;
6753            updateOrientationListenerLp();
6754
6755            if (mKeyguardDelegate != null) {
6756                mKeyguardDelegate.onScreenTurnedOff();
6757            }
6758        }
6759        reportScreenStateToVrManager(false);
6760    }
6761
6762    private long getKeyguardDrawnTimeout() {
6763        final boolean bootCompleted =
6764                LocalServices.getService(SystemServiceManager.class).isBootCompleted();
6765        // Set longer timeout if it has not booted yet to prevent showing empty window.
6766        return bootCompleted ? 1000 : 5000;
6767    }
6768
6769    // Called on the DisplayManager's DisplayPowerController thread.
6770    @Override
6771    public void screenTurningOn(final ScreenOnListener screenOnListener) {
6772        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
6773
6774        updateScreenOffSleepToken(false);
6775        synchronized (mLock) {
6776            mScreenOnEarly = true;
6777            mScreenOnFully = false;
6778            mKeyguardDrawComplete = false;
6779            mWindowManagerDrawComplete = false;
6780            mScreenOnListener = screenOnListener;
6781
6782            if (mKeyguardDelegate != null) {
6783                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6784                mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT,
6785                        getKeyguardDrawnTimeout());
6786                mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
6787            } else {
6788                if (DEBUG_WAKEUP) Slog.d(TAG,
6789                        "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
6790                finishKeyguardDrawn();
6791            }
6792        }
6793    }
6794
6795    // Called on the DisplayManager's DisplayPowerController thread.
6796    @Override
6797    public void screenTurnedOn() {
6798        synchronized (mLock) {
6799            if (mKeyguardDelegate != null) {
6800                mKeyguardDelegate.onScreenTurnedOn();
6801            }
6802        }
6803        reportScreenStateToVrManager(true);
6804    }
6805
6806    @Override
6807    public void screenTurningOff(ScreenOffListener screenOffListener) {
6808        mWindowManagerFuncs.screenTurningOff(screenOffListener);
6809        synchronized (mLock) {
6810            if (mKeyguardDelegate != null) {
6811                mKeyguardDelegate.onScreenTurningOff();
6812            }
6813        }
6814    }
6815
6816    private void reportScreenStateToVrManager(boolean isScreenOn) {
6817        if (mVrManagerInternal == null) {
6818            return;
6819        }
6820        mVrManagerInternal.onScreenStateChanged(isScreenOn);
6821    }
6822
6823    private void finishWindowsDrawn() {
6824        synchronized (mLock) {
6825            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
6826                return; // Screen is not turned on or we did already handle this case earlier.
6827            }
6828
6829            mWindowManagerDrawComplete = true;
6830        }
6831
6832        finishScreenTurningOn();
6833    }
6834
6835    private void finishScreenTurningOn() {
6836        synchronized (mLock) {
6837            // We have just finished drawing screen content. Since the orientation listener
6838            // gets only installed when all windows are drawn, we try to install it again.
6839            updateOrientationListenerLp();
6840        }
6841        final ScreenOnListener listener;
6842        final boolean enableScreen;
6843        synchronized (mLock) {
6844            if (DEBUG_WAKEUP) Slog.d(TAG,
6845                    "finishScreenTurningOn: mAwake=" + mAwake
6846                            + ", mScreenOnEarly=" + mScreenOnEarly
6847                            + ", mScreenOnFully=" + mScreenOnFully
6848                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
6849                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
6850
6851            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
6852                    || (mAwake && !mKeyguardDrawComplete)) {
6853                return; // spurious or not ready yet
6854            }
6855
6856            if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
6857            listener = mScreenOnListener;
6858            mScreenOnListener = null;
6859            mScreenOnFully = true;
6860
6861            // Remember the first time we draw the keyguard so we know when we're done with
6862            // the main part of booting and can enable the screen and hide boot messages.
6863            if (!mKeyguardDrawnOnce && mAwake) {
6864                mKeyguardDrawnOnce = true;
6865                enableScreen = true;
6866                if (mBootMessageNeedsHiding) {
6867                    mBootMessageNeedsHiding = false;
6868                    hideBootMessages();
6869                }
6870            } else {
6871                enableScreen = false;
6872            }
6873        }
6874
6875        if (listener != null) {
6876            listener.onScreenOn();
6877        }
6878
6879        if (enableScreen) {
6880            try {
6881                mWindowManager.enableScreenIfNeeded();
6882            } catch (RemoteException unhandled) {
6883            }
6884        }
6885    }
6886
6887    private void handleHideBootMessage() {
6888        synchronized (mLock) {
6889            if (!mKeyguardDrawnOnce) {
6890                mBootMessageNeedsHiding = true;
6891                return; // keyguard hasn't drawn the first time yet, not done booting
6892            }
6893        }
6894
6895        if (mBootMsgDialog != null) {
6896            if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
6897            mBootMsgDialog.dismiss();
6898            mBootMsgDialog = null;
6899        }
6900    }
6901
6902    @Override
6903    public boolean isScreenOn() {
6904        synchronized (mLock) {
6905            return mScreenOnEarly;
6906        }
6907    }
6908
6909    @Override
6910    public boolean okToAnimate() {
6911        return mAwake && !mGoingToSleep;
6912    }
6913
6914    /** {@inheritDoc} */
6915    @Override
6916    public void enableKeyguard(boolean enabled) {
6917        if (mKeyguardDelegate != null) {
6918            mKeyguardDelegate.setKeyguardEnabled(enabled);
6919        }
6920    }
6921
6922    /** {@inheritDoc} */
6923    @Override
6924    public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
6925        if (mKeyguardDelegate != null) {
6926            mKeyguardDelegate.verifyUnlock(callback);
6927        }
6928    }
6929
6930    @Override
6931    public boolean isKeyguardShowingAndNotOccluded() {
6932        if (mKeyguardDelegate == null) return false;
6933        return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
6934    }
6935
6936    @Override
6937    public boolean isKeyguardTrustedLw() {
6938        if (mKeyguardDelegate == null) return false;
6939        return mKeyguardDelegate.isTrusted();
6940    }
6941
6942    /** {@inheritDoc} */
6943    @Override
6944    public boolean isKeyguardLocked() {
6945        return keyguardOn();
6946    }
6947
6948    /** {@inheritDoc} */
6949    @Override
6950    public boolean isKeyguardSecure(int userId) {
6951        if (mKeyguardDelegate == null) return false;
6952        return mKeyguardDelegate.isSecure(userId);
6953    }
6954
6955    /** {@inheritDoc} */
6956    @Override
6957    public boolean isKeyguardOccluded() {
6958        if (mKeyguardDelegate == null) return false;
6959        return mKeyguardOccluded;
6960    }
6961
6962    /** {@inheritDoc} */
6963    @Override
6964    public boolean inKeyguardRestrictedKeyInputMode() {
6965        if (mKeyguardDelegate == null) return false;
6966        return mKeyguardDelegate.isInputRestricted();
6967    }
6968
6969    @Override
6970    public void dismissKeyguardLw(IKeyguardDismissCallback callback) {
6971        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
6972            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
6973
6974            // ask the keyguard to prompt the user to authenticate if necessary
6975            mKeyguardDelegate.dismiss(callback);
6976        } else if (callback != null) {
6977            try {
6978                callback.onDismissError();
6979            } catch (RemoteException e) {
6980                Slog.w(TAG, "Failed to call callback", e);
6981            }
6982        }
6983    }
6984
6985    @Override
6986    public boolean isKeyguardDrawnLw() {
6987        synchronized (mLock) {
6988            return mKeyguardDrawnOnce;
6989        }
6990    }
6991
6992    @Override
6993    public boolean isShowingDreamLw() {
6994        return mShowingDream;
6995    }
6996
6997    @Override
6998    public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
6999        if (mKeyguardDelegate != null) {
7000            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
7001            mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
7002        }
7003    }
7004
7005    @Override
7006    public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
7007            Rect outInsets) {
7008        outInsets.setEmpty();
7009
7010        // Navigation bar and status bar.
7011        getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
7012        outInsets.top = mStatusBarHeight;
7013    }
7014
7015    @Override
7016    public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
7017            Rect outInsets) {
7018        outInsets.setEmpty();
7019
7020        // Only navigation bar
7021        if (mHasNavigationBar) {
7022            int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
7023            if (position == NAV_BAR_BOTTOM) {
7024                outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
7025            } else if (position == NAV_BAR_RIGHT) {
7026                outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
7027            } else if (position == NAV_BAR_LEFT) {
7028                outInsets.left = getNavigationBarWidth(displayRotation, mUiMode);
7029            }
7030        }
7031    }
7032
7033    @Override
7034    public boolean isNavBarForcedShownLw(WindowState windowState) {
7035        return mForceShowSystemBars;
7036    }
7037
7038    @Override
7039    public int getNavBarPosition() {
7040        // TODO(multi-display): Support system decor on secondary displays.
7041        return mNavigationBarPosition;
7042    }
7043
7044    @Override
7045    public boolean isDockSideAllowed(int dockSide) {
7046
7047        // We do not allow all dock sides at which the navigation bar touches the docked stack.
7048        if (!mNavigationBarCanMove) {
7049            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT;
7050        } else {
7051            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT;
7052        }
7053    }
7054
7055    void sendCloseSystemWindows() {
7056        PhoneWindow.sendCloseSystemWindows(mContext, null);
7057    }
7058
7059    void sendCloseSystemWindows(String reason) {
7060        PhoneWindow.sendCloseSystemWindows(mContext, reason);
7061    }
7062
7063    @Override
7064    public int rotationForOrientationLw(int orientation, int lastRotation) {
7065        if (false) {
7066            Slog.v(TAG, "rotationForOrientationLw(orient="
7067                        + orientation + ", last=" + lastRotation
7068                        + "); user=" + mUserRotation + " "
7069                        + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
7070                            ? "USER_ROTATION_LOCKED" : "")
7071                        );
7072        }
7073
7074        if (mForceDefaultOrientation) {
7075            return Surface.ROTATION_0;
7076        }
7077
7078        synchronized (mLock) {
7079            int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
7080            if (sensorRotation < 0) {
7081                sensorRotation = lastRotation;
7082            }
7083
7084            final int preferredRotation;
7085            if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
7086                // Ignore sensor when lid switch is open and rotation is forced.
7087                preferredRotation = mLidOpenRotation;
7088            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
7089                    && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
7090                // Ignore sensor when in car dock unless explicitly enabled.
7091                // This case can override the behavior of NOSENSOR, and can also
7092                // enable 180 degree rotation while docked.
7093                preferredRotation = mCarDockEnablesAccelerometer
7094                        ? sensorRotation : mCarDockRotation;
7095            } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7096                    || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
7097                    || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
7098                    && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
7099                // Ignore sensor when in desk dock unless explicitly enabled.
7100                // This case can override the behavior of NOSENSOR, and can also
7101                // enable 180 degree rotation while docked.
7102                preferredRotation = mDeskDockEnablesAccelerometer
7103                        ? sensorRotation : mDeskDockRotation;
7104            } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
7105                // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
7106                // Note that the dock orientation overrides the HDMI orientation.
7107                preferredRotation = mDemoHdmiRotation;
7108            } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
7109                    && mUndockedHdmiRotation >= 0) {
7110                // Ignore sensor when plugged into HDMI and an undocked orientation has
7111                // been specified in the configuration (only for legacy devices without
7112                // full multi-display support).
7113                // Note that the dock orientation overrides the HDMI orientation.
7114                preferredRotation = mUndockedHdmiRotation;
7115            } else if (mDemoRotationLock) {
7116                // Ignore sensor when demo rotation lock is enabled.
7117                // Note that the dock orientation and HDMI rotation lock override this.
7118                preferredRotation = mDemoRotation;
7119            } else if (mPersistentVrModeEnabled) {
7120                // While in VR, apps always prefer a portrait rotation. This does not change
7121                // any apps that explicitly set landscape, but does cause sensors be ignored,
7122                // and ignored any orientation lock that the user has set (this conditional
7123                // should remain above the ORIENTATION_LOCKED conditional below).
7124                preferredRotation = mPortraitRotation;
7125            } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
7126                // Application just wants to remain locked in the last rotation.
7127                preferredRotation = lastRotation;
7128            } else if (!mSupportAutoRotation) {
7129                // If we don't support auto-rotation then bail out here and ignore
7130                // the sensor and any rotation lock settings.
7131                preferredRotation = -1;
7132            } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
7133                            && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
7134                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
7135                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
7136                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
7137                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
7138                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
7139                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
7140                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
7141                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
7142                // Otherwise, use sensor only if requested by the application or enabled
7143                // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
7144                if (mAllowAllRotations < 0) {
7145                    // Can't read this during init() because the context doesn't
7146                    // have display metrics at that time so we cannot determine
7147                    // tablet vs. phone then.
7148                    mAllowAllRotations = mContext.getResources().getBoolean(
7149                            com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
7150                }
7151                if (sensorRotation != Surface.ROTATION_180
7152                        || mAllowAllRotations == 1
7153                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
7154                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
7155                    preferredRotation = sensorRotation;
7156                } else {
7157                    preferredRotation = lastRotation;
7158                }
7159            } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
7160                    && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
7161                // Apply rotation lock.  Does not apply to NOSENSOR.
7162                // The idea is that the user rotation expresses a weak preference for the direction
7163                // of gravity and as NOSENSOR is never affected by gravity, then neither should
7164                // NOSENSOR be affected by rotation lock (although it will be affected by docks).
7165                preferredRotation = mUserRotation;
7166            } else {
7167                // No overriding preference.
7168                // We will do exactly what the application asked us to do.
7169                preferredRotation = -1;
7170            }
7171
7172            switch (orientation) {
7173                case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
7174                    // Return portrait unless overridden.
7175                    if (isAnyPortrait(preferredRotation)) {
7176                        return preferredRotation;
7177                    }
7178                    return mPortraitRotation;
7179
7180                case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
7181                    // Return landscape unless overridden.
7182                    if (isLandscapeOrSeascape(preferredRotation)) {
7183                        return preferredRotation;
7184                    }
7185                    return mLandscapeRotation;
7186
7187                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
7188                    // Return reverse portrait unless overridden.
7189                    if (isAnyPortrait(preferredRotation)) {
7190                        return preferredRotation;
7191                    }
7192                    return mUpsideDownRotation;
7193
7194                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
7195                    // Return seascape unless overridden.
7196                    if (isLandscapeOrSeascape(preferredRotation)) {
7197                        return preferredRotation;
7198                    }
7199                    return mSeascapeRotation;
7200
7201                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
7202                case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
7203                    // Return either landscape rotation.
7204                    if (isLandscapeOrSeascape(preferredRotation)) {
7205                        return preferredRotation;
7206                    }
7207                    if (isLandscapeOrSeascape(lastRotation)) {
7208                        return lastRotation;
7209                    }
7210                    return mLandscapeRotation;
7211
7212                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
7213                case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
7214                    // Return either portrait rotation.
7215                    if (isAnyPortrait(preferredRotation)) {
7216                        return preferredRotation;
7217                    }
7218                    if (isAnyPortrait(lastRotation)) {
7219                        return lastRotation;
7220                    }
7221                    return mPortraitRotation;
7222
7223                default:
7224                    // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
7225                    // just return the preferred orientation we already calculated.
7226                    if (preferredRotation >= 0) {
7227                        return preferredRotation;
7228                    }
7229                    return Surface.ROTATION_0;
7230            }
7231        }
7232    }
7233
7234    @Override
7235    public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
7236        switch (orientation) {
7237            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
7238            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
7239            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
7240                return isAnyPortrait(rotation);
7241
7242            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
7243            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
7244            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
7245                return isLandscapeOrSeascape(rotation);
7246
7247            default:
7248                return true;
7249        }
7250    }
7251
7252    @Override
7253    public void setRotationLw(int rotation) {
7254        mOrientationListener.setCurrentRotation(rotation);
7255    }
7256
7257    private boolean isLandscapeOrSeascape(int rotation) {
7258        return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
7259    }
7260
7261    private boolean isAnyPortrait(int rotation) {
7262        return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
7263    }
7264
7265    @Override
7266    public int getUserRotationMode() {
7267        return Settings.System.getIntForUser(mContext.getContentResolver(),
7268                Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
7269                        WindowManagerPolicy.USER_ROTATION_FREE :
7270                                WindowManagerPolicy.USER_ROTATION_LOCKED;
7271    }
7272
7273    // User rotation: to be used when all else fails in assigning an orientation to the device
7274    @Override
7275    public void setUserRotationMode(int mode, int rot) {
7276        ContentResolver res = mContext.getContentResolver();
7277
7278        // mUserRotationMode and mUserRotation will be assigned by the content observer
7279        if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
7280            Settings.System.putIntForUser(res,
7281                    Settings.System.USER_ROTATION,
7282                    rot,
7283                    UserHandle.USER_CURRENT);
7284            Settings.System.putIntForUser(res,
7285                    Settings.System.ACCELEROMETER_ROTATION,
7286                    0,
7287                    UserHandle.USER_CURRENT);
7288        } else {
7289            Settings.System.putIntForUser(res,
7290                    Settings.System.ACCELEROMETER_ROTATION,
7291                    1,
7292                    UserHandle.USER_CURRENT);
7293        }
7294    }
7295
7296    @Override
7297    public void setSafeMode(boolean safeMode) {
7298        mSafeMode = safeMode;
7299        if (safeMode) {
7300            performHapticFeedbackLw(null, HapticFeedbackConstants.SAFE_MODE_ENABLED, true);
7301        }
7302    }
7303
7304    static long[] getLongIntArray(Resources r, int resid) {
7305        int[] ar = r.getIntArray(resid);
7306        if (ar == null) {
7307            return null;
7308        }
7309        long[] out = new long[ar.length];
7310        for (int i=0; i<ar.length; i++) {
7311            out[i] = ar[i];
7312        }
7313        return out;
7314    }
7315
7316    private void bindKeyguard() {
7317        synchronized (mLock) {
7318            if (mKeyguardBound) {
7319                return;
7320            }
7321            mKeyguardBound = true;
7322        }
7323        mKeyguardDelegate.bindService(mContext);
7324    }
7325
7326    @Override
7327    public void onSystemUiStarted() {
7328        bindKeyguard();
7329    }
7330
7331    /** {@inheritDoc} */
7332    @Override
7333    public void systemReady() {
7334        // In normal flow, systemReady is called before other system services are ready.
7335        // So it is better not to bind keyguard here.
7336        mKeyguardDelegate.onSystemReady();
7337
7338        mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
7339        if (mVrManagerInternal != null) {
7340            mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
7341        }
7342
7343        readCameraLensCoverState();
7344        updateUiMode();
7345        synchronized (mLock) {
7346            updateOrientationListenerLp();
7347            mSystemReady = true;
7348            mHandler.post(new Runnable() {
7349                @Override
7350                public void run() {
7351                    updateSettings();
7352                }
7353            });
7354            // If this happens, for whatever reason, systemReady came later than systemBooted.
7355            // And keyguard should be already bound from systemBooted
7356            if (mSystemBooted) {
7357                mKeyguardDelegate.onBootCompleted();
7358            }
7359        }
7360
7361        mSystemGestures.systemReady();
7362        mImmersiveModeConfirmation.systemReady();
7363
7364        mAutofillManagerInternal = LocalServices.getService(AutofillManagerInternal.class);
7365    }
7366
7367    /** {@inheritDoc} */
7368    @Override
7369    public void systemBooted() {
7370        bindKeyguard();
7371        synchronized (mLock) {
7372            mSystemBooted = true;
7373            if (mSystemReady) {
7374                mKeyguardDelegate.onBootCompleted();
7375            }
7376        }
7377        startedWakingUp();
7378        screenTurningOn(null);
7379        screenTurnedOn();
7380    }
7381
7382    @Override
7383    public boolean canDismissBootAnimation() {
7384        synchronized (mLock) {
7385            return mKeyguardDrawComplete;
7386        }
7387    }
7388
7389    ProgressDialog mBootMsgDialog = null;
7390
7391    /** {@inheritDoc} */
7392    @Override
7393    public void showBootMessage(final CharSequence msg, final boolean always) {
7394        mHandler.post(new Runnable() {
7395            @Override public void run() {
7396                if (mBootMsgDialog == null) {
7397                    int theme;
7398                    if (mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK)) {
7399                        theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
7400                    } else {
7401                        theme = 0;
7402                    }
7403
7404                    mBootMsgDialog = new ProgressDialog(mContext, theme) {
7405                        // This dialog will consume all events coming in to
7406                        // it, to avoid it trying to do things too early in boot.
7407                        @Override public boolean dispatchKeyEvent(KeyEvent event) {
7408                            return true;
7409                        }
7410                        @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7411                            return true;
7412                        }
7413                        @Override public boolean dispatchTouchEvent(MotionEvent ev) {
7414                            return true;
7415                        }
7416                        @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
7417                            return true;
7418                        }
7419                        @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
7420                            return true;
7421                        }
7422                        @Override public boolean dispatchPopulateAccessibilityEvent(
7423                                AccessibilityEvent event) {
7424                            return true;
7425                        }
7426                    };
7427                    if (mContext.getPackageManager().isUpgrade()) {
7428                        mBootMsgDialog.setTitle(R.string.android_upgrading_title);
7429                    } else {
7430                        mBootMsgDialog.setTitle(R.string.android_start_title);
7431                    }
7432                    mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
7433                    mBootMsgDialog.setIndeterminate(true);
7434                    mBootMsgDialog.getWindow().setType(
7435                            WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
7436                    mBootMsgDialog.getWindow().addFlags(
7437                            WindowManager.LayoutParams.FLAG_DIM_BEHIND
7438                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
7439                    mBootMsgDialog.getWindow().setDimAmount(1);
7440                    WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
7441                    lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
7442                    mBootMsgDialog.getWindow().setAttributes(lp);
7443                    mBootMsgDialog.setCancelable(false);
7444                    mBootMsgDialog.show();
7445                }
7446                mBootMsgDialog.setMessage(msg);
7447            }
7448        });
7449    }
7450
7451    /** {@inheritDoc} */
7452    @Override
7453    public void hideBootMessages() {
7454        mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
7455    }
7456
7457    /** {@inheritDoc} */
7458    @Override
7459    public void userActivity() {
7460        // ***************************************
7461        // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
7462        // ***************************************
7463        // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
7464        // WITH ITS LOCKS HELD.
7465        //
7466        // This code must be VERY careful about the locks
7467        // it acquires.
7468        // In fact, the current code acquires way too many,
7469        // and probably has lurking deadlocks.
7470
7471        synchronized (mScreenLockTimeout) {
7472            if (mLockScreenTimerActive) {
7473                // reset the timer
7474                mHandler.removeCallbacks(mScreenLockTimeout);
7475                mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7476            }
7477        }
7478    }
7479
7480    class ScreenLockTimeout implements Runnable {
7481        Bundle options;
7482
7483        @Override
7484        public void run() {
7485            synchronized (this) {
7486                if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
7487                if (mKeyguardDelegate != null) {
7488                    mKeyguardDelegate.doKeyguardTimeout(options);
7489                }
7490                mLockScreenTimerActive = false;
7491                options = null;
7492            }
7493        }
7494
7495        public void setLockOptions(Bundle options) {
7496            this.options = options;
7497        }
7498    }
7499
7500    ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
7501
7502    @Override
7503    public void lockNow(Bundle options) {
7504        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
7505        mHandler.removeCallbacks(mScreenLockTimeout);
7506        if (options != null) {
7507            // In case multiple calls are made to lockNow, we don't wipe out the options
7508            // until the runnable actually executes.
7509            mScreenLockTimeout.setLockOptions(options);
7510        }
7511        mHandler.post(mScreenLockTimeout);
7512    }
7513
7514    private void updateLockScreenTimeout() {
7515        synchronized (mScreenLockTimeout) {
7516            boolean enable = (mAllowLockscreenWhenOn && mAwake &&
7517                    mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
7518            if (mLockScreenTimerActive != enable) {
7519                if (enable) {
7520                    if (localLOGV) Log.v(TAG, "setting lockscreen timer");
7521                    mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
7522                    mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7523                } else {
7524                    if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
7525                    mHandler.removeCallbacks(mScreenLockTimeout);
7526                }
7527                mLockScreenTimerActive = enable;
7528            }
7529        }
7530    }
7531
7532    // TODO (multidisplay): Support multiple displays in WindowManagerPolicy.
7533    private void updateDreamingSleepToken(boolean acquire) {
7534        if (acquire) {
7535            if (mDreamingSleepToken == null) {
7536                mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken(
7537                        "Dream", DEFAULT_DISPLAY);
7538            }
7539        } else {
7540            if (mDreamingSleepToken != null) {
7541                mDreamingSleepToken.release();
7542                mDreamingSleepToken = null;
7543            }
7544        }
7545    }
7546
7547    // TODO (multidisplay): Support multiple displays in WindowManagerPolicy.
7548    private void updateScreenOffSleepToken(boolean acquire) {
7549        if (acquire) {
7550            if (mScreenOffSleepToken == null) {
7551                mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken(
7552                        "ScreenOff", DEFAULT_DISPLAY);
7553            }
7554        } else {
7555            if (mScreenOffSleepToken != null) {
7556                mScreenOffSleepToken.release();
7557                mScreenOffSleepToken = null;
7558            }
7559        }
7560    }
7561
7562    /** {@inheritDoc} */
7563    @Override
7564    public void enableScreenAfterBoot() {
7565        readLidState();
7566        applyLidSwitchState();
7567        updateRotation(true);
7568    }
7569
7570    private void applyLidSwitchState() {
7571        if (mLidState == LID_CLOSED && mLidControlsSleep) {
7572            goToSleep(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
7573                    PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
7574        } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
7575            mWindowManagerFuncs.lockDeviceNow();
7576        }
7577
7578        synchronized (mLock) {
7579            updateWakeGestureListenerLp();
7580        }
7581    }
7582
7583    void updateUiMode() {
7584        if (mUiModeManager == null) {
7585            mUiModeManager = IUiModeManager.Stub.asInterface(
7586                    ServiceManager.getService(Context.UI_MODE_SERVICE));
7587        }
7588        try {
7589            mUiMode = mUiModeManager.getCurrentModeType();
7590        } catch (RemoteException e) {
7591        }
7592    }
7593
7594    void updateRotation(boolean alwaysSendConfiguration) {
7595        try {
7596            //set orientation on WindowManager
7597            mWindowManager.updateRotation(alwaysSendConfiguration, false);
7598        } catch (RemoteException e) {
7599            // Ignore
7600        }
7601    }
7602
7603    void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
7604        try {
7605            //set orientation on WindowManager
7606            mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
7607        } catch (RemoteException e) {
7608            // Ignore
7609        }
7610    }
7611
7612    /**
7613     * Return an Intent to launch the currently active dock app as home.  Returns
7614     * null if the standard home should be launched, which is the case if any of the following is
7615     * true:
7616     * <ul>
7617     *  <li>The device is not in either car mode or desk mode
7618     *  <li>The device is in car mode but mEnableCarDockHomeCapture is false
7619     *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
7620     *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
7621     *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
7622     * </ul>
7623     * @return A dock intent.
7624     */
7625    Intent createHomeDockIntent() {
7626        Intent intent = null;
7627
7628        // What home does is based on the mode, not the dock state.  That
7629        // is, when in car mode you should be taken to car home regardless
7630        // of whether we are actually in a car dock.
7631        if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
7632            if (mEnableCarDockHomeCapture) {
7633                intent = mCarDockIntent;
7634            }
7635        } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
7636            if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
7637                intent = mDeskDockIntent;
7638            }
7639        } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
7640                && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7641                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
7642                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
7643            // Always launch dock home from home when watch is docked, if it exists.
7644            intent = mDeskDockIntent;
7645        } else if (mUiMode == Configuration.UI_MODE_TYPE_VR_HEADSET) {
7646            if (ENABLE_VR_HEADSET_HOME_CAPTURE) {
7647                intent = mVrHeadsetHomeIntent;
7648            }
7649        }
7650
7651        if (intent == null) {
7652            return null;
7653        }
7654
7655        ActivityInfo ai = null;
7656        ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
7657                intent,
7658                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
7659                mCurrentUserId);
7660        if (info != null) {
7661            ai = info.activityInfo;
7662        }
7663        if (ai != null
7664                && ai.metaData != null
7665                && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
7666            intent = new Intent(intent);
7667            intent.setClassName(ai.packageName, ai.name);
7668            return intent;
7669        }
7670
7671        return null;
7672    }
7673
7674    void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
7675        if (awakenFromDreams) {
7676            awakenDreams();
7677        }
7678
7679        Intent dock = createHomeDockIntent();
7680        if (dock != null) {
7681            try {
7682                if (fromHomeKey) {
7683                    dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7684                }
7685                startActivityAsUser(dock, UserHandle.CURRENT);
7686                return;
7687            } catch (ActivityNotFoundException e) {
7688            }
7689        }
7690
7691        Intent intent;
7692
7693        if (fromHomeKey) {
7694            intent = new Intent(mHomeIntent);
7695            intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7696        } else {
7697            intent = mHomeIntent;
7698        }
7699
7700        startActivityAsUser(intent, UserHandle.CURRENT);
7701    }
7702
7703    /**
7704     * goes to the home screen
7705     * @return whether it did anything
7706     */
7707    boolean goHome() {
7708        if (!isUserSetupComplete()) {
7709            Slog.i(TAG, "Not going home because user setup is in progress.");
7710            return false;
7711        }
7712        if (false) {
7713            // This code always brings home to the front.
7714            try {
7715                ActivityManager.getService().stopAppSwitches();
7716            } catch (RemoteException e) {
7717            }
7718            sendCloseSystemWindows();
7719            startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
7720        } else {
7721            // This code brings home to the front or, if it is already
7722            // at the front, puts the device to sleep.
7723            try {
7724                if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
7725                    /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
7726                    Log.d(TAG, "UTS-TEST-MODE");
7727                } else {
7728                    ActivityManager.getService().stopAppSwitches();
7729                    sendCloseSystemWindows();
7730                    Intent dock = createHomeDockIntent();
7731                    if (dock != null) {
7732                        int result = ActivityManager.getService()
7733                                .startActivityAsUser(null, null, dock,
7734                                        dock.resolveTypeIfNeeded(mContext.getContentResolver()),
7735                                        null, null, 0,
7736                                        ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7737                                        null, null, UserHandle.USER_CURRENT);
7738                        if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7739                            return false;
7740                        }
7741                    }
7742                }
7743                int result = ActivityManager.getService()
7744                        .startActivityAsUser(null, null, mHomeIntent,
7745                                mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
7746                                null, null, 0,
7747                                ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7748                                null, null, UserHandle.USER_CURRENT);
7749                if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7750                    return false;
7751                }
7752            } catch (RemoteException ex) {
7753                // bummer, the activity manager, which is in this process, is dead
7754            }
7755        }
7756        return true;
7757    }
7758
7759    @Override
7760    public void setCurrentOrientationLw(int newOrientation) {
7761        synchronized (mLock) {
7762            if (newOrientation != mCurrentAppOrientation) {
7763                mCurrentAppOrientation = newOrientation;
7764                updateOrientationListenerLp();
7765            }
7766        }
7767    }
7768
7769    private boolean isTheaterModeEnabled() {
7770        return Settings.Global.getInt(mContext.getContentResolver(),
7771                Settings.Global.THEATER_MODE_ON, 0) == 1;
7772    }
7773
7774    private boolean areSystemNavigationKeysEnabled() {
7775        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
7776                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
7777    }
7778
7779    @Override
7780    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
7781        if (!mVibrator.hasVibrator()) {
7782            return false;
7783        }
7784        final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
7785                Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
7786        if (hapticsDisabled && !always) {
7787            return false;
7788        }
7789
7790        VibrationEffect effect = getVibrationEffect(effectId);
7791        if (effect == null) {
7792            return false;
7793        }
7794
7795        int owningUid;
7796        String owningPackage;
7797        if (win != null) {
7798            owningUid = win.getOwningUid();
7799            owningPackage = win.getOwningPackage();
7800        } else {
7801            owningUid = android.os.Process.myUid();
7802            owningPackage = mContext.getOpPackageName();
7803        }
7804        mVibrator.vibrate(owningUid, owningPackage, effect, VIBRATION_ATTRIBUTES);
7805        return true;
7806    }
7807
7808    private VibrationEffect getVibrationEffect(int effectId) {
7809        long[] pattern;
7810        switch (effectId) {
7811            case HapticFeedbackConstants.LONG_PRESS:
7812                pattern = mLongPressVibePattern;
7813                break;
7814            case HapticFeedbackConstants.CLOCK_TICK:
7815                return VibrationEffect.get(VibrationEffect.EFFECT_TICK);
7816            case HapticFeedbackConstants.CALENDAR_DATE:
7817                pattern = mCalendarDateVibePattern;
7818                break;
7819            case HapticFeedbackConstants.SAFE_MODE_ENABLED:
7820                pattern = mSafeModeEnabledVibePattern;
7821                break;
7822            case HapticFeedbackConstants.CONTEXT_CLICK:
7823                return VibrationEffect.get(VibrationEffect.EFFECT_TICK);
7824            case HapticFeedbackConstants.VIRTUAL_KEY:
7825                return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
7826            case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE:
7827                return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false);
7828            case HapticFeedbackConstants.KEYBOARD_PRESS:  // == HapticFeedbackConstants.KEYBOARD_TAP
7829                return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
7830            case HapticFeedbackConstants.KEYBOARD_RELEASE:
7831                return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false);
7832            case HapticFeedbackConstants.TEXT_HANDLE_MOVE:
7833                return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false);
7834            default:
7835                return null;
7836        }
7837        if (pattern.length == 0) {
7838            // No vibration
7839            return null;
7840        } else if (pattern.length == 1) {
7841            // One-shot vibration
7842            return VibrationEffect.createOneShot(pattern[0], VibrationEffect.DEFAULT_AMPLITUDE);
7843        } else {
7844            // Pattern vibration
7845            return VibrationEffect.createWaveform(pattern, -1);
7846        }
7847    }
7848
7849    @Override
7850    public void keepScreenOnStartedLw() {
7851    }
7852
7853    @Override
7854    public void keepScreenOnStoppedLw() {
7855        if (isKeyguardShowingAndNotOccluded()) {
7856            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
7857        }
7858    }
7859
7860    private int updateSystemUiVisibilityLw() {
7861        // If there is no window focused, there will be nobody to handle the events
7862        // anyway, so just hang on in whatever state we're in until things settle down.
7863        WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
7864                : mTopFullscreenOpaqueWindowState;
7865        if (winCandidate == null) {
7866            return 0;
7867        }
7868        if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
7869            // The immersive mode confirmation should never affect the system bar visibility,
7870            // otherwise it will unhide the navigation bar and hide itself.
7871            winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState;
7872            if (winCandidate == null) {
7873                return 0;
7874            }
7875        }
7876        final WindowState win = winCandidate;
7877        if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mKeyguardOccluded) {
7878            // We are updating at a point where the keyguard has gotten
7879            // focus, but we were last in a state where the top window is
7880            // hiding it.  This is probably because the keyguard as been
7881            // shown while the top window was displayed, so we want to ignore
7882            // it here because this is just a very transient change and it
7883            // will quickly lose focus once it correctly gets hidden.
7884            return 0;
7885        }
7886
7887        int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
7888                & ~mResettingSystemUiFlags
7889                & ~mForceClearedSystemUiFlags;
7890        if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
7891            tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
7892        }
7893
7894        final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
7895                mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
7896        final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
7897                mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
7898        mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);
7899        mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);
7900        final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
7901        final int diff = visibility ^ mLastSystemUiFlags;
7902        final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
7903        final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
7904        final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
7905        if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
7906                && mFocusedApp == win.getAppToken()
7907                && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
7908                && mLastDockedStackBounds.equals(mDockedStackBounds)) {
7909            return 0;
7910        }
7911        mLastSystemUiFlags = visibility;
7912        mLastFullscreenStackSysUiFlags = fullscreenVisibility;
7913        mLastDockedStackSysUiFlags = dockedVisibility;
7914        mLastFocusNeedsMenu = needsMenu;
7915        mFocusedApp = win.getAppToken();
7916        final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
7917        final Rect dockedStackBounds = new Rect(mDockedStackBounds);
7918        mHandler.post(new Runnable() {
7919                @Override
7920                public void run() {
7921                    StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
7922                    if (statusbar != null) {
7923                        statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
7924                                dockedVisibility, 0xffffffff, fullscreenStackBounds,
7925                                dockedStackBounds, win.toString());
7926                        statusbar.topAppWindowChanged(needsMenu);
7927                    }
7928                }
7929            });
7930        return diff;
7931    }
7932
7933    private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
7934        final boolean onKeyguard = isStatusBarKeyguard() && !mKeyguardOccluded;
7935        final WindowState statusColorWin = onKeyguard ? mStatusBar : opaqueOrDimming;
7936        if (statusColorWin != null && (statusColorWin == opaque || onKeyguard)) {
7937            // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7938            // its light flag.
7939            vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7940            vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
7941                    & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7942        } else if (statusColorWin != null && statusColorWin.isDimming()) {
7943            // Otherwise if it's dimming, clear the light flag.
7944            vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7945        }
7946        return vis;
7947    }
7948
7949    private int updateLightNavigationBarLw(int vis, WindowState opaque,
7950            WindowState opaqueOrDimming) {
7951        final WindowState imeWin = mWindowManagerFuncs.getInputMethodWindowLw();
7952
7953        final WindowState navColorWin;
7954        if (imeWin != null && imeWin.isVisibleLw() && mNavigationBarPosition == NAV_BAR_BOTTOM) {
7955            navColorWin = imeWin;
7956        } else {
7957            navColorWin = opaqueOrDimming;
7958        }
7959
7960        if (navColorWin != null) {
7961            if (navColorWin == opaque) {
7962                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7963                // its light flag.
7964                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7965                vis |= PolicyControl.getSystemUiVisibility(navColorWin, null)
7966                        & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7967            } else if (navColorWin.isDimming() || navColorWin == imeWin) {
7968                // Otherwise if it's dimming or it's the IME window, clear the light flag.
7969                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7970            }
7971        }
7972        return vis;
7973    }
7974
7975    private boolean drawsSystemBarBackground(WindowState win) {
7976        return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
7977    }
7978
7979    private boolean forcesDrawStatusBarBackground(WindowState win) {
7980        return win == null || (win.getAttrs().privateFlags
7981                & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
7982    }
7983
7984    private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
7985        final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
7986        final boolean freeformStackVisible =
7987                mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
7988        final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
7989
7990        // We need to force system bars when the docked stack is visible, when the freeform stack
7991        // is visible but also when we are resizing for the transitions when docked stack
7992        // visibility changes.
7993        mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
7994        final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
7995
7996        // apply translucent bar vis flags
7997        WindowState fullscreenTransWin = isStatusBarKeyguard() && !mKeyguardOccluded
7998                ? mStatusBar
7999                : mTopFullscreenOpaqueWindowState;
8000        vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
8001        vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
8002        final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
8003                mTopDockedOpaqueWindowState, 0, 0);
8004
8005        final boolean fullscreenDrawsStatusBarBackground =
8006                (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
8007                        && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
8008                || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
8009        final boolean dockedDrawsStatusBarBackground =
8010                (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
8011                        && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
8012                || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
8013
8014        // prevent status bar interaction from clearing certain flags
8015        int type = win.getAttrs().type;
8016        boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
8017        if (statusBarHasFocus && !isStatusBarKeyguard()) {
8018            int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
8019                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
8020                    | View.SYSTEM_UI_FLAG_IMMERSIVE
8021                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
8022                    | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
8023            if (mKeyguardOccluded) {
8024                flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
8025            }
8026            vis = (vis & ~flags) | (oldVis & flags);
8027        }
8028
8029        if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
8030            vis |= View.STATUS_BAR_TRANSPARENT;
8031            vis &= ~View.STATUS_BAR_TRANSLUCENT;
8032        } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
8033                || forceOpaqueStatusBar) {
8034            vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
8035        }
8036
8037        vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
8038
8039        // update status bar
8040        boolean immersiveSticky =
8041                (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
8042        final boolean hideStatusBarWM =
8043                mTopFullscreenOpaqueWindowState != null
8044                && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
8045                        & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
8046        final boolean hideStatusBarSysui =
8047                (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
8048        final boolean hideNavBarSysui =
8049                (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
8050
8051        final boolean transientStatusBarAllowed = mStatusBar != null
8052                && (statusBarHasFocus || (!mForceShowSystemBars
8053                        && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
8054
8055        final boolean transientNavBarAllowed = mNavigationBar != null
8056                && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
8057
8058        final long now = SystemClock.uptimeMillis();
8059        final boolean pendingPanic = mPendingPanicGestureUptime != 0
8060                && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
8061        if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
8062            // The user performed the panic gesture recently, we're about to hide the bars,
8063            // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
8064            mPendingPanicGestureUptime = 0;
8065            mStatusBarController.showTransient();
8066            if (!isNavBarEmpty(vis)) {
8067                mNavigationBarController.showTransient();
8068            }
8069        }
8070
8071        final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
8072                && !transientStatusBarAllowed && hideStatusBarSysui;
8073        final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
8074                && !transientNavBarAllowed;
8075        if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
8076            // clear the clearable flags instead
8077            clearClearableFlagsLw();
8078            vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
8079        }
8080
8081        final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
8082        immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
8083        final boolean navAllowedHidden = immersive || immersiveSticky;
8084
8085        if (hideNavBarSysui && !navAllowedHidden
8086                && getWindowLayerLw(win) > getWindowLayerFromTypeLw(TYPE_INPUT_CONSUMER)) {
8087            // We can't hide the navbar from this window otherwise the input consumer would not get
8088            // the input events.
8089            vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
8090        }
8091
8092        vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
8093
8094        // update navigation bar
8095        boolean oldImmersiveMode = isImmersiveMode(oldVis);
8096        boolean newImmersiveMode = isImmersiveMode(vis);
8097        if (win != null && oldImmersiveMode != newImmersiveMode) {
8098            final String pkg = win.getOwningPackage();
8099            mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
8100                    isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility()));
8101        }
8102
8103        vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
8104
8105        vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState,
8106                mTopFullscreenOpaqueOrDimmingWindowState);
8107
8108        return vis;
8109    }
8110
8111    /**
8112     * @return the current visibility flags with the nav-bar opacity related flags toggled based
8113     *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
8114     */
8115    private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
8116            boolean freeformStackVisible, boolean isDockedDividerResizing) {
8117        if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
8118            if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
8119                visibility = setNavBarOpaqueFlag(visibility);
8120            }
8121        } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
8122            if (isDockedDividerResizing) {
8123                visibility = setNavBarOpaqueFlag(visibility);
8124            } else if (freeformStackVisible) {
8125                visibility = setNavBarTranslucentFlag(visibility);
8126            } else {
8127                visibility = setNavBarOpaqueFlag(visibility);
8128            }
8129        }
8130
8131        if (!areTranslucentBarsAllowed()) {
8132            visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
8133        }
8134        return visibility;
8135    }
8136
8137    private int setNavBarOpaqueFlag(int visibility) {
8138        return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
8139    }
8140
8141    private int setNavBarTranslucentFlag(int visibility) {
8142        visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
8143        return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
8144    }
8145
8146    private void clearClearableFlagsLw() {
8147        int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
8148        if (newVal != mResettingSystemUiFlags) {
8149            mResettingSystemUiFlags = newVal;
8150            mWindowManagerFuncs.reevaluateStatusBarVisibility();
8151        }
8152    }
8153
8154    private boolean isImmersiveMode(int vis) {
8155        final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
8156        return mNavigationBar != null
8157                && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
8158                && (vis & flags) != 0
8159                && canHideNavigationBar();
8160    }
8161
8162    private static boolean isNavBarEmpty(int systemUiFlags) {
8163        final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
8164                | View.STATUS_BAR_DISABLE_BACK
8165                | View.STATUS_BAR_DISABLE_RECENT);
8166
8167        return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
8168    }
8169
8170    /**
8171     * @return whether the navigation or status bar can be made translucent
8172     *
8173     * This should return true unless touch exploration is not enabled or
8174     * R.boolean.config_enableTranslucentDecor is false.
8175     */
8176    private boolean areTranslucentBarsAllowed() {
8177        return mTranslucentDecorEnabled;
8178    }
8179
8180    // Use this instead of checking config_showNavigationBar so that it can be consistently
8181    // overridden by qemu.hw.mainkeys in the emulator.
8182    @Override
8183    public boolean hasNavigationBar() {
8184        return mHasNavigationBar;
8185    }
8186
8187    @Override
8188    public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
8189        mLastInputMethodWindow = ime;
8190        mLastInputMethodTargetWindow = target;
8191    }
8192
8193    @Override
8194    public void setDismissImeOnBackKeyPressed(boolean newValue) {
8195        mDismissImeOnBackKeyPressed = newValue;
8196    }
8197
8198    @Override
8199    public int getInputMethodWindowVisibleHeightLw() {
8200        return mDockBottom - mCurBottom;
8201    }
8202
8203    @Override
8204    public void setCurrentUserLw(int newUserId) {
8205        mCurrentUserId = newUserId;
8206        if (mKeyguardDelegate != null) {
8207            mKeyguardDelegate.setCurrentUser(newUserId);
8208        }
8209        if (mAccessibilityShortcutController != null) {
8210            mAccessibilityShortcutController.setCurrentUser(newUserId);
8211        }
8212        StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
8213        if (statusBar != null) {
8214            statusBar.setCurrentUser(newUserId);
8215        }
8216        setLastInputMethodWindowLw(null, null);
8217    }
8218
8219    @Override
8220    public void setSwitchingUser(boolean switching) {
8221        mKeyguardDelegate.setSwitchingUser(switching);
8222    }
8223
8224    @Override
8225    public boolean canMagnifyWindow(int windowType) {
8226        switch (windowType) {
8227            case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
8228            case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
8229            case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
8230            case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
8231                return false;
8232            }
8233        }
8234        return true;
8235    }
8236
8237    @Override
8238    public boolean isTopLevelWindow(int windowType) {
8239        if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
8240                && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
8241            return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
8242        }
8243        return true;
8244    }
8245
8246    @Override
8247    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
8248        // For the upside down rotation we don't rotate seamlessly as the navigation
8249        // bar moves position.
8250        // Note most apps (using orientation:sensor or user as opposed to fullSensor)
8251        // will not enter the reverse portrait orientation, so actually the
8252        // orientation won't change at all.
8253        if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
8254            return false;
8255        }
8256        // If the navigation bar can't change sides, then it will
8257        // jump when we change orientations and we don't rotate
8258        // seamlessly.
8259        if (!mNavigationBarCanMove) {
8260            return false;
8261        }
8262        int delta = newRotation - oldRotation;
8263        if (delta < 0) delta += 4;
8264        // Likewise we don't rotate seamlessly for 180 degree rotations
8265        // in this case the surfaces never resize, and our logic to
8266        // revert the transformations on size change will fail. We could
8267        // fix this in the future with the "tagged" frames idea.
8268        if (delta == Surface.ROTATION_180) {
8269            return false;
8270        }
8271
8272        final WindowState w = mTopFullscreenOpaqueWindowState;
8273        if (w != mFocusedWindow) {
8274            return false;
8275        }
8276
8277        // We only enable seamless rotation if the top window has requested
8278        // it and is in the fullscreen opaque state. Seamless rotation
8279        // requires freezing various Surface states and won't work well
8280        // with animations, so we disable it in the animation case for now.
8281        if (w != null && !w.isAnimatingLw() &&
8282                ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) ||
8283                        (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) {
8284            return true;
8285        }
8286        return false;
8287    }
8288
8289    @Override
8290    public void dump(String prefix, PrintWriter pw, String[] args) {
8291        pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
8292                pw.print(" mSystemReady="); pw.print(mSystemReady);
8293                pw.print(" mSystemBooted="); pw.println(mSystemBooted);
8294        pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
8295                pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
8296                pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
8297                pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
8298        if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
8299                || mForceClearedSystemUiFlags != 0) {
8300            pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
8301                    pw.print(Integer.toHexString(mLastSystemUiFlags));
8302                    pw.print(" mResettingSystemUiFlags=0x");
8303                    pw.print(Integer.toHexString(mResettingSystemUiFlags));
8304                    pw.print(" mForceClearedSystemUiFlags=0x");
8305                    pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
8306        }
8307        if (mLastFocusNeedsMenu) {
8308            pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
8309                    pw.println(mLastFocusNeedsMenu);
8310        }
8311        pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
8312                pw.println(mWakeGestureEnabledSetting);
8313
8314        pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
8315        pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
8316                pw.print(" mDockMode="); pw.print(mDockMode);
8317                pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
8318                pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
8319                pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
8320        pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
8321                pw.print(" mUserRotation="); pw.print(mUserRotation);
8322                pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
8323        pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
8324        pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
8325                pw.print(mCarDockEnablesAccelerometer);
8326                pw.print(" mDeskDockEnablesAccelerometer=");
8327                pw.println(mDeskDockEnablesAccelerometer);
8328        pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
8329                pw.print(mLidKeyboardAccessibility);
8330                pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
8331                pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
8332                pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
8333        pw.print(prefix);
8334                pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
8335        pw.print(prefix);
8336                pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
8337                pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
8338        pw.print(prefix);
8339                pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
8340                pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
8341        pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
8342        pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
8343        pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
8344                pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
8345        pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
8346                pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
8347        pw.print(prefix); pw.print("mOrientationSensorEnabled=");
8348                pw.println(mOrientationSensorEnabled);
8349        pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
8350                pw.print(","); pw.print(mOverscanScreenTop);
8351                pw.print(") "); pw.print(mOverscanScreenWidth);
8352                pw.print("x"); pw.println(mOverscanScreenHeight);
8353        if (mOverscanLeft != 0 || mOverscanTop != 0
8354                || mOverscanRight != 0 || mOverscanBottom != 0) {
8355            pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
8356                    pw.print(" top="); pw.print(mOverscanTop);
8357                    pw.print(" right="); pw.print(mOverscanRight);
8358                    pw.print(" bottom="); pw.println(mOverscanBottom);
8359        }
8360        pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
8361                pw.print(mRestrictedOverscanScreenLeft);
8362                pw.print(","); pw.print(mRestrictedOverscanScreenTop);
8363                pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
8364                pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
8365        pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
8366                pw.print(","); pw.print(mUnrestrictedScreenTop);
8367                pw.print(") "); pw.print(mUnrestrictedScreenWidth);
8368                pw.print("x"); pw.println(mUnrestrictedScreenHeight);
8369        pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
8370                pw.print(","); pw.print(mRestrictedScreenTop);
8371                pw.print(") "); pw.print(mRestrictedScreenWidth);
8372                pw.print("x"); pw.println(mRestrictedScreenHeight);
8373        pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
8374                pw.print(","); pw.print(mStableFullscreenTop);
8375                pw.print(")-("); pw.print(mStableFullscreenRight);
8376                pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
8377        pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
8378                pw.print(","); pw.print(mStableTop);
8379                pw.print(")-("); pw.print(mStableRight);
8380                pw.print(","); pw.print(mStableBottom); pw.println(")");
8381        pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
8382                pw.print(","); pw.print(mSystemTop);
8383                pw.print(")-("); pw.print(mSystemRight);
8384                pw.print(","); pw.print(mSystemBottom); pw.println(")");
8385        pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
8386                pw.print(","); pw.print(mCurTop);
8387                pw.print(")-("); pw.print(mCurRight);
8388                pw.print(","); pw.print(mCurBottom); pw.println(")");
8389        pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
8390                pw.print(","); pw.print(mContentTop);
8391                pw.print(")-("); pw.print(mContentRight);
8392                pw.print(","); pw.print(mContentBottom); pw.println(")");
8393        pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft);
8394                pw.print(","); pw.print(mVoiceContentTop);
8395                pw.print(")-("); pw.print(mVoiceContentRight);
8396                pw.print(","); pw.print(mVoiceContentBottom); pw.println(")");
8397        pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
8398                pw.print(","); pw.print(mDockTop);
8399                pw.print(")-("); pw.print(mDockRight);
8400                pw.print(","); pw.print(mDockBottom); pw.println(")");
8401        pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
8402                pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
8403        pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
8404                pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
8405                pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
8406        if (mLastInputMethodWindow != null) {
8407            pw.print(prefix); pw.print("mLastInputMethodWindow=");
8408                    pw.println(mLastInputMethodWindow);
8409        }
8410        if (mLastInputMethodTargetWindow != null) {
8411            pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
8412                    pw.println(mLastInputMethodTargetWindow);
8413        }
8414        pw.print(prefix); pw.print("mDismissImeOnBackKeyPressed=");
8415                pw.println(mDismissImeOnBackKeyPressed);
8416        if (mStatusBar != null) {
8417            pw.print(prefix); pw.print("mStatusBar=");
8418                    pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
8419                    pw.println(isStatusBarKeyguard());
8420        }
8421        if (mNavigationBar != null) {
8422            pw.print(prefix); pw.print("mNavigationBar=");
8423                    pw.println(mNavigationBar);
8424        }
8425        if (mFocusedWindow != null) {
8426            pw.print(prefix); pw.print("mFocusedWindow=");
8427                    pw.println(mFocusedWindow);
8428        }
8429        if (mFocusedApp != null) {
8430            pw.print(prefix); pw.print("mFocusedApp=");
8431                    pw.println(mFocusedApp);
8432        }
8433        if (mTopFullscreenOpaqueWindowState != null) {
8434            pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
8435                    pw.println(mTopFullscreenOpaqueWindowState);
8436        }
8437        if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
8438            pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
8439                    pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
8440        }
8441        if (mForcingShowNavBar) {
8442            pw.print(prefix); pw.print("mForcingShowNavBar=");
8443                    pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
8444                    pw.println(mForcingShowNavBarLayer);
8445        }
8446        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
8447                pw.print(" mKeyguardOccluded="); pw.println(mKeyguardOccluded);
8448                pw.print(" mKeyguardOccludedChanged="); pw.println(mKeyguardOccludedChanged);
8449                pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded);
8450        pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
8451                pw.print(" mForceStatusBarFromKeyguard=");
8452                pw.println(mForceStatusBarFromKeyguard);
8453        pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
8454        pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
8455                pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
8456                pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
8457        pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
8458                pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
8459                pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior);
8460                pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
8461        pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
8462                pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
8463        pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
8464                pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
8465        pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
8466                pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
8467        pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
8468        if (mHasFeatureLeanback) {
8469            pw.print(prefix);
8470            pw.print("mAccessibilityTvKey1Pressed="); pw.println(mAccessibilityTvKey1Pressed);
8471            pw.print(prefix);
8472            pw.print("mAccessibilityTvKey2Pressed="); pw.println(mAccessibilityTvKey2Pressed);
8473            pw.print(prefix);
8474            pw.print("mAccessibilityTvScheduled="); pw.println(mAccessibilityTvScheduled);
8475        }
8476
8477        mGlobalKeyManager.dump(prefix, pw);
8478        mStatusBarController.dump(pw, prefix);
8479        mNavigationBarController.dump(pw, prefix);
8480        PolicyControl.dump(prefix, pw);
8481
8482        if (mWakeGestureListener != null) {
8483            mWakeGestureListener.dump(pw, prefix);
8484        }
8485        if (mOrientationListener != null) {
8486            mOrientationListener.dump(pw, prefix);
8487        }
8488        if (mBurnInProtectionHelper != null) {
8489            mBurnInProtectionHelper.dump(prefix, pw);
8490        }
8491        if (mKeyguardDelegate != null) {
8492            mKeyguardDelegate.dump(prefix, pw);
8493        }
8494    }
8495}
8496