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