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