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