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