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