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