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