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