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