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