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