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