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