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