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