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