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