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