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