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