PhoneWindowManager.java revision a58589bdc168ad5a06dac3608712d3f9dfbc6d27
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 && mStatusBarController.isTransientShowing()) {
5489                    mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
5490                            mLastSystemUiFlags, mLastSystemUiFlags);
5491                }
5492                if (statusBarExpanded && mNavigationBar != null) {
5493                    if (mNavigationBarController.setBarShowingLw(true)) {
5494                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5495                    }
5496                }
5497            } else if (mTopFullscreenOpaqueWindowState != null) {
5498                final int fl = PolicyControl.getWindowFlags(null, lp);
5499                if (localLOGV) {
5500                    Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
5501                            + " shown position: "
5502                            + mTopFullscreenOpaqueWindowState.getShownPositionLw());
5503                    Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
5504                            + " lp.flags=0x" + Integer.toHexString(fl));
5505                }
5506                topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
5507                        || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
5508                // The subtle difference between the window for mTopFullscreenOpaqueWindowState
5509                // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
5510                // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
5511                // case though.
5512                if (mStatusBarController.isTransientShowing()) {
5513                    if (mStatusBarController.setBarShowingLw(true)) {
5514                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5515                    }
5516                } else if (topIsFullscreen
5517                        && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)
5518                        && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) {
5519                    if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
5520                    if (mStatusBarController.setBarShowingLw(false)) {
5521                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5522                    } else {
5523                        if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
5524                    }
5525                } else {
5526                    if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
5527                    if (mStatusBarController.setBarShowingLw(true)) {
5528                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5529                    }
5530                }
5531            }
5532        }
5533
5534        if (mTopIsFullscreen != topIsFullscreen) {
5535            if (!topIsFullscreen) {
5536                // Force another layout when status bar becomes fully shown.
5537                changes |= FINISH_LAYOUT_REDO_LAYOUT;
5538            }
5539            mTopIsFullscreen = topIsFullscreen;
5540        }
5541
5542        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5543            // If the navigation bar has been hidden or shown, we need to do another
5544            // layout pass to update that window.
5545            changes |= FINISH_LAYOUT_REDO_LAYOUT;
5546        }
5547
5548        if (mShowingDream != mLastShowingDream) {
5549            mLastShowingDream = mShowingDream;
5550            mWindowManagerFuncs.notifyShowingDreamChanged();
5551        }
5552
5553        // update since mAllowLockscreenWhenOn might have changed
5554        updateLockScreenTimeout();
5555        return changes;
5556    }
5557
5558    /**
5559     * Updates the occluded state of the Keyguard.
5560     *
5561     * @return Whether the flags have changed and we have to redo the layout.
5562     */
5563    private boolean setKeyguardOccludedLw(boolean isOccluded, boolean force) {
5564        if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded);
5565        final boolean wasOccluded = mKeyguardOccluded;
5566        final boolean showing = mKeyguardDelegate.isShowing();
5567        final boolean changed = wasOccluded != isOccluded || force;
5568        if (!isOccluded && changed && showing) {
5569            mKeyguardOccluded = false;
5570            mKeyguardDelegate.setOccluded(false, true /* animate */);
5571            if (mStatusBar != null) {
5572                mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
5573                if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
5574                    mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5575                }
5576            }
5577            return true;
5578        } else if (isOccluded && changed && showing) {
5579            mKeyguardOccluded = true;
5580            mKeyguardDelegate.setOccluded(true, false /* animate */);
5581            if (mStatusBar != null) {
5582                mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
5583                mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
5584            }
5585            return true;
5586        } else if (changed) {
5587            mKeyguardOccluded = isOccluded;
5588            mKeyguardDelegate.setOccluded(isOccluded, false /* animate */);
5589            return false;
5590        } else {
5591            return false;
5592        }
5593    }
5594
5595    private boolean isStatusBarKeyguard() {
5596        return mStatusBar != null
5597                && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
5598    }
5599
5600    @Override
5601    public boolean allowAppAnimationsLw() {
5602        if (mShowingDream) {
5603            // If keyguard or dreams is currently visible, no reason to animate behind it.
5604            return false;
5605        }
5606        return true;
5607    }
5608
5609    @Override
5610    public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
5611        mFocusedWindow = newFocus;
5612        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5613            // If the navigation bar has been hidden or shown, we need to do another
5614            // layout pass to update that window.
5615            return FINISH_LAYOUT_REDO_LAYOUT;
5616        }
5617        return 0;
5618    }
5619
5620    /** {@inheritDoc} */
5621    @Override
5622    public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
5623        // lid changed state
5624        final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
5625        if (newLidState == mLidState) {
5626            return;
5627        }
5628
5629        mLidState = newLidState;
5630        applyLidSwitchState();
5631        updateRotation(true);
5632
5633        if (lidOpen) {
5634            wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
5635                    "android.policy:LID");
5636        } else if (!mLidControlsSleep) {
5637            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
5638        }
5639    }
5640
5641    @Override
5642    public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
5643        int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
5644        if (mCameraLensCoverState == lensCoverState) {
5645            return;
5646        }
5647        if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
5648                lensCoverState == CAMERA_LENS_UNCOVERED) {
5649            Intent intent;
5650            final boolean keyguardActive = mKeyguardDelegate == null ? false :
5651                    mKeyguardDelegate.isShowing();
5652            if (keyguardActive) {
5653                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
5654            } else {
5655                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
5656            }
5657            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
5658                    "android.policy:CAMERA_COVER");
5659            startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
5660        }
5661        mCameraLensCoverState = lensCoverState;
5662    }
5663
5664    void setHdmiPlugged(boolean plugged) {
5665        if (mHdmiPlugged != plugged) {
5666            mHdmiPlugged = plugged;
5667            updateRotation(true, true);
5668            Intent intent = new Intent(ACTION_HDMI_PLUGGED);
5669            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
5670            intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
5671            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
5672        }
5673    }
5674
5675    void initializeHdmiState() {
5676        boolean plugged = false;
5677        // watch for HDMI plug messages if the hdmi switch exists
5678        if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
5679            mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
5680
5681            final String filename = "/sys/class/switch/hdmi/state";
5682            FileReader reader = null;
5683            try {
5684                reader = new FileReader(filename);
5685                char[] buf = new char[15];
5686                int n = reader.read(buf);
5687                if (n > 1) {
5688                    plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
5689                }
5690            } catch (IOException ex) {
5691                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5692            } catch (NumberFormatException ex) {
5693                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5694            } finally {
5695                if (reader != null) {
5696                    try {
5697                        reader.close();
5698                    } catch (IOException ex) {
5699                    }
5700                }
5701            }
5702        }
5703        // This dance forces the code in setHdmiPlugged to run.
5704        // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
5705        mHdmiPlugged = !plugged;
5706        setHdmiPlugged(!mHdmiPlugged);
5707    }
5708
5709    final Object mScreenshotLock = new Object();
5710    ServiceConnection mScreenshotConnection = null;
5711
5712    final Runnable mScreenshotTimeout = new Runnable() {
5713        @Override public void run() {
5714            synchronized (mScreenshotLock) {
5715                if (mScreenshotConnection != null) {
5716                    mContext.unbindService(mScreenshotConnection);
5717                    mScreenshotConnection = null;
5718                    notifyScreenshotError();
5719                }
5720            }
5721        }
5722    };
5723
5724    // Assume this is called from the Handler thread.
5725    private void takeScreenshot(final int screenshotType) {
5726        synchronized (mScreenshotLock) {
5727            if (mScreenshotConnection != null) {
5728                return;
5729            }
5730            final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
5731                    SYSUI_SCREENSHOT_SERVICE);
5732            final Intent serviceIntent = new Intent();
5733            serviceIntent.setComponent(serviceComponent);
5734            ServiceConnection conn = new ServiceConnection() {
5735                @Override
5736                public void onServiceConnected(ComponentName name, IBinder service) {
5737                    synchronized (mScreenshotLock) {
5738                        if (mScreenshotConnection != this) {
5739                            return;
5740                        }
5741                        Messenger messenger = new Messenger(service);
5742                        Message msg = Message.obtain(null, screenshotType);
5743                        final ServiceConnection myConn = this;
5744                        Handler h = new Handler(mHandler.getLooper()) {
5745                            @Override
5746                            public void handleMessage(Message msg) {
5747                                synchronized (mScreenshotLock) {
5748                                    if (mScreenshotConnection == myConn) {
5749                                        mContext.unbindService(mScreenshotConnection);
5750                                        mScreenshotConnection = null;
5751                                        mHandler.removeCallbacks(mScreenshotTimeout);
5752                                    }
5753                                }
5754                            }
5755                        };
5756                        msg.replyTo = new Messenger(h);
5757                        msg.arg1 = msg.arg2 = 0;
5758                        if (mStatusBar != null && mStatusBar.isVisibleLw())
5759                            msg.arg1 = 1;
5760                        if (mNavigationBar != null && mNavigationBar.isVisibleLw())
5761                            msg.arg2 = 1;
5762                        try {
5763                            messenger.send(msg);
5764                        } catch (RemoteException e) {
5765                        }
5766                    }
5767                }
5768
5769                @Override
5770                public void onServiceDisconnected(ComponentName name) {
5771                    synchronized (mScreenshotLock) {
5772                        if (mScreenshotConnection != null) {
5773                            mContext.unbindService(mScreenshotConnection);
5774                            mScreenshotConnection = null;
5775                            mHandler.removeCallbacks(mScreenshotTimeout);
5776                            notifyScreenshotError();
5777                        }
5778                    }
5779                }
5780            };
5781            if (mContext.bindServiceAsUser(serviceIntent, conn,
5782                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
5783                    UserHandle.CURRENT)) {
5784                mScreenshotConnection = conn;
5785                mHandler.postDelayed(mScreenshotTimeout, 10000);
5786            }
5787        }
5788    }
5789
5790    /**
5791     * Notifies the screenshot service to show an error.
5792     */
5793    private void notifyScreenshotError() {
5794        // If the service process is killed, then ask it to clean up after itself
5795        final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
5796                SYSUI_SCREENSHOT_ERROR_RECEIVER);
5797        Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
5798        errorIntent.setComponent(errorComponent);
5799        errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
5800                Intent.FLAG_RECEIVER_FOREGROUND);
5801        mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT);
5802    }
5803
5804    /** {@inheritDoc} */
5805    @Override
5806    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
5807        if (!mSystemBooted) {
5808            // If we have not yet booted, don't let key events do anything.
5809            return 0;
5810        }
5811
5812        final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
5813        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
5814        final boolean canceled = event.isCanceled();
5815        final int keyCode = event.getKeyCode();
5816
5817        final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
5818
5819        // If screen is off then we treat the case where the keyguard is open but hidden
5820        // the same as if it were open and in front.
5821        // This will prevent any keys other than the power button from waking the screen
5822        // when the keyguard is hidden by another activity.
5823        final boolean keyguardActive = (mKeyguardDelegate == null ? false :
5824                                            (interactive ?
5825                                                isKeyguardShowingAndNotOccluded() :
5826                                                mKeyguardDelegate.isShowing()));
5827
5828        if (DEBUG_INPUT) {
5829            Log.d(TAG, "interceptKeyTq keycode=" + keyCode
5830                    + " interactive=" + interactive + " keyguardActive=" + keyguardActive
5831                    + " policyFlags=" + Integer.toHexString(policyFlags));
5832        }
5833
5834        // Basic policy based on interactive state.
5835        int result;
5836        boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
5837                || event.isWakeKey();
5838        if (interactive || (isInjected && !isWakeKey)) {
5839            // When the device is interactive or the key is injected pass the
5840            // key to the application.
5841            result = ACTION_PASS_TO_USER;
5842            isWakeKey = false;
5843
5844            if (interactive) {
5845                // If the screen is awake, but the button pressed was the one that woke the device
5846                // then don't pass it to the application
5847                if (keyCode == mPendingWakeKey && !down) {
5848                    result = 0;
5849                }
5850                // Reset the pending key
5851                mPendingWakeKey = PENDING_KEY_NULL;
5852            }
5853        } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
5854            // If we're currently dozing with the screen on and the keyguard showing, pass the key
5855            // to the application but preserve its wake key status to make sure we still move
5856            // from dozing to fully interactive if we would normally go from off to fully
5857            // interactive.
5858            result = ACTION_PASS_TO_USER;
5859            // Since we're dispatching the input, reset the pending key
5860            mPendingWakeKey = PENDING_KEY_NULL;
5861        } else {
5862            // When the screen is off and the key is not injected, determine whether
5863            // to wake the device but don't pass the key to the application.
5864            result = 0;
5865            if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
5866                isWakeKey = false;
5867            }
5868            // Cache the wake key on down event so we can also avoid sending the up event to the app
5869            if (isWakeKey && down) {
5870                mPendingWakeKey = keyCode;
5871            }
5872        }
5873
5874        // If the key would be handled globally, just return the result, don't worry about special
5875        // key processing.
5876        if (isValidGlobalKey(keyCode)
5877                && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
5878            if (isWakeKey) {
5879                wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5880            }
5881            return result;
5882        }
5883
5884        boolean useHapticFeedback = down
5885                && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
5886                && event.getRepeatCount() == 0;
5887
5888        // Handle special keys.
5889        switch (keyCode) {
5890            case KeyEvent.KEYCODE_BACK: {
5891                if (down) {
5892                    interceptBackKeyDown();
5893                } else {
5894                    boolean handled = interceptBackKeyUp(event);
5895
5896                    // Don't pass back press to app if we've already handled it via long press
5897                    if (handled) {
5898                        result &= ~ACTION_PASS_TO_USER;
5899                    }
5900                }
5901                break;
5902            }
5903
5904            case KeyEvent.KEYCODE_VOLUME_DOWN:
5905            case KeyEvent.KEYCODE_VOLUME_UP:
5906            case KeyEvent.KEYCODE_VOLUME_MUTE: {
5907                if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
5908                    if (down) {
5909                        if (interactive && !mScreenshotChordVolumeDownKeyTriggered
5910                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5911                            mScreenshotChordVolumeDownKeyTriggered = true;
5912                            mScreenshotChordVolumeDownKeyTime = event.getDownTime();
5913                            mScreenshotChordVolumeDownKeyConsumed = false;
5914                            cancelPendingPowerKeyAction();
5915                            interceptScreenshotChord();
5916                            interceptAccessibilityShortcutChord();
5917                        }
5918                    } else {
5919                        mScreenshotChordVolumeDownKeyTriggered = false;
5920                        cancelPendingScreenshotChordAction();
5921                        cancelPendingAccessibilityShortcutAction();
5922                    }
5923                } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
5924                    if (down) {
5925                        if (interactive && !mA11yShortcutChordVolumeUpKeyTriggered
5926                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5927                            mA11yShortcutChordVolumeUpKeyTriggered = true;
5928                            mA11yShortcutChordVolumeUpKeyTime = event.getDownTime();
5929                            mA11yShortcutChordVolumeUpKeyConsumed = false;
5930                            cancelPendingPowerKeyAction();
5931                            cancelPendingScreenshotChordAction();
5932                            interceptAccessibilityShortcutChord();
5933                        }
5934                    } else {
5935                        mA11yShortcutChordVolumeUpKeyTriggered = false;
5936                        cancelPendingScreenshotChordAction();
5937                        cancelPendingAccessibilityShortcutAction();
5938                    }
5939                }
5940                if (down) {
5941                    TelecomManager telecomManager = getTelecommService();
5942                    if (telecomManager != null) {
5943                        if (telecomManager.isRinging()) {
5944                            // If an incoming call is ringing, either VOLUME key means
5945                            // "silence ringer".  We handle these keys here, rather than
5946                            // in the InCallScreen, to make sure we'll respond to them
5947                            // even if the InCallScreen hasn't come to the foreground yet.
5948                            // Look for the DOWN event here, to agree with the "fallback"
5949                            // behavior in the InCallScreen.
5950                            Log.i(TAG, "interceptKeyBeforeQueueing:"
5951                                  + " VOLUME key-down while ringing: Silence ringer!");
5952
5953                            // Silence the ringer.  (It's safe to call this
5954                            // even if the ringer has already been silenced.)
5955                            telecomManager.silenceRinger();
5956
5957                            // And *don't* pass this key thru to the current activity
5958                            // (which is probably the InCallScreen.)
5959                            result &= ~ACTION_PASS_TO_USER;
5960                            break;
5961                        }
5962                        if (telecomManager.isInCall()
5963                                && (result & ACTION_PASS_TO_USER) == 0) {
5964                            // If we are in call but we decided not to pass the key to
5965                            // the application, just pass it to the session service.
5966                            MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
5967                                    event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
5968                            break;
5969                        }
5970                    }
5971                }
5972                if (mUseTvRouting || mHandleVolumeKeysInWM) {
5973                    // Defer special key handlings to
5974                    // {@link interceptKeyBeforeDispatching()}.
5975                    result |= ACTION_PASS_TO_USER;
5976                } else if ((result & ACTION_PASS_TO_USER) == 0) {
5977                    // If we aren't passing to the user and no one else
5978                    // handled it send it to the session manager to
5979                    // figure out.
5980                    MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
5981                            event, AudioManager.USE_DEFAULT_STREAM_TYPE, true);
5982                }
5983                break;
5984            }
5985
5986            case KeyEvent.KEYCODE_ENDCALL: {
5987                result &= ~ACTION_PASS_TO_USER;
5988                if (down) {
5989                    TelecomManager telecomManager = getTelecommService();
5990                    boolean hungUp = false;
5991                    if (telecomManager != null) {
5992                        hungUp = telecomManager.endCall();
5993                    }
5994                    if (interactive && !hungUp) {
5995                        mEndCallKeyHandled = false;
5996                        mHandler.postDelayed(mEndCallLongPress,
5997                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
5998                    } else {
5999                        mEndCallKeyHandled = true;
6000                    }
6001                } else {
6002                    if (!mEndCallKeyHandled) {
6003                        mHandler.removeCallbacks(mEndCallLongPress);
6004                        if (!canceled) {
6005                            if ((mEndcallBehavior
6006                                    & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
6007                                if (goHome()) {
6008                                    break;
6009                                }
6010                            }
6011                            if ((mEndcallBehavior
6012                                    & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
6013                                mPowerManager.goToSleep(event.getEventTime(),
6014                                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
6015                                isWakeKey = false;
6016                            }
6017                        }
6018                    }
6019                }
6020                break;
6021            }
6022
6023            case KeyEvent.KEYCODE_POWER: {
6024                // Any activity on the power button stops the accessibility shortcut
6025                cancelPendingAccessibilityShortcutAction();
6026                result &= ~ACTION_PASS_TO_USER;
6027                isWakeKey = false; // wake-up will be handled separately
6028                if (down) {
6029                    interceptPowerKeyDown(event, interactive);
6030                } else {
6031                    interceptPowerKeyUp(event, interactive, canceled);
6032                }
6033                break;
6034            }
6035
6036            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
6037                // fall through
6038            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
6039                // fall through
6040            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
6041                // fall through
6042            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
6043                result &= ~ACTION_PASS_TO_USER;
6044                interceptSystemNavigationKey(event);
6045                break;
6046            }
6047
6048            case KeyEvent.KEYCODE_SLEEP: {
6049                result &= ~ACTION_PASS_TO_USER;
6050                isWakeKey = false;
6051                if (!mPowerManager.isInteractive()) {
6052                    useHapticFeedback = false; // suppress feedback if already non-interactive
6053                }
6054                if (down) {
6055                    sleepPress(event.getEventTime());
6056                } else {
6057                    sleepRelease(event.getEventTime());
6058                }
6059                break;
6060            }
6061
6062            case KeyEvent.KEYCODE_SOFT_SLEEP: {
6063                result &= ~ACTION_PASS_TO_USER;
6064                isWakeKey = false;
6065                if (!down) {
6066                    mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
6067                }
6068                break;
6069            }
6070
6071            case KeyEvent.KEYCODE_WAKEUP: {
6072                result &= ~ACTION_PASS_TO_USER;
6073                isWakeKey = true;
6074                break;
6075            }
6076
6077            case KeyEvent.KEYCODE_MEDIA_PLAY:
6078            case KeyEvent.KEYCODE_MEDIA_PAUSE:
6079            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6080            case KeyEvent.KEYCODE_HEADSETHOOK:
6081            case KeyEvent.KEYCODE_MUTE:
6082            case KeyEvent.KEYCODE_MEDIA_STOP:
6083            case KeyEvent.KEYCODE_MEDIA_NEXT:
6084            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6085            case KeyEvent.KEYCODE_MEDIA_REWIND:
6086            case KeyEvent.KEYCODE_MEDIA_RECORD:
6087            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6088            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
6089                if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
6090                    // If the global session is active pass all media keys to it
6091                    // instead of the active window.
6092                    result &= ~ACTION_PASS_TO_USER;
6093                }
6094                if ((result & ACTION_PASS_TO_USER) == 0) {
6095                    // Only do this if we would otherwise not pass it to the user. In that
6096                    // case, the PhoneWindow class will do the same thing, except it will
6097                    // only do it if the showing app doesn't process the key on its own.
6098                    // Note that we need to make a copy of the key event here because the
6099                    // original key event will be recycled when we return.
6100                    mBroadcastWakeLock.acquire();
6101                    Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
6102                            new KeyEvent(event));
6103                    msg.setAsynchronous(true);
6104                    msg.sendToTarget();
6105                }
6106                break;
6107            }
6108
6109            case KeyEvent.KEYCODE_CALL: {
6110                if (down) {
6111                    TelecomManager telecomManager = getTelecommService();
6112                    if (telecomManager != null) {
6113                        if (telecomManager.isRinging()) {
6114                            Log.i(TAG, "interceptKeyBeforeQueueing:"
6115                                  + " CALL key-down while ringing: Answer the call!");
6116                            telecomManager.acceptRingingCall();
6117
6118                            // And *don't* pass this key thru to the current activity
6119                            // (which is presumably the InCallScreen.)
6120                            result &= ~ACTION_PASS_TO_USER;
6121                        }
6122                    }
6123                }
6124                break;
6125            }
6126            case KeyEvent.KEYCODE_VOICE_ASSIST: {
6127                // Only do this if we would otherwise not pass it to the user. In that case,
6128                // interceptKeyBeforeDispatching would apply a similar but different policy in
6129                // order to invoke voice assist actions. Note that we need to make a copy of the
6130                // key event here because the original key event will be recycled when we return.
6131                if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
6132                    mBroadcastWakeLock.acquire();
6133                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
6134                            keyguardActive ? 1 : 0, 0);
6135                    msg.setAsynchronous(true);
6136                    msg.sendToTarget();
6137                }
6138                break;
6139            }
6140            case KeyEvent.KEYCODE_WINDOW: {
6141                if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
6142                    if (mPictureInPictureVisible) {
6143                        // Consumes the key only if picture-in-picture is visible to show
6144                        // picture-in-picture control menu. This gives a chance to the foreground
6145                        // activity to customize PIP key behavior.
6146                        if (!down) {
6147                            showPictureInPictureMenu(event);
6148                        }
6149                        result &= ~ACTION_PASS_TO_USER;
6150                    }
6151                }
6152                break;
6153            }
6154        }
6155
6156        if (useHapticFeedback) {
6157            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
6158        }
6159
6160        if (isWakeKey) {
6161            wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
6162        }
6163
6164        return result;
6165    }
6166
6167    /**
6168     * Handle statusbar expansion events.
6169     * @param event
6170     */
6171    private void interceptSystemNavigationKey(KeyEvent event) {
6172        if (event.getAction() == KeyEvent.ACTION_UP) {
6173            if (!mAccessibilityManager.isEnabled()
6174                    || !mAccessibilityManager.sendFingerprintGesture(event.getKeyCode())) {
6175                if (areSystemNavigationKeysEnabled()) {
6176                    IStatusBarService sbar = getStatusBarService();
6177                    if (sbar != null) {
6178                        try {
6179                            sbar.handleSystemNavigationKey(event.getKeyCode());
6180                        } catch (RemoteException e1) {
6181                            // oops, no statusbar. Ignore event.
6182                        }
6183                    }
6184                }
6185            }
6186        }
6187    }
6188
6189    /**
6190     * Returns true if the key can have global actions attached to it.
6191     * We reserve all power management keys for the system since they require
6192     * very careful handling.
6193     */
6194    private static boolean isValidGlobalKey(int keyCode) {
6195        switch (keyCode) {
6196            case KeyEvent.KEYCODE_POWER:
6197            case KeyEvent.KEYCODE_WAKEUP:
6198            case KeyEvent.KEYCODE_SLEEP:
6199                return false;
6200            default:
6201                return true;
6202        }
6203    }
6204
6205    /**
6206     * When the screen is off we ignore some keys that might otherwise typically
6207     * be considered wake keys.  We filter them out here.
6208     *
6209     * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
6210     * is always considered a wake key.
6211     */
6212    private boolean isWakeKeyWhenScreenOff(int keyCode) {
6213        switch (keyCode) {
6214            // ignore volume keys unless docked
6215            case KeyEvent.KEYCODE_VOLUME_UP:
6216            case KeyEvent.KEYCODE_VOLUME_DOWN:
6217            case KeyEvent.KEYCODE_VOLUME_MUTE:
6218                return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
6219
6220            // ignore media and camera keys
6221            case KeyEvent.KEYCODE_MUTE:
6222            case KeyEvent.KEYCODE_HEADSETHOOK:
6223            case KeyEvent.KEYCODE_MEDIA_PLAY:
6224            case KeyEvent.KEYCODE_MEDIA_PAUSE:
6225            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6226            case KeyEvent.KEYCODE_MEDIA_STOP:
6227            case KeyEvent.KEYCODE_MEDIA_NEXT:
6228            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6229            case KeyEvent.KEYCODE_MEDIA_REWIND:
6230            case KeyEvent.KEYCODE_MEDIA_RECORD:
6231            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6232            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
6233            case KeyEvent.KEYCODE_CAMERA:
6234                return false;
6235        }
6236        return true;
6237    }
6238
6239
6240    /** {@inheritDoc} */
6241    @Override
6242    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
6243        if ((policyFlags & FLAG_WAKE) != 0) {
6244            if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
6245                    "android.policy:MOTION")) {
6246                return 0;
6247            }
6248        }
6249
6250        if (shouldDispatchInputWhenNonInteractive(null)) {
6251            return ACTION_PASS_TO_USER;
6252        }
6253
6254        // If we have not passed the action up and we are in theater mode without dreaming,
6255        // there will be no dream to intercept the touch and wake into ambient.  The device should
6256        // wake up in this case.
6257        if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
6258            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
6259                    "android.policy:MOTION");
6260        }
6261
6262        return 0;
6263    }
6264
6265    private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
6266        final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
6267
6268        if (displayOff && !mHasFeatureWatch) {
6269            return false;
6270        }
6271
6272        // Send events to keyguard while the screen is on and it's showing.
6273        if (isKeyguardShowingAndNotOccluded() && !displayOff) {
6274            return true;
6275        }
6276
6277        // Watches handle BACK specially
6278        if (mHasFeatureWatch
6279                && event != null
6280                && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
6281                        || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
6282            return false;
6283        }
6284
6285        // Send events to a dozing dream even if the screen is off since the dream
6286        // is in control of the state of the screen.
6287        IDreamManager dreamManager = getDreamManager();
6288
6289        try {
6290            if (dreamManager != null && dreamManager.isDreaming()) {
6291                return true;
6292            }
6293        } catch (RemoteException e) {
6294            Slog.e(TAG, "RemoteException when checking if dreaming", e);
6295        }
6296
6297        // Otherwise, consume events since the user can't see what is being
6298        // interacted with.
6299        return false;
6300    }
6301
6302    private void dispatchDirectAudioEvent(KeyEvent event) {
6303        if (event.getAction() != KeyEvent.ACTION_DOWN) {
6304            return;
6305        }
6306        int keyCode = event.getKeyCode();
6307        int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
6308                | AudioManager.FLAG_FROM_KEY;
6309        String pkgName = mContext.getOpPackageName();
6310        switch (keyCode) {
6311            case KeyEvent.KEYCODE_VOLUME_UP:
6312                try {
6313                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
6314                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6315                } catch (RemoteException e) {
6316                    Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
6317                }
6318                break;
6319            case KeyEvent.KEYCODE_VOLUME_DOWN:
6320                try {
6321                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
6322                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6323                } catch (RemoteException e) {
6324                    Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
6325                }
6326                break;
6327            case KeyEvent.KEYCODE_VOLUME_MUTE:
6328                try {
6329                    if (event.getRepeatCount() == 0) {
6330                        getAudioService().adjustSuggestedStreamVolume(
6331                                AudioManager.ADJUST_TOGGLE_MUTE,
6332                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6333                    }
6334                } catch (RemoteException e) {
6335                    Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
6336                }
6337                break;
6338        }
6339    }
6340
6341    void dispatchMediaKeyWithWakeLock(KeyEvent event) {
6342        if (DEBUG_INPUT) {
6343            Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
6344        }
6345
6346        if (mHavePendingMediaKeyRepeatWithWakeLock) {
6347            if (DEBUG_INPUT) {
6348                Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
6349            }
6350
6351            mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
6352            mHavePendingMediaKeyRepeatWithWakeLock = false;
6353            mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
6354        }
6355
6356        dispatchMediaKeyWithWakeLockToAudioService(event);
6357
6358        if (event.getAction() == KeyEvent.ACTION_DOWN
6359                && event.getRepeatCount() == 0) {
6360            mHavePendingMediaKeyRepeatWithWakeLock = true;
6361
6362            Message msg = mHandler.obtainMessage(
6363                    MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
6364            msg.setAsynchronous(true);
6365            mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
6366        } else {
6367            mBroadcastWakeLock.release();
6368        }
6369    }
6370
6371    void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
6372        mHavePendingMediaKeyRepeatWithWakeLock = false;
6373
6374        KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
6375                SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6376        if (DEBUG_INPUT) {
6377            Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
6378        }
6379
6380        dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
6381        mBroadcastWakeLock.release();
6382    }
6383
6384    void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
6385        if (mActivityManagerInternal.isSystemReady()) {
6386            MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
6387        }
6388    }
6389
6390    void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
6391        IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
6392                ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
6393        if (dic != null) {
6394            try {
6395                dic.exitIdle("voice-search");
6396            } catch (RemoteException e) {
6397            }
6398        }
6399        Intent voiceIntent =
6400            new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
6401        voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
6402        startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
6403        mBroadcastWakeLock.release();
6404    }
6405
6406    BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
6407        @Override
6408        public void onReceive(Context context, Intent intent) {
6409            if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
6410                mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6411                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
6412            } else {
6413                try {
6414                    IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
6415                            ServiceManager.getService(Context.UI_MODE_SERVICE));
6416                    mUiMode = uiModeService.getCurrentModeType();
6417                } catch (RemoteException e) {
6418                }
6419            }
6420            updateRotation(true);
6421            synchronized (mLock) {
6422                updateOrientationListenerLp();
6423            }
6424        }
6425    };
6426
6427    BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
6428        @Override
6429        public void onReceive(Context context, Intent intent) {
6430            if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
6431                if (mKeyguardDelegate != null) {
6432                    mKeyguardDelegate.onDreamingStarted();
6433                }
6434            } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
6435                if (mKeyguardDelegate != null) {
6436                    mKeyguardDelegate.onDreamingStopped();
6437                }
6438            }
6439        }
6440    };
6441
6442    BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
6443        @Override
6444        public void onReceive(Context context, Intent intent) {
6445            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
6446                // tickle the settings observer: this first ensures that we're
6447                // observing the relevant settings for the newly-active user,
6448                // and then updates our own bookkeeping based on the now-
6449                // current user.
6450                mSettingsObserver.onChange(false);
6451
6452                // force a re-application of focused window sysui visibility.
6453                // the window may never have been shown for this user
6454                // e.g. the keyguard when going through the new-user setup flow
6455                synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6456                    mLastSystemUiFlags = 0;
6457                    updateSystemUiVisibilityLw();
6458                }
6459            }
6460        }
6461    };
6462
6463    private final Runnable mHiddenNavPanic = new Runnable() {
6464        @Override
6465        public void run() {
6466            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6467                if (!isUserSetupComplete()) {
6468                    // Swipe-up for navigation bar is disabled during setup
6469                    return;
6470                }
6471                mPendingPanicGestureUptime = SystemClock.uptimeMillis();
6472                if (!isNavBarEmpty(mLastSystemUiFlags)) {
6473                    mNavigationBarController.showTransient();
6474                }
6475            }
6476        }
6477    };
6478
6479    private void requestTransientBars(WindowState swipeTarget) {
6480        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6481            if (!isUserSetupComplete()) {
6482                // Swipe-up for navigation bar is disabled during setup
6483                return;
6484            }
6485            boolean sb = mStatusBarController.checkShowTransientBarLw();
6486            boolean nb = mNavigationBarController.checkShowTransientBarLw()
6487                    && !isNavBarEmpty(mLastSystemUiFlags);
6488            if (sb || nb) {
6489                // Don't show status bar when swiping on already visible navigation bar
6490                if (!nb && swipeTarget == mNavigationBar) {
6491                    if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
6492                    return;
6493                }
6494                if (sb) mStatusBarController.showTransient();
6495                if (nb) mNavigationBarController.showTransient();
6496                mImmersiveModeConfirmation.confirmCurrentPrompt();
6497                updateSystemUiVisibilityLw();
6498            }
6499        }
6500    }
6501
6502    // Called on the PowerManager's Notifier thread.
6503    @Override
6504    public void startedGoingToSleep(int why) {
6505        if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
6506        mCameraGestureTriggeredDuringGoingToSleep = false;
6507        mGoingToSleep = true;
6508        if (mKeyguardDelegate != null) {
6509            mKeyguardDelegate.onStartedGoingToSleep(why);
6510        }
6511    }
6512
6513    // Called on the PowerManager's Notifier thread.
6514    @Override
6515    public void finishedGoingToSleep(int why) {
6516        EventLog.writeEvent(70000, 0);
6517        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
6518        MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
6519
6520        mGoingToSleep = false;
6521
6522        // We must get this work done here because the power manager will drop
6523        // the wake lock and let the system suspend once this function returns.
6524        synchronized (mLock) {
6525            mAwake = false;
6526            updateWakeGestureListenerLp();
6527            updateOrientationListenerLp();
6528            updateLockScreenTimeout();
6529        }
6530        if (mKeyguardDelegate != null) {
6531            mKeyguardDelegate.onFinishedGoingToSleep(why,
6532                    mCameraGestureTriggeredDuringGoingToSleep);
6533        }
6534        mCameraGestureTriggeredDuringGoingToSleep = false;
6535    }
6536
6537    // Called on the PowerManager's Notifier thread.
6538    @Override
6539    public void startedWakingUp() {
6540        EventLog.writeEvent(70000, 1);
6541        if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
6542
6543        // Since goToSleep performs these functions synchronously, we must
6544        // do the same here.  We cannot post this work to a handler because
6545        // that might cause it to become reordered with respect to what
6546        // may happen in a future call to goToSleep.
6547        synchronized (mLock) {
6548            mAwake = true;
6549
6550            updateWakeGestureListenerLp();
6551            updateOrientationListenerLp();
6552            updateLockScreenTimeout();
6553        }
6554
6555        if (mKeyguardDelegate != null) {
6556            mKeyguardDelegate.onStartedWakingUp();
6557        }
6558    }
6559
6560    // Called on the PowerManager's Notifier thread.
6561    @Override
6562    public void finishedWakingUp() {
6563        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
6564    }
6565
6566    private void wakeUpFromPowerKey(long eventTime) {
6567        wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
6568    }
6569
6570    private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
6571        final boolean theaterModeEnabled = isTheaterModeEnabled();
6572        if (!wakeInTheaterMode && theaterModeEnabled) {
6573            return false;
6574        }
6575
6576        if (theaterModeEnabled) {
6577            Settings.Global.putInt(mContext.getContentResolver(),
6578                    Settings.Global.THEATER_MODE_ON, 0);
6579        }
6580
6581        mPowerManager.wakeUp(wakeTime, reason);
6582        return true;
6583    }
6584
6585    private void finishKeyguardDrawn() {
6586        synchronized (mLock) {
6587            if (!mScreenOnEarly || mKeyguardDrawComplete) {
6588                return; // We are not awake yet or we have already informed of this event.
6589            }
6590
6591            mKeyguardDrawComplete = true;
6592            if (mKeyguardDelegate != null) {
6593                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6594            }
6595            mWindowManagerDrawComplete = false;
6596        }
6597
6598        // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
6599        // as well as enabling the orientation change logic/sensor.
6600        mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
6601                WAITING_FOR_DRAWN_TIMEOUT);
6602    }
6603
6604    // Called on the DisplayManager's DisplayPowerController thread.
6605    @Override
6606    public void screenTurnedOff() {
6607        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
6608
6609        updateScreenOffSleepToken(true);
6610        synchronized (mLock) {
6611            mScreenOnEarly = false;
6612            mScreenOnFully = false;
6613            mKeyguardDrawComplete = false;
6614            mWindowManagerDrawComplete = false;
6615            mScreenOnListener = null;
6616            updateOrientationListenerLp();
6617
6618            if (mKeyguardDelegate != null) {
6619                mKeyguardDelegate.onScreenTurnedOff();
6620            }
6621        }
6622        reportScreenStateToVrManager(false);
6623    }
6624
6625    // Called on the DisplayManager's DisplayPowerController thread.
6626    @Override
6627    public void screenTurningOn(final ScreenOnListener screenOnListener) {
6628        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
6629
6630        updateScreenOffSleepToken(false);
6631        synchronized (mLock) {
6632            mScreenOnEarly = true;
6633            mScreenOnFully = false;
6634            mKeyguardDrawComplete = false;
6635            mWindowManagerDrawComplete = false;
6636            mScreenOnListener = screenOnListener;
6637
6638            if (mKeyguardDelegate != null) {
6639                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6640                mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
6641                mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
6642            } else {
6643                if (DEBUG_WAKEUP) Slog.d(TAG,
6644                        "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
6645                finishKeyguardDrawn();
6646            }
6647        }
6648    }
6649
6650    // Called on the DisplayManager's DisplayPowerController thread.
6651    @Override
6652    public void screenTurnedOn() {
6653        synchronized (mLock) {
6654            if (mKeyguardDelegate != null) {
6655                mKeyguardDelegate.onScreenTurnedOn();
6656            }
6657        }
6658        reportScreenStateToVrManager(true);
6659    }
6660
6661    private void reportScreenStateToVrManager(boolean isScreenOn) {
6662        if (mVrManagerInternal == null) {
6663            return;
6664        }
6665        mVrManagerInternal.onScreenStateChanged(isScreenOn);
6666    }
6667
6668    private void finishWindowsDrawn() {
6669        synchronized (mLock) {
6670            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
6671                return; // Screen is not turned on or we did already handle this case earlier.
6672            }
6673
6674            mWindowManagerDrawComplete = true;
6675        }
6676
6677        finishScreenTurningOn();
6678    }
6679
6680    private void finishScreenTurningOn() {
6681        synchronized (mLock) {
6682            // We have just finished drawing screen content. Since the orientation listener
6683            // gets only installed when all windows are drawn, we try to install it again.
6684            updateOrientationListenerLp();
6685        }
6686        final ScreenOnListener listener;
6687        final boolean enableScreen;
6688        synchronized (mLock) {
6689            if (DEBUG_WAKEUP) Slog.d(TAG,
6690                    "finishScreenTurningOn: mAwake=" + mAwake
6691                            + ", mScreenOnEarly=" + mScreenOnEarly
6692                            + ", mScreenOnFully=" + mScreenOnFully
6693                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
6694                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
6695
6696            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
6697                    || (mAwake && !mKeyguardDrawComplete)) {
6698                return; // spurious or not ready yet
6699            }
6700
6701            if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
6702            listener = mScreenOnListener;
6703            mScreenOnListener = null;
6704            mScreenOnFully = true;
6705
6706            // Remember the first time we draw the keyguard so we know when we're done with
6707            // the main part of booting and can enable the screen and hide boot messages.
6708            if (!mKeyguardDrawnOnce && mAwake) {
6709                mKeyguardDrawnOnce = true;
6710                enableScreen = true;
6711                if (mBootMessageNeedsHiding) {
6712                    mBootMessageNeedsHiding = false;
6713                    hideBootMessages();
6714                }
6715            } else {
6716                enableScreen = false;
6717            }
6718        }
6719
6720        if (listener != null) {
6721            listener.onScreenOn();
6722        }
6723
6724        if (enableScreen) {
6725            try {
6726                mWindowManager.enableScreenIfNeeded();
6727            } catch (RemoteException unhandled) {
6728            }
6729        }
6730    }
6731
6732    private void handleHideBootMessage() {
6733        synchronized (mLock) {
6734            if (!mKeyguardDrawnOnce) {
6735                mBootMessageNeedsHiding = true;
6736                return; // keyguard hasn't drawn the first time yet, not done booting
6737            }
6738        }
6739
6740        if (mBootMsgDialog != null) {
6741            if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
6742            mBootMsgDialog.dismiss();
6743            mBootMsgDialog = null;
6744        }
6745    }
6746
6747    @Override
6748    public boolean isScreenOn() {
6749        return mScreenOnFully;
6750    }
6751
6752    /** {@inheritDoc} */
6753    @Override
6754    public void enableKeyguard(boolean enabled) {
6755        if (mKeyguardDelegate != null) {
6756            mKeyguardDelegate.setKeyguardEnabled(enabled);
6757        }
6758    }
6759
6760    /** {@inheritDoc} */
6761    @Override
6762    public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
6763        if (mKeyguardDelegate != null) {
6764            mKeyguardDelegate.verifyUnlock(callback);
6765        }
6766    }
6767
6768    @Override
6769    public boolean isKeyguardShowingAndNotOccluded() {
6770        if (mKeyguardDelegate == null) return false;
6771        return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
6772    }
6773
6774    @Override
6775    public boolean isKeyguardTrustedLw() {
6776        if (mKeyguardDelegate == null) return false;
6777        return mKeyguardDelegate.isTrusted();
6778    }
6779
6780    /** {@inheritDoc} */
6781    @Override
6782    public boolean isKeyguardLocked() {
6783        return keyguardOn();
6784    }
6785
6786    /** {@inheritDoc} */
6787    @Override
6788    public boolean isKeyguardSecure(int userId) {
6789        if (mKeyguardDelegate == null) return false;
6790        return mKeyguardDelegate.isSecure(userId);
6791    }
6792
6793    /** {@inheritDoc} */
6794    @Override
6795    public boolean isKeyguardOccluded() {
6796        if (mKeyguardDelegate == null) return false;
6797        return mKeyguardOccluded;
6798    }
6799
6800    /** {@inheritDoc} */
6801    @Override
6802    public boolean inKeyguardRestrictedKeyInputMode() {
6803        if (mKeyguardDelegate == null) return false;
6804        return mKeyguardDelegate.isInputRestricted();
6805    }
6806
6807    @Override
6808    public void dismissKeyguardLw(IKeyguardDismissCallback callback) {
6809        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
6810            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
6811
6812            // ask the keyguard to prompt the user to authenticate if necessary
6813            mKeyguardDelegate.dismiss(callback);
6814        } else if (callback != null) {
6815            try {
6816                callback.onDismissError();
6817            } catch (RemoteException e) {
6818                Slog.w(TAG, "Failed to call callback", e);
6819            }
6820        }
6821    }
6822
6823    @Override
6824    public boolean isKeyguardDrawnLw() {
6825        synchronized (mLock) {
6826            return mKeyguardDrawnOnce;
6827        }
6828    }
6829
6830    @Override
6831    public boolean isShowingDreamLw() {
6832        return mShowingDream;
6833    }
6834
6835    @Override
6836    public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
6837        if (mKeyguardDelegate != null) {
6838            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
6839            mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
6840        }
6841    }
6842
6843    @Override
6844    public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6845            Rect outInsets) {
6846        outInsets.setEmpty();
6847
6848        // Navigation bar and status bar.
6849        getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
6850        outInsets.top = mStatusBarHeight;
6851    }
6852
6853    @Override
6854    public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6855            Rect outInsets) {
6856        outInsets.setEmpty();
6857
6858        // Only navigation bar
6859        if (mHasNavigationBar) {
6860            int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
6861            if (position == NAV_BAR_BOTTOM) {
6862                outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
6863            } else if (position == NAV_BAR_RIGHT) {
6864                outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
6865            } else if (position == NAV_BAR_LEFT) {
6866                outInsets.left = getNavigationBarWidth(displayRotation, mUiMode);
6867            }
6868        }
6869    }
6870
6871    @Override
6872    public boolean isNavBarForcedShownLw(WindowState windowState) {
6873        return mForceShowSystemBars;
6874    }
6875
6876    @Override
6877    public boolean isDockSideAllowed(int dockSide) {
6878
6879        // We do not allow all dock sides at which the navigation bar touches the docked stack.
6880        if (!mNavigationBarCanMove) {
6881            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT;
6882        } else {
6883            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT;
6884        }
6885    }
6886
6887    void sendCloseSystemWindows() {
6888        PhoneWindow.sendCloseSystemWindows(mContext, null);
6889    }
6890
6891    void sendCloseSystemWindows(String reason) {
6892        PhoneWindow.sendCloseSystemWindows(mContext, reason);
6893    }
6894
6895    @Override
6896    public int rotationForOrientationLw(int orientation, int lastRotation) {
6897        if (false) {
6898            Slog.v(TAG, "rotationForOrientationLw(orient="
6899                        + orientation + ", last=" + lastRotation
6900                        + "); user=" + mUserRotation + " "
6901                        + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
6902                            ? "USER_ROTATION_LOCKED" : "")
6903                        );
6904        }
6905
6906        if (mForceDefaultOrientation) {
6907            return Surface.ROTATION_0;
6908        }
6909
6910        synchronized (mLock) {
6911            int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
6912            if (sensorRotation < 0) {
6913                sensorRotation = lastRotation;
6914            }
6915
6916            final int preferredRotation;
6917            if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
6918                // Ignore sensor when lid switch is open and rotation is forced.
6919                preferredRotation = mLidOpenRotation;
6920            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
6921                    && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
6922                // Ignore sensor when in car dock unless explicitly enabled.
6923                // This case can override the behavior of NOSENSOR, and can also
6924                // enable 180 degree rotation while docked.
6925                preferredRotation = mCarDockEnablesAccelerometer
6926                        ? sensorRotation : mCarDockRotation;
6927            } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
6928                    || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
6929                    || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
6930                    && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
6931                // Ignore sensor when in desk 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 = mDeskDockEnablesAccelerometer
6935                        ? sensorRotation : mDeskDockRotation;
6936            } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
6937                // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
6938                // Note that the dock orientation overrides the HDMI orientation.
6939                preferredRotation = mDemoHdmiRotation;
6940            } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
6941                    && mUndockedHdmiRotation >= 0) {
6942                // Ignore sensor when plugged into HDMI and an undocked orientation has
6943                // been specified in the configuration (only for legacy devices without
6944                // full multi-display support).
6945                // Note that the dock orientation overrides the HDMI orientation.
6946                preferredRotation = mUndockedHdmiRotation;
6947            } else if (mDemoRotationLock) {
6948                // Ignore sensor when demo rotation lock is enabled.
6949                // Note that the dock orientation and HDMI rotation lock override this.
6950                preferredRotation = mDemoRotation;
6951            } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
6952                // Application just wants to remain locked in the last rotation.
6953                preferredRotation = lastRotation;
6954            } else if (!mSupportAutoRotation) {
6955                // If we don't support auto-rotation then bail out here and ignore
6956                // the sensor and any rotation lock settings.
6957                preferredRotation = -1;
6958            } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
6959                            && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
6960                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
6961                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
6962                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
6963                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
6964                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
6965                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6966                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
6967                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
6968                // Otherwise, use sensor only if requested by the application or enabled
6969                // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
6970                if (mAllowAllRotations < 0) {
6971                    // Can't read this during init() because the context doesn't
6972                    // have display metrics at that time so we cannot determine
6973                    // tablet vs. phone then.
6974                    mAllowAllRotations = mContext.getResources().getBoolean(
6975                            com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
6976                }
6977                if (sensorRotation != Surface.ROTATION_180
6978                        || mAllowAllRotations == 1
6979                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6980                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
6981                    // In VrMode, we report the sensor as always being in default orientation so:
6982                    // 1) The orientation doesn't change as the user moves their head.
6983                    // 2) 2D apps within VR show in the device's default orientation.
6984                    // This only overwrites the sensor-provided orientation and does not affect any
6985                    // explicit orientation preferences specified by any activities.
6986                    preferredRotation =
6987                            mPersistentVrModeEnabled ? Surface.ROTATION_0 : sensorRotation;
6988                } else {
6989                    preferredRotation = lastRotation;
6990                }
6991            } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
6992                    && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
6993                // Apply rotation lock.  Does not apply to NOSENSOR.
6994                // The idea is that the user rotation expresses a weak preference for the direction
6995                // of gravity and as NOSENSOR is never affected by gravity, then neither should
6996                // NOSENSOR be affected by rotation lock (although it will be affected by docks).
6997                preferredRotation = mUserRotation;
6998            } else {
6999                // No overriding preference.
7000                // We will do exactly what the application asked us to do.
7001                preferredRotation = -1;
7002            }
7003
7004            switch (orientation) {
7005                case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
7006                    // Return portrait unless overridden.
7007                    if (isAnyPortrait(preferredRotation)) {
7008                        return preferredRotation;
7009                    }
7010                    return mPortraitRotation;
7011
7012                case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
7013                    // Return landscape unless overridden.
7014                    if (isLandscapeOrSeascape(preferredRotation)) {
7015                        return preferredRotation;
7016                    }
7017                    return mLandscapeRotation;
7018
7019                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
7020                    // Return reverse portrait unless overridden.
7021                    if (isAnyPortrait(preferredRotation)) {
7022                        return preferredRotation;
7023                    }
7024                    return mUpsideDownRotation;
7025
7026                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
7027                    // Return seascape unless overridden.
7028                    if (isLandscapeOrSeascape(preferredRotation)) {
7029                        return preferredRotation;
7030                    }
7031                    return mSeascapeRotation;
7032
7033                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
7034                case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
7035                    // Return either landscape rotation.
7036                    if (isLandscapeOrSeascape(preferredRotation)) {
7037                        return preferredRotation;
7038                    }
7039                    if (isLandscapeOrSeascape(lastRotation)) {
7040                        return lastRotation;
7041                    }
7042                    return mLandscapeRotation;
7043
7044                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
7045                case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
7046                    // Return either portrait rotation.
7047                    if (isAnyPortrait(preferredRotation)) {
7048                        return preferredRotation;
7049                    }
7050                    if (isAnyPortrait(lastRotation)) {
7051                        return lastRotation;
7052                    }
7053                    return mPortraitRotation;
7054
7055                default:
7056                    // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
7057                    // just return the preferred orientation we already calculated.
7058                    if (preferredRotation >= 0) {
7059                        return preferredRotation;
7060                    }
7061                    return Surface.ROTATION_0;
7062            }
7063        }
7064    }
7065
7066    @Override
7067    public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
7068        switch (orientation) {
7069            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
7070            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
7071            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
7072                return isAnyPortrait(rotation);
7073
7074            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
7075            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
7076            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
7077                return isLandscapeOrSeascape(rotation);
7078
7079            default:
7080                return true;
7081        }
7082    }
7083
7084    @Override
7085    public void setRotationLw(int rotation) {
7086        mOrientationListener.setCurrentRotation(rotation);
7087    }
7088
7089    private boolean isLandscapeOrSeascape(int rotation) {
7090        return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
7091    }
7092
7093    private boolean isAnyPortrait(int rotation) {
7094        return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
7095    }
7096
7097    @Override
7098    public int getUserRotationMode() {
7099        return Settings.System.getIntForUser(mContext.getContentResolver(),
7100                Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
7101                        WindowManagerPolicy.USER_ROTATION_FREE :
7102                                WindowManagerPolicy.USER_ROTATION_LOCKED;
7103    }
7104
7105    // User rotation: to be used when all else fails in assigning an orientation to the device
7106    @Override
7107    public void setUserRotationMode(int mode, int rot) {
7108        ContentResolver res = mContext.getContentResolver();
7109
7110        // mUserRotationMode and mUserRotation will be assigned by the content observer
7111        if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
7112            Settings.System.putIntForUser(res,
7113                    Settings.System.USER_ROTATION,
7114                    rot,
7115                    UserHandle.USER_CURRENT);
7116            Settings.System.putIntForUser(res,
7117                    Settings.System.ACCELEROMETER_ROTATION,
7118                    0,
7119                    UserHandle.USER_CURRENT);
7120        } else {
7121            Settings.System.putIntForUser(res,
7122                    Settings.System.ACCELEROMETER_ROTATION,
7123                    1,
7124                    UserHandle.USER_CURRENT);
7125        }
7126    }
7127
7128    @Override
7129    public void setSafeMode(boolean safeMode) {
7130        mSafeMode = safeMode;
7131        performHapticFeedbackLw(null, safeMode
7132                ? HapticFeedbackConstants.SAFE_MODE_ENABLED
7133                : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
7134    }
7135
7136    static long[] getLongIntArray(Resources r, int resid) {
7137        int[] ar = r.getIntArray(resid);
7138        if (ar == null) {
7139            return null;
7140        }
7141        long[] out = new long[ar.length];
7142        for (int i=0; i<ar.length; i++) {
7143            out[i] = ar[i];
7144        }
7145        return out;
7146    }
7147
7148    /** {@inheritDoc} */
7149    @Override
7150    public void systemReady() {
7151        mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
7152                new StateCallback() {
7153                    @Override
7154                    public void onTrustedChanged() {
7155                        mWindowManagerFuncs.notifyKeyguardTrustedChanged();
7156                    }
7157                });
7158        mKeyguardDelegate.onSystemReady();
7159
7160        mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
7161        if (mVrManagerInternal != null) {
7162            mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
7163        }
7164
7165        readCameraLensCoverState();
7166        updateUiMode();
7167        boolean bindKeyguardNow;
7168        synchronized (mLock) {
7169            updateOrientationListenerLp();
7170            mSystemReady = true;
7171            mHandler.post(new Runnable() {
7172                @Override
7173                public void run() {
7174                    updateSettings();
7175                }
7176            });
7177
7178            bindKeyguardNow = mDeferBindKeyguard;
7179            if (bindKeyguardNow) {
7180                // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now.
7181                mDeferBindKeyguard = false;
7182            }
7183        }
7184
7185        if (bindKeyguardNow) {
7186            mKeyguardDelegate.bindService(mContext);
7187            mKeyguardDelegate.onBootCompleted();
7188        }
7189        mSystemGestures.systemReady();
7190        mImmersiveModeConfirmation.systemReady();
7191    }
7192
7193    /** {@inheritDoc} */
7194    @Override
7195    public void systemBooted() {
7196        boolean bindKeyguardNow = false;
7197        synchronized (mLock) {
7198            // Time to bind Keyguard; take care to only bind it once, either here if ready or
7199            // in systemReady if not.
7200            if (mKeyguardDelegate != null) {
7201                bindKeyguardNow = true;
7202            } else {
7203                // Because mKeyguardDelegate is null, we know that the synchronized block in
7204                // systemReady didn't run yet and setting this will actually have an effect.
7205                mDeferBindKeyguard = true;
7206            }
7207        }
7208        if (bindKeyguardNow) {
7209            mKeyguardDelegate.bindService(mContext);
7210            mKeyguardDelegate.onBootCompleted();
7211        }
7212        synchronized (mLock) {
7213            mSystemBooted = true;
7214        }
7215        startedWakingUp();
7216        screenTurningOn(null);
7217        screenTurnedOn();
7218    }
7219
7220    ProgressDialog mBootMsgDialog = null;
7221
7222    /** {@inheritDoc} */
7223    @Override
7224    public void showBootMessage(final CharSequence msg, final boolean always) {
7225        mHandler.post(new Runnable() {
7226            @Override public void run() {
7227                if (mBootMsgDialog == null) {
7228                    int theme;
7229                    if (mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK)) {
7230                        theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
7231                    } else {
7232                        theme = 0;
7233                    }
7234
7235                    mBootMsgDialog = new ProgressDialog(mContext, theme) {
7236                        // This dialog will consume all events coming in to
7237                        // it, to avoid it trying to do things too early in boot.
7238                        @Override public boolean dispatchKeyEvent(KeyEvent event) {
7239                            return true;
7240                        }
7241                        @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7242                            return true;
7243                        }
7244                        @Override public boolean dispatchTouchEvent(MotionEvent ev) {
7245                            return true;
7246                        }
7247                        @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
7248                            return true;
7249                        }
7250                        @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
7251                            return true;
7252                        }
7253                        @Override public boolean dispatchPopulateAccessibilityEvent(
7254                                AccessibilityEvent event) {
7255                            return true;
7256                        }
7257                    };
7258                    if (mContext.getPackageManager().isUpgrade()) {
7259                        mBootMsgDialog.setTitle(R.string.android_upgrading_title);
7260                    } else {
7261                        mBootMsgDialog.setTitle(R.string.android_start_title);
7262                    }
7263                    mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
7264                    mBootMsgDialog.setIndeterminate(true);
7265                    mBootMsgDialog.getWindow().setType(
7266                            WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
7267                    mBootMsgDialog.getWindow().addFlags(
7268                            WindowManager.LayoutParams.FLAG_DIM_BEHIND
7269                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
7270                    mBootMsgDialog.getWindow().setDimAmount(1);
7271                    WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
7272                    lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
7273                    mBootMsgDialog.getWindow().setAttributes(lp);
7274                    mBootMsgDialog.setCancelable(false);
7275                    mBootMsgDialog.show();
7276                }
7277                mBootMsgDialog.setMessage(msg);
7278            }
7279        });
7280    }
7281
7282    /** {@inheritDoc} */
7283    @Override
7284    public void hideBootMessages() {
7285        mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
7286    }
7287
7288    /** {@inheritDoc} */
7289    @Override
7290    public void userActivity() {
7291        // ***************************************
7292        // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
7293        // ***************************************
7294        // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
7295        // WITH ITS LOCKS HELD.
7296        //
7297        // This code must be VERY careful about the locks
7298        // it acquires.
7299        // In fact, the current code acquires way too many,
7300        // and probably has lurking deadlocks.
7301
7302        synchronized (mScreenLockTimeout) {
7303            if (mLockScreenTimerActive) {
7304                // reset the timer
7305                mHandler.removeCallbacks(mScreenLockTimeout);
7306                mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7307            }
7308        }
7309    }
7310
7311    class ScreenLockTimeout implements Runnable {
7312        Bundle options;
7313
7314        @Override
7315        public void run() {
7316            synchronized (this) {
7317                if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
7318                if (mKeyguardDelegate != null) {
7319                    mKeyguardDelegate.doKeyguardTimeout(options);
7320                }
7321                mLockScreenTimerActive = false;
7322                options = null;
7323            }
7324        }
7325
7326        public void setLockOptions(Bundle options) {
7327            this.options = options;
7328        }
7329    }
7330
7331    ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
7332
7333    @Override
7334    public void lockNow(Bundle options) {
7335        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
7336        mHandler.removeCallbacks(mScreenLockTimeout);
7337        if (options != null) {
7338            // In case multiple calls are made to lockNow, we don't wipe out the options
7339            // until the runnable actually executes.
7340            mScreenLockTimeout.setLockOptions(options);
7341        }
7342        mHandler.post(mScreenLockTimeout);
7343    }
7344
7345    private void updateLockScreenTimeout() {
7346        synchronized (mScreenLockTimeout) {
7347            boolean enable = (mAllowLockscreenWhenOn && mAwake &&
7348                    mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
7349            if (mLockScreenTimerActive != enable) {
7350                if (enable) {
7351                    if (localLOGV) Log.v(TAG, "setting lockscreen timer");
7352                    mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
7353                    mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7354                } else {
7355                    if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
7356                    mHandler.removeCallbacks(mScreenLockTimeout);
7357                }
7358                mLockScreenTimerActive = enable;
7359            }
7360        }
7361    }
7362
7363    private void updateDreamingSleepToken(boolean acquire) {
7364        if (acquire) {
7365            if (mDreamingSleepToken == null) {
7366                mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream");
7367            }
7368        } else {
7369            if (mDreamingSleepToken != null) {
7370                mDreamingSleepToken.release();
7371                mDreamingSleepToken = null;
7372            }
7373        }
7374    }
7375
7376    private void updateScreenOffSleepToken(boolean acquire) {
7377        if (acquire) {
7378            if (mScreenOffSleepToken == null) {
7379                mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff");
7380            }
7381        } else {
7382            if (mScreenOffSleepToken != null) {
7383                mScreenOffSleepToken.release();
7384                mScreenOffSleepToken = null;
7385            }
7386        }
7387    }
7388
7389    /** {@inheritDoc} */
7390    @Override
7391    public void enableScreenAfterBoot() {
7392        readLidState();
7393        applyLidSwitchState();
7394        updateRotation(true);
7395    }
7396
7397    private void applyLidSwitchState() {
7398        if (mLidState == LID_CLOSED && mLidControlsSleep) {
7399            mPowerManager.goToSleep(SystemClock.uptimeMillis(),
7400                    PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
7401                    PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
7402        } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
7403            mWindowManagerFuncs.lockDeviceNow();
7404        }
7405
7406        synchronized (mLock) {
7407            updateWakeGestureListenerLp();
7408        }
7409    }
7410
7411    void updateUiMode() {
7412        if (mUiModeManager == null) {
7413            mUiModeManager = IUiModeManager.Stub.asInterface(
7414                    ServiceManager.getService(Context.UI_MODE_SERVICE));
7415        }
7416        try {
7417            mUiMode = mUiModeManager.getCurrentModeType();
7418        } catch (RemoteException e) {
7419        }
7420    }
7421
7422    void updateRotation(boolean alwaysSendConfiguration) {
7423        try {
7424            //set orientation on WindowManager
7425            mWindowManager.updateRotation(alwaysSendConfiguration, false);
7426        } catch (RemoteException e) {
7427            // Ignore
7428        }
7429    }
7430
7431    void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
7432        try {
7433            //set orientation on WindowManager
7434            mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
7435        } catch (RemoteException e) {
7436            // Ignore
7437        }
7438    }
7439
7440    /**
7441     * Return an Intent to launch the currently active dock app as home.  Returns
7442     * null if the standard home should be launched, which is the case if any of the following is
7443     * true:
7444     * <ul>
7445     *  <li>The device is not in either car mode or desk mode
7446     *  <li>The device is in car mode but mEnableCarDockHomeCapture is false
7447     *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
7448     *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
7449     *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
7450     * </ul>
7451     * @return A dock intent.
7452     */
7453    Intent createHomeDockIntent() {
7454        Intent intent = null;
7455
7456        // What home does is based on the mode, not the dock state.  That
7457        // is, when in car mode you should be taken to car home regardless
7458        // of whether we are actually in a car dock.
7459        if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
7460            if (mEnableCarDockHomeCapture) {
7461                intent = mCarDockIntent;
7462            }
7463        } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
7464            if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
7465                intent = mDeskDockIntent;
7466            }
7467        } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
7468                && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7469                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
7470                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
7471            // Always launch dock home from home when watch is docked, if it exists.
7472            intent = mDeskDockIntent;
7473        } else if (mUiMode == Configuration.UI_MODE_TYPE_VR_HEADSET) {
7474            if (ENABLE_VR_HEADSET_HOME_CAPTURE) {
7475                intent = mVrHeadsetHomeIntent;
7476            }
7477        }
7478
7479        if (intent == null) {
7480            return null;
7481        }
7482
7483        ActivityInfo ai = null;
7484        ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
7485                intent,
7486                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
7487                mCurrentUserId);
7488        if (info != null) {
7489            ai = info.activityInfo;
7490        }
7491        if (ai != null
7492                && ai.metaData != null
7493                && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
7494            intent = new Intent(intent);
7495            intent.setClassName(ai.packageName, ai.name);
7496            return intent;
7497        }
7498
7499        return null;
7500    }
7501
7502    void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
7503        if (awakenFromDreams) {
7504            awakenDreams();
7505        }
7506
7507        Intent dock = createHomeDockIntent();
7508        if (dock != null) {
7509            try {
7510                if (fromHomeKey) {
7511                    dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7512                }
7513                startActivityAsUser(dock, UserHandle.CURRENT);
7514                return;
7515            } catch (ActivityNotFoundException e) {
7516            }
7517        }
7518
7519        Intent intent;
7520
7521        if (fromHomeKey) {
7522            intent = new Intent(mHomeIntent);
7523            intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7524        } else {
7525            intent = mHomeIntent;
7526        }
7527
7528        startActivityAsUser(intent, UserHandle.CURRENT);
7529    }
7530
7531    /**
7532     * goes to the home screen
7533     * @return whether it did anything
7534     */
7535    boolean goHome() {
7536        if (!isUserSetupComplete()) {
7537            Slog.i(TAG, "Not going home because user setup is in progress.");
7538            return false;
7539        }
7540        if (false) {
7541            // This code always brings home to the front.
7542            try {
7543                ActivityManager.getService().stopAppSwitches();
7544            } catch (RemoteException e) {
7545            }
7546            sendCloseSystemWindows();
7547            startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
7548        } else {
7549            // This code brings home to the front or, if it is already
7550            // at the front, puts the device to sleep.
7551            try {
7552                if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
7553                    /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
7554                    Log.d(TAG, "UTS-TEST-MODE");
7555                } else {
7556                    ActivityManager.getService().stopAppSwitches();
7557                    sendCloseSystemWindows();
7558                    Intent dock = createHomeDockIntent();
7559                    if (dock != null) {
7560                        int result = ActivityManager.getService()
7561                                .startActivityAsUser(null, null, dock,
7562                                        dock.resolveTypeIfNeeded(mContext.getContentResolver()),
7563                                        null, null, 0,
7564                                        ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7565                                        null, null, UserHandle.USER_CURRENT);
7566                        if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7567                            return false;
7568                        }
7569                    }
7570                }
7571                int result = ActivityManager.getService()
7572                        .startActivityAsUser(null, null, mHomeIntent,
7573                                mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
7574                                null, null, 0,
7575                                ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7576                                null, null, UserHandle.USER_CURRENT);
7577                if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7578                    return false;
7579                }
7580            } catch (RemoteException ex) {
7581                // bummer, the activity manager, which is in this process, is dead
7582            }
7583        }
7584        return true;
7585    }
7586
7587    @Override
7588    public void setCurrentOrientationLw(int newOrientation) {
7589        synchronized (mLock) {
7590            if (newOrientation != mCurrentAppOrientation) {
7591                mCurrentAppOrientation = newOrientation;
7592                updateOrientationListenerLp();
7593            }
7594        }
7595    }
7596
7597    private boolean isTheaterModeEnabled() {
7598        return Settings.Global.getInt(mContext.getContentResolver(),
7599                Settings.Global.THEATER_MODE_ON, 0) == 1;
7600    }
7601
7602    private boolean areSystemNavigationKeysEnabled() {
7603        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
7604                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
7605    }
7606
7607    @Override
7608    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
7609        if (!mVibrator.hasVibrator()) {
7610            return false;
7611        }
7612        final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
7613                Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
7614        if (hapticsDisabled && !always) {
7615            return false;
7616        }
7617
7618        VibrationEffect effect = getVibrationEffect(effectId);
7619        if (effect == null) {
7620            return false;
7621        }
7622
7623        int owningUid;
7624        String owningPackage;
7625        if (win != null) {
7626            owningUid = win.getOwningUid();
7627            owningPackage = win.getOwningPackage();
7628        } else {
7629            owningUid = android.os.Process.myUid();
7630            owningPackage = mContext.getOpPackageName();
7631        }
7632        mVibrator.vibrate(owningUid, owningPackage, effect, VIBRATION_ATTRIBUTES);
7633        return true;
7634    }
7635
7636    private VibrationEffect getVibrationEffect(int effectId) {
7637        long[] pattern;
7638        switch (effectId) {
7639            case HapticFeedbackConstants.VIRTUAL_KEY:
7640                return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
7641            case HapticFeedbackConstants.LONG_PRESS:
7642                pattern = mLongPressVibePattern;
7643                break;
7644            case HapticFeedbackConstants.KEYBOARD_TAP:
7645                return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
7646            case HapticFeedbackConstants.CLOCK_TICK:
7647                pattern = mClockTickVibePattern;
7648                break;
7649            case HapticFeedbackConstants.CALENDAR_DATE:
7650                pattern = mCalendarDateVibePattern;
7651                break;
7652            case HapticFeedbackConstants.SAFE_MODE_DISABLED:
7653                pattern = mSafeModeDisabledVibePattern;
7654                break;
7655            case HapticFeedbackConstants.SAFE_MODE_ENABLED:
7656                pattern = mSafeModeEnabledVibePattern;
7657                break;
7658            case HapticFeedbackConstants.CONTEXT_CLICK:
7659                pattern = mContextClickVibePattern;
7660                break;
7661            default:
7662                return null;
7663        }
7664        if (pattern.length == 1) {
7665            // One-shot vibration
7666            return VibrationEffect.createOneShot(pattern[0], VibrationEffect.DEFAULT_AMPLITUDE);
7667        } else {
7668            // Pattern vibration
7669            return VibrationEffect.createWaveform(pattern, -1);
7670        }
7671    }
7672
7673    @Override
7674    public void keepScreenOnStartedLw() {
7675    }
7676
7677    @Override
7678    public void keepScreenOnStoppedLw() {
7679        if (isKeyguardShowingAndNotOccluded()) {
7680            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
7681        }
7682    }
7683
7684    private int updateSystemUiVisibilityLw() {
7685        // If there is no window focused, there will be nobody to handle the events
7686        // anyway, so just hang on in whatever state we're in until things settle down.
7687        WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
7688                : mTopFullscreenOpaqueWindowState;
7689        if (winCandidate == null) {
7690            return 0;
7691        }
7692        if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
7693            // The immersive mode confirmation should never affect the system bar visibility,
7694            // otherwise it will unhide the navigation bar and hide itself.
7695            winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState;
7696            if (winCandidate == null) {
7697                return 0;
7698            }
7699        }
7700        final WindowState win = winCandidate;
7701        if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mKeyguardOccluded) {
7702            // We are updating at a point where the keyguard has gotten
7703            // focus, but we were last in a state where the top window is
7704            // hiding it.  This is probably because the keyguard as been
7705            // shown while the top window was displayed, so we want to ignore
7706            // it here because this is just a very transient change and it
7707            // will quickly lose focus once it correctly gets hidden.
7708            return 0;
7709        }
7710
7711        int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
7712                & ~mResettingSystemUiFlags
7713                & ~mForceClearedSystemUiFlags;
7714        if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
7715            tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
7716        }
7717
7718        final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
7719                mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
7720        final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
7721                mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
7722        mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);
7723        mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);
7724        final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
7725        final int diff = visibility ^ mLastSystemUiFlags;
7726        final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
7727        final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
7728        final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
7729        if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
7730                && mFocusedApp == win.getAppToken()
7731                && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
7732                && mLastDockedStackBounds.equals(mDockedStackBounds)) {
7733            return 0;
7734        }
7735        mLastSystemUiFlags = visibility;
7736        mLastFullscreenStackSysUiFlags = fullscreenVisibility;
7737        mLastDockedStackSysUiFlags = dockedVisibility;
7738        mLastFocusNeedsMenu = needsMenu;
7739        mFocusedApp = win.getAppToken();
7740        final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
7741        final Rect dockedStackBounds = new Rect(mDockedStackBounds);
7742        mHandler.post(new Runnable() {
7743                @Override
7744                public void run() {
7745                    StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
7746                    if (statusbar != null) {
7747                        statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
7748                                dockedVisibility, 0xffffffff, fullscreenStackBounds,
7749                                dockedStackBounds, win.toString());
7750                        statusbar.topAppWindowChanged(needsMenu);
7751                    }
7752                }
7753            });
7754        return diff;
7755    }
7756
7757    private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
7758        WindowState statusColorWin = isStatusBarKeyguard() && !mKeyguardOccluded
7759                ? mStatusBar
7760                : opaqueOrDimming;
7761
7762        if (statusColorWin != null) {
7763            if (statusColorWin == opaque) {
7764                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7765                // its light flag.
7766                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7767                vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
7768                        & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7769            } else if (statusColorWin != null && statusColorWin.isDimming()) {
7770                // Otherwise if it's dimming, clear the light flag.
7771                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7772            }
7773        }
7774        return vis;
7775    }
7776
7777    private int updateLightNavigationBarLw(int vis, WindowState opaque,
7778            WindowState opaqueOrDimming) {
7779        final WindowState imeWin = mWindowManagerFuncs.getInputMethodWindowLw();
7780
7781        final WindowState navColorWin;
7782        if (imeWin != null && imeWin.isVisibleLw()) {
7783            navColorWin = imeWin;
7784        } else {
7785            navColorWin = opaqueOrDimming;
7786        }
7787
7788        if (navColorWin != null) {
7789            if (navColorWin == opaque) {
7790                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7791                // its light flag.
7792                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7793                vis |= PolicyControl.getSystemUiVisibility(navColorWin, null)
7794                        & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7795            } else if (navColorWin.isDimming() || navColorWin == imeWin) {
7796                // Otherwise if it's dimming or it's the IME window, clear the light flag.
7797                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7798            }
7799        }
7800        return vis;
7801    }
7802
7803    private boolean drawsSystemBarBackground(WindowState win) {
7804        return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
7805    }
7806
7807    private boolean forcesDrawStatusBarBackground(WindowState win) {
7808        return win == null || (win.getAttrs().privateFlags
7809                & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
7810    }
7811
7812    private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
7813        final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
7814        final boolean freeformStackVisible =
7815                mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
7816        final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
7817
7818        // We need to force system bars when the docked stack is visible, when the freeform stack
7819        // is visible but also when we are resizing for the transitions when docked stack
7820        // visibility changes.
7821        mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
7822        final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
7823
7824        // apply translucent bar vis flags
7825        WindowState fullscreenTransWin = isStatusBarKeyguard() && !mKeyguardOccluded
7826                ? mStatusBar
7827                : mTopFullscreenOpaqueWindowState;
7828        vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7829        vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7830        final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
7831                mTopDockedOpaqueWindowState, 0, 0);
7832
7833        final boolean fullscreenDrawsStatusBarBackground =
7834                (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
7835                        && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
7836                || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
7837        final boolean dockedDrawsStatusBarBackground =
7838                (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
7839                        && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
7840                || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
7841
7842        // prevent status bar interaction from clearing certain flags
7843        int type = win.getAttrs().type;
7844        boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
7845        if (statusBarHasFocus && !isStatusBarKeyguard()) {
7846            int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
7847                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
7848                    | View.SYSTEM_UI_FLAG_IMMERSIVE
7849                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
7850                    | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7851            if (mKeyguardOccluded) {
7852                flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
7853            }
7854            vis = (vis & ~flags) | (oldVis & flags);
7855        }
7856
7857        if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
7858            vis |= View.STATUS_BAR_TRANSPARENT;
7859            vis &= ~View.STATUS_BAR_TRANSLUCENT;
7860        } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
7861                || forceOpaqueStatusBar) {
7862            vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
7863        }
7864
7865        vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
7866
7867        // update status bar
7868        boolean immersiveSticky =
7869                (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7870        final boolean hideStatusBarWM =
7871                mTopFullscreenOpaqueWindowState != null
7872                && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
7873                        & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
7874        final boolean hideStatusBarSysui =
7875                (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
7876        final boolean hideNavBarSysui =
7877                (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
7878
7879        final boolean transientStatusBarAllowed = mStatusBar != null
7880                && (statusBarHasFocus || (!mForceShowSystemBars
7881                        && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
7882
7883        final boolean transientNavBarAllowed = mNavigationBar != null
7884                && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
7885
7886        final long now = SystemClock.uptimeMillis();
7887        final boolean pendingPanic = mPendingPanicGestureUptime != 0
7888                && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
7889        if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
7890            // The user performed the panic gesture recently, we're about to hide the bars,
7891            // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
7892            mPendingPanicGestureUptime = 0;
7893            mStatusBarController.showTransient();
7894            if (!isNavBarEmpty(vis)) {
7895                mNavigationBarController.showTransient();
7896            }
7897        }
7898
7899        final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
7900                && !transientStatusBarAllowed && hideStatusBarSysui;
7901        final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
7902                && !transientNavBarAllowed;
7903        if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
7904            // clear the clearable flags instead
7905            clearClearableFlagsLw();
7906            vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
7907        }
7908
7909        final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
7910        immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7911        final boolean navAllowedHidden = immersive || immersiveSticky;
7912
7913        if (hideNavBarSysui && !navAllowedHidden
7914                && getWindowLayerLw(win) > getWindowLayerFromTypeLw(TYPE_INPUT_CONSUMER)) {
7915            // We can't hide the navbar from this window otherwise the input consumer would not get
7916            // the input events.
7917            vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
7918        }
7919
7920        vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
7921
7922        // update navigation bar
7923        boolean oldImmersiveMode = isImmersiveMode(oldVis);
7924        boolean newImmersiveMode = isImmersiveMode(vis);
7925        if (win != null && oldImmersiveMode != newImmersiveMode) {
7926            final String pkg = win.getOwningPackage();
7927            mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
7928                    isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility()));
7929        }
7930
7931        vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
7932
7933        vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState,
7934                mTopFullscreenOpaqueOrDimmingWindowState);
7935
7936        return vis;
7937    }
7938
7939    /**
7940     * @return the current visibility flags with the nav-bar opacity related flags toggled based
7941     *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
7942     */
7943    private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
7944            boolean freeformStackVisible, boolean isDockedDividerResizing) {
7945        if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
7946            if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
7947                visibility = setNavBarOpaqueFlag(visibility);
7948            }
7949        } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
7950            if (isDockedDividerResizing) {
7951                visibility = setNavBarOpaqueFlag(visibility);
7952            } else if (freeformStackVisible) {
7953                visibility = setNavBarTranslucentFlag(visibility);
7954            } else {
7955                visibility = setNavBarOpaqueFlag(visibility);
7956            }
7957        }
7958
7959        if (!areTranslucentBarsAllowed()) {
7960            visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
7961        }
7962        return visibility;
7963    }
7964
7965    private int setNavBarOpaqueFlag(int visibility) {
7966        return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
7967    }
7968
7969    private int setNavBarTranslucentFlag(int visibility) {
7970        visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
7971        return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
7972    }
7973
7974    private void clearClearableFlagsLw() {
7975        int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
7976        if (newVal != mResettingSystemUiFlags) {
7977            mResettingSystemUiFlags = newVal;
7978            mWindowManagerFuncs.reevaluateStatusBarVisibility();
7979        }
7980    }
7981
7982    private boolean isImmersiveMode(int vis) {
7983        final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
7984        return mNavigationBar != null
7985                && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
7986                && (vis & flags) != 0
7987                && canHideNavigationBar();
7988    }
7989
7990    private static boolean isNavBarEmpty(int systemUiFlags) {
7991        final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
7992                | View.STATUS_BAR_DISABLE_BACK
7993                | View.STATUS_BAR_DISABLE_RECENT);
7994
7995        return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
7996    }
7997
7998    /**
7999     * @return whether the navigation or status bar can be made translucent
8000     *
8001     * This should return true unless touch exploration is not enabled or
8002     * R.boolean.config_enableTranslucentDecor is false.
8003     */
8004    private boolean areTranslucentBarsAllowed() {
8005        return mTranslucentDecorEnabled;
8006    }
8007
8008    // Use this instead of checking config_showNavigationBar so that it can be consistently
8009    // overridden by qemu.hw.mainkeys in the emulator.
8010    @Override
8011    public boolean hasNavigationBar() {
8012        return mHasNavigationBar;
8013    }
8014
8015    @Override
8016    public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
8017        mLastInputMethodWindow = ime;
8018        mLastInputMethodTargetWindow = target;
8019    }
8020
8021    @Override
8022    public void setDismissImeOnBackKeyPressed(boolean newValue) {
8023        mDismissImeOnBackKeyPressed = newValue;
8024    }
8025
8026    @Override
8027    public int getInputMethodWindowVisibleHeightLw() {
8028        return mDockBottom - mCurBottom;
8029    }
8030
8031    @Override
8032    public void setCurrentUserLw(int newUserId) {
8033        mCurrentUserId = newUserId;
8034        if (mKeyguardDelegate != null) {
8035            mKeyguardDelegate.setCurrentUser(newUserId);
8036        }
8037        if (mAccessibilityShortcutController != null) {
8038            mAccessibilityShortcutController.setCurrentUser(newUserId);
8039        }
8040        StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
8041        if (statusBar != null) {
8042            statusBar.setCurrentUser(newUserId);
8043        }
8044        setLastInputMethodWindowLw(null, null);
8045    }
8046
8047    @Override
8048    public void setSwitchingUser(boolean switching) {
8049        mKeyguardDelegate.setSwitchingUser(switching);
8050    }
8051
8052    @Override
8053    public boolean canMagnifyWindow(int windowType) {
8054        switch (windowType) {
8055            case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
8056            case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
8057            case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
8058            case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
8059                return false;
8060            }
8061        }
8062        return true;
8063    }
8064
8065    @Override
8066    public boolean isTopLevelWindow(int windowType) {
8067        if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
8068                && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
8069            return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
8070        }
8071        return true;
8072    }
8073
8074    @Override
8075    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
8076        // For the upside down rotation we don't rotate seamlessly as the navigation
8077        // bar moves position.
8078        // Note most apps (using orientation:sensor or user as opposed to fullSensor)
8079        // will not enter the reverse portrait orientation, so actually the
8080        // orientation won't change at all.
8081        if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
8082            return false;
8083        }
8084        // If the navigation bar can't change sides, then it will
8085        // jump when we change orientations and we don't rotate
8086        // seamlessly.
8087        if (!mNavigationBarCanMove) {
8088            return false;
8089        }
8090        int delta = newRotation - oldRotation;
8091        if (delta < 0) delta += 4;
8092        // Likewise we don't rotate seamlessly for 180 degree rotations
8093        // in this case the surfaces never resize, and our logic to
8094        // revert the transformations on size change will fail. We could
8095        // fix this in the future with the "tagged" frames idea.
8096        if (delta == Surface.ROTATION_180) {
8097            return false;
8098        }
8099
8100        final WindowState w = mTopFullscreenOpaqueWindowState;
8101        if (w != mFocusedWindow) {
8102            return false;
8103        }
8104
8105        // We only enable seamless rotation if the top window has requested
8106        // it and is in the fullscreen opaque state. Seamless rotation
8107        // requires freezing various Surface states and won't work well
8108        // with animations, so we disable it in the animation case for now.
8109        if (w != null && !w.isAnimatingLw() &&
8110                ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) ||
8111                        (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) {
8112            return true;
8113        }
8114        return false;
8115    }
8116
8117    @Override
8118    public void dump(String prefix, PrintWriter pw, String[] args) {
8119        pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
8120                pw.print(" mSystemReady="); pw.print(mSystemReady);
8121                pw.print(" mSystemBooted="); pw.println(mSystemBooted);
8122        pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
8123                pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
8124                pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
8125                pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
8126        if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
8127                || mForceClearedSystemUiFlags != 0) {
8128            pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
8129                    pw.print(Integer.toHexString(mLastSystemUiFlags));
8130                    pw.print(" mResettingSystemUiFlags=0x");
8131                    pw.print(Integer.toHexString(mResettingSystemUiFlags));
8132                    pw.print(" mForceClearedSystemUiFlags=0x");
8133                    pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
8134        }
8135        if (mLastFocusNeedsMenu) {
8136            pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
8137                    pw.println(mLastFocusNeedsMenu);
8138        }
8139        pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
8140                pw.println(mWakeGestureEnabledSetting);
8141
8142        pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
8143        pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
8144                pw.print(" mDockMode="); pw.print(mDockMode);
8145                pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
8146                pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
8147                pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
8148        pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
8149                pw.print(" mUserRotation="); pw.print(mUserRotation);
8150                pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
8151        pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
8152        pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
8153                pw.print(mCarDockEnablesAccelerometer);
8154                pw.print(" mDeskDockEnablesAccelerometer=");
8155                pw.println(mDeskDockEnablesAccelerometer);
8156        pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
8157                pw.print(mLidKeyboardAccessibility);
8158                pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
8159                pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
8160                pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
8161        pw.print(prefix);
8162                pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
8163        pw.print(prefix);
8164                pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
8165                pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
8166        pw.print(prefix);
8167                pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
8168                pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
8169        pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
8170        pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
8171        pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
8172                pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
8173        pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
8174                pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
8175        pw.print(prefix); pw.print("mOrientationSensorEnabled=");
8176                pw.println(mOrientationSensorEnabled);
8177        pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
8178                pw.print(","); pw.print(mOverscanScreenTop);
8179                pw.print(") "); pw.print(mOverscanScreenWidth);
8180                pw.print("x"); pw.println(mOverscanScreenHeight);
8181        if (mOverscanLeft != 0 || mOverscanTop != 0
8182                || mOverscanRight != 0 || mOverscanBottom != 0) {
8183            pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
8184                    pw.print(" top="); pw.print(mOverscanTop);
8185                    pw.print(" right="); pw.print(mOverscanRight);
8186                    pw.print(" bottom="); pw.println(mOverscanBottom);
8187        }
8188        pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
8189                pw.print(mRestrictedOverscanScreenLeft);
8190                pw.print(","); pw.print(mRestrictedOverscanScreenTop);
8191                pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
8192                pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
8193        pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
8194                pw.print(","); pw.print(mUnrestrictedScreenTop);
8195                pw.print(") "); pw.print(mUnrestrictedScreenWidth);
8196                pw.print("x"); pw.println(mUnrestrictedScreenHeight);
8197        pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
8198                pw.print(","); pw.print(mRestrictedScreenTop);
8199                pw.print(") "); pw.print(mRestrictedScreenWidth);
8200                pw.print("x"); pw.println(mRestrictedScreenHeight);
8201        pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
8202                pw.print(","); pw.print(mStableFullscreenTop);
8203                pw.print(")-("); pw.print(mStableFullscreenRight);
8204                pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
8205        pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
8206                pw.print(","); pw.print(mStableTop);
8207                pw.print(")-("); pw.print(mStableRight);
8208                pw.print(","); pw.print(mStableBottom); pw.println(")");
8209        pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
8210                pw.print(","); pw.print(mSystemTop);
8211                pw.print(")-("); pw.print(mSystemRight);
8212                pw.print(","); pw.print(mSystemBottom); pw.println(")");
8213        pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
8214                pw.print(","); pw.print(mCurTop);
8215                pw.print(")-("); pw.print(mCurRight);
8216                pw.print(","); pw.print(mCurBottom); pw.println(")");
8217        pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
8218                pw.print(","); pw.print(mContentTop);
8219                pw.print(")-("); pw.print(mContentRight);
8220                pw.print(","); pw.print(mContentBottom); pw.println(")");
8221        pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft);
8222                pw.print(","); pw.print(mVoiceContentTop);
8223                pw.print(")-("); pw.print(mVoiceContentRight);
8224                pw.print(","); pw.print(mVoiceContentBottom); pw.println(")");
8225        pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
8226                pw.print(","); pw.print(mDockTop);
8227                pw.print(")-("); pw.print(mDockRight);
8228                pw.print(","); pw.print(mDockBottom); pw.println(")");
8229        pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
8230                pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
8231        pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
8232                pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
8233                pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
8234        if (mLastInputMethodWindow != null) {
8235            pw.print(prefix); pw.print("mLastInputMethodWindow=");
8236                    pw.println(mLastInputMethodWindow);
8237        }
8238        if (mLastInputMethodTargetWindow != null) {
8239            pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
8240                    pw.println(mLastInputMethodTargetWindow);
8241        }
8242        pw.print(prefix); pw.print("mDismissImeOnBackKeyPressed=");
8243                pw.println(mDismissImeOnBackKeyPressed);
8244        if (mStatusBar != null) {
8245            pw.print(prefix); pw.print("mStatusBar=");
8246                    pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
8247                    pw.println(isStatusBarKeyguard());
8248        }
8249        if (mNavigationBar != null) {
8250            pw.print(prefix); pw.print("mNavigationBar=");
8251                    pw.println(mNavigationBar);
8252        }
8253        if (mFocusedWindow != null) {
8254            pw.print(prefix); pw.print("mFocusedWindow=");
8255                    pw.println(mFocusedWindow);
8256        }
8257        if (mFocusedApp != null) {
8258            pw.print(prefix); pw.print("mFocusedApp=");
8259                    pw.println(mFocusedApp);
8260        }
8261        if (mTopFullscreenOpaqueWindowState != null) {
8262            pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
8263                    pw.println(mTopFullscreenOpaqueWindowState);
8264        }
8265        if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
8266            pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
8267                    pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
8268        }
8269        if (mForcingShowNavBar) {
8270            pw.print(prefix); pw.print("mForcingShowNavBar=");
8271                    pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
8272                    pw.println(mForcingShowNavBarLayer);
8273        }
8274        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
8275                pw.print(" mKeyguardOccluded="); pw.println(mKeyguardOccluded);
8276                pw.print(" mKeyguardOccludedChanged="); pw.println(mKeyguardOccludedChanged);
8277                pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded);
8278        pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
8279                pw.print(" mForceStatusBarFromKeyguard=");
8280                pw.println(mForceStatusBarFromKeyguard);
8281        pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
8282        pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
8283                pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
8284                pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
8285        pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
8286                pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
8287                pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior);
8288                pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
8289        pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
8290                pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
8291        pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
8292                pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
8293        pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
8294                pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
8295        pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
8296        if (mHasFeatureLeanback) {
8297            pw.print(prefix);
8298            pw.print("mAccessibilityTvKey1Pressed="); pw.println(mAccessibilityTvKey1Pressed);
8299            pw.print(prefix);
8300            pw.print("mAccessibilityTvKey2Pressed="); pw.println(mAccessibilityTvKey2Pressed);
8301            pw.print(prefix);
8302            pw.print("mAccessibilityTvScheduled="); pw.println(mAccessibilityTvScheduled);
8303        }
8304
8305        mGlobalKeyManager.dump(prefix, pw);
8306        mStatusBarController.dump(pw, prefix);
8307        mNavigationBarController.dump(pw, prefix);
8308        PolicyControl.dump(prefix, pw);
8309
8310        if (mWakeGestureListener != null) {
8311            mWakeGestureListener.dump(pw, prefix);
8312        }
8313        if (mOrientationListener != null) {
8314            mOrientationListener.dump(pw, prefix);
8315        }
8316        if (mBurnInProtectionHelper != null) {
8317            mBurnInProtectionHelper.dump(prefix, pw);
8318        }
8319        if (mKeyguardDelegate != null) {
8320            mKeyguardDelegate.dump(prefix, pw);
8321        }
8322    }
8323}
8324