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