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