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