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