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