PhoneWindowManager.java revision 9ff881ad72694e77e13978340aa7c4b5d6d41741
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.getMultiPressTimeout());
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                    pf.left = df.left = of.left = cf.left = hasNavBar
5040                            ? mDockLeft : mUnrestrictedScreenLeft;
5041                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
5042                    pf.right = df.right = of.right = cf.right = hasNavBar
5043                            ? mRestrictedScreenLeft + mRestrictedScreenWidth
5044                            : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5045                    pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar
5046                            ? mRestrictedScreenTop + mRestrictedScreenHeight
5047                            : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5048                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
5049                            "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
5050                            pf.left, pf.top, pf.right, pf.bottom));
5051                } else if (attrs.type == TYPE_VOLUME_OVERLAY) {
5052                    // Volume overlay covers everything, including the status and navbar
5053                    pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
5054                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
5055                    pf.right = df.right = of.right = cf.right =
5056                            mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5057                    pf.bottom = df.bottom = of.bottom = cf.bottom =
5058                            mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5059                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
5060                                    "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
5061                                    pf.left, pf.top, pf.right, pf.bottom));
5062                } else if (attrs.type == TYPE_NAVIGATION_BAR
5063                        || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
5064                    // The navigation bar has Real Ultimate Power.
5065                    pf.left = df.left = of.left = mUnrestrictedScreenLeft;
5066                    pf.top = df.top = of.top = mUnrestrictedScreenTop;
5067                    pf.right = df.right = of.right = mUnrestrictedScreenLeft
5068                            + mUnrestrictedScreenWidth;
5069                    pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop
5070                            + mUnrestrictedScreenHeight;
5071                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
5072                                    "Laying out navigation bar window: (%d,%d - %d,%d)",
5073                                    pf.left, pf.top, pf.right, pf.bottom));
5074                } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
5075                                || attrs.type == TYPE_BOOT_PROGRESS
5076                                || attrs.type == TYPE_SCREENSHOT)
5077                        && ((fl & FLAG_FULLSCREEN) != 0)) {
5078                    // Fullscreen secure system overlays get what they ask for. Screenshot region
5079                    // selection overlay should also expand to full screen.
5080                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
5081                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
5082                    pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
5083                            + mOverscanScreenWidth;
5084                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
5085                            + mOverscanScreenHeight;
5086                } else if (attrs.type == TYPE_BOOT_PROGRESS) {
5087                    // Boot progress screen always covers entire display.
5088                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
5089                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
5090                    pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
5091                            + mOverscanScreenWidth;
5092                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
5093                            + mOverscanScreenHeight;
5094                } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
5095                        && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
5096                        && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
5097                    // Asking to layout into the overscan region, so give it that pure
5098                    // unrestricted area.
5099                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
5100                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
5101                    pf.right = df.right = of.right = cf.right
5102                            = mOverscanScreenLeft + mOverscanScreenWidth;
5103                    pf.bottom = df.bottom = of.bottom = cf.bottom
5104                            = mOverscanScreenTop + mOverscanScreenHeight;
5105                } else if (canHideNavigationBar()
5106                        && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
5107                        && (attrs.type == TYPE_STATUS_BAR
5108                            || attrs.type == TYPE_TOAST
5109                            || attrs.type == TYPE_DOCK_DIVIDER
5110                            || attrs.type == TYPE_VOICE_INTERACTION_STARTING
5111                            || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
5112                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
5113                    // Asking for layout as if the nav bar is hidden, lets the
5114                    // application extend into the unrestricted screen area.  We
5115                    // only do this for application windows (or toasts) to ensure no window that
5116                    // can be above the nav bar can do this.
5117                    // XXX This assumes that an app asking for this will also
5118                    // ask for layout in only content.  We can't currently figure out
5119                    // what the screen would be if only laying out to hide the nav bar.
5120                    pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
5121                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
5122                    pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft
5123                            + mUnrestrictedScreenWidth;
5124                    pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
5125                            + mUnrestrictedScreenHeight;
5126                } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
5127                    pf.left = df.left = of.left = mRestrictedScreenLeft;
5128                    pf.top = df.top = of.top  = mRestrictedScreenTop;
5129                    pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
5130                    pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop
5131                            + mRestrictedScreenHeight;
5132                    if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5133                        cf.left = mDockLeft;
5134                        cf.top = mDockTop;
5135                        cf.right = mDockRight;
5136                        cf.bottom = mDockBottom;
5137                    } else {
5138                        cf.left = mContentLeft;
5139                        cf.top = mContentTop;
5140                        cf.right = mContentRight;
5141                        cf.bottom = mContentBottom;
5142                    }
5143                } else {
5144                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
5145                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
5146                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
5147                            + mRestrictedScreenWidth;
5148                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
5149                            + mRestrictedScreenHeight;
5150                }
5151
5152                applyStableConstraints(sysUiFl, fl, cf);
5153
5154                if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5155                    vf.left = mCurLeft;
5156                    vf.top = mCurTop;
5157                    vf.right = mCurRight;
5158                    vf.bottom = mCurBottom;
5159                } else {
5160                    vf.set(cf);
5161                }
5162            } else if (attached != null) {
5163                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5164                        "): attached to " + attached);
5165                // A child window should be placed inside of the same visible
5166                // frame that its parent had.
5167                setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf);
5168            } else {
5169                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5170                        "): normal window");
5171                // Otherwise, a normal window must be placed inside the content
5172                // of all screen decorations.
5173                if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) {
5174                    // Status bar panels and the volume dialog are the only windows who can go on
5175                    // top of the status bar.  They are protected by the STATUS_BAR_SERVICE
5176                    // permission, so they have the same privileges as the status
5177                    // bar itself.
5178                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
5179                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
5180                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
5181                            + mRestrictedScreenWidth;
5182                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
5183                            + mRestrictedScreenHeight;
5184                } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) {
5185                    // These dialogs are stable to interim decor changes.
5186                    pf.left = df.left = of.left = cf.left = mStableLeft;
5187                    pf.top = df.top = of.top = cf.top = mStableTop;
5188                    pf.right = df.right = of.right = cf.right = mStableRight;
5189                    pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom;
5190                } else {
5191                    pf.left = mContentLeft;
5192                    pf.top = mContentTop;
5193                    pf.right = mContentRight;
5194                    pf.bottom = mContentBottom;
5195                    if (win.isVoiceInteraction()) {
5196                        df.left = of.left = cf.left = mVoiceContentLeft;
5197                        df.top = of.top = cf.top = mVoiceContentTop;
5198                        df.right = of.right = cf.right = mVoiceContentRight;
5199                        df.bottom = of.bottom = cf.bottom = mVoiceContentBottom;
5200                    } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5201                        df.left = of.left = cf.left = mDockLeft;
5202                        df.top = of.top = cf.top = mDockTop;
5203                        df.right = of.right = cf.right = mDockRight;
5204                        df.bottom = of.bottom = cf.bottom = mDockBottom;
5205                    } else {
5206                        df.left = of.left = cf.left = mContentLeft;
5207                        df.top = of.top = cf.top = mContentTop;
5208                        df.right = of.right = cf.right = mContentRight;
5209                        df.bottom = of.bottom = cf.bottom = mContentBottom;
5210                    }
5211                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5212                        vf.left = mCurLeft;
5213                        vf.top = mCurTop;
5214                        vf.right = mCurRight;
5215                        vf.bottom = mCurBottom;
5216                    } else {
5217                        vf.set(cf);
5218                    }
5219                }
5220            }
5221        }
5222
5223        // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
5224        // Also, we don't allow windows in multi-window mode to extend out of the screen.
5225        if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR
5226                && !win.isInMultiWindowMode()) {
5227            df.left = df.top = -10000;
5228            df.right = df.bottom = 10000;
5229            if (attrs.type != TYPE_WALLPAPER) {
5230                of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
5231                of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
5232            }
5233        }
5234
5235        // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we
5236        // need to provide information to the clients that want to pretend that you can draw there.
5237        // We only want to apply outsets to certain types of windows. For example, we never want to
5238        // apply the outsets to floating dialogs, because they wouldn't make sense there.
5239        final boolean useOutsets = shouldUseOutsets(attrs, fl);
5240        if (isDefaultDisplay && useOutsets) {
5241            osf = mTmpOutsetFrame;
5242            osf.set(cf.left, cf.top, cf.right, cf.bottom);
5243            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
5244            if (outset > 0) {
5245                int rotation = mDisplayRotation;
5246                if (rotation == Surface.ROTATION_0) {
5247                    osf.bottom += outset;
5248                } else if (rotation == Surface.ROTATION_90) {
5249                    osf.right += outset;
5250                } else if (rotation == Surface.ROTATION_180) {
5251                    osf.top -= outset;
5252                } else if (rotation == Surface.ROTATION_270) {
5253                    osf.left -= outset;
5254                }
5255                if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset
5256                        + " with rotation " + rotation + ", result: " + osf);
5257            }
5258        }
5259
5260        if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
5261                + ": sim=#" + Integer.toHexString(sim)
5262                + " attach=" + attached + " type=" + attrs.type
5263                + String.format(" flags=0x%08x", fl)
5264                + " pf=" + pf.toShortString() + " df=" + df.toShortString()
5265                + " of=" + of.toShortString()
5266                + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
5267                + " dcf=" + dcf.toShortString()
5268                + " sf=" + sf.toShortString()
5269                + " osf=" + (osf == null ? "null" : osf.toShortString()));
5270
5271        win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf);
5272
5273        // Dock windows carve out the bottom of the screen, so normal windows
5274        // can't appear underneath them.
5275        if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleLw()
5276                && !win.getGivenInsetsPendingLw()) {
5277            setLastInputMethodWindowLw(null, null);
5278            offsetInputMethodWindowLw(win);
5279        }
5280        if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleLw()
5281                && !win.getGivenInsetsPendingLw()) {
5282            offsetVoiceInputWindowLw(win);
5283        }
5284    }
5285
5286    private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) {
5287
5288        // The wallpaper also has Real Ultimate Power, but we want to tell
5289        // it about the overscan area.
5290        pf.left = df.left = mOverscanScreenLeft;
5291        pf.top = df.top = mOverscanScreenTop;
5292        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
5293        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
5294        of.left = cf.left = mUnrestrictedScreenLeft;
5295        of.top = cf.top = mUnrestrictedScreenTop;
5296        of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5297        of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5298    }
5299
5300    private void offsetInputMethodWindowLw(WindowState win) {
5301        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5302        top += win.getGivenContentInsetsLw().top;
5303        if (mContentBottom > top) {
5304            mContentBottom = top;
5305        }
5306        if (mVoiceContentBottom > top) {
5307            mVoiceContentBottom = top;
5308        }
5309        top = win.getVisibleFrameLw().top;
5310        top += win.getGivenVisibleInsetsLw().top;
5311        if (mCurBottom > top) {
5312            mCurBottom = top;
5313        }
5314        if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
5315                + mDockBottom + " mContentBottom="
5316                + mContentBottom + " mCurBottom=" + mCurBottom);
5317    }
5318
5319    private void offsetVoiceInputWindowLw(WindowState win) {
5320        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5321        top += win.getGivenContentInsetsLw().top;
5322        if (mVoiceContentBottom > top) {
5323            mVoiceContentBottom = top;
5324        }
5325    }
5326
5327    /** {@inheritDoc} */
5328    @Override
5329    public void finishLayoutLw() {
5330        return;
5331    }
5332
5333    /** {@inheritDoc} */
5334    @Override
5335    public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
5336        mTopFullscreenOpaqueWindowState = null;
5337        mTopFullscreenOpaqueOrDimmingWindowState = null;
5338        mTopDockedOpaqueWindowState = null;
5339        mTopDockedOpaqueOrDimmingWindowState = null;
5340        mForceStatusBar = false;
5341        mForceStatusBarFromKeyguard = false;
5342        mForceStatusBarTransparent = false;
5343        mForcingShowNavBar = false;
5344        mForcingShowNavBarLayer = -1;
5345
5346        mAllowLockscreenWhenOn = false;
5347        mShowingDream = false;
5348    }
5349
5350    /** {@inheritDoc} */
5351    @Override
5352    public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
5353            WindowState attached, WindowState imeTarget) {
5354        final boolean affectsSystemUi = win.canAffectSystemUiFlags();
5355        if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": affectsSystemUi=" + affectsSystemUi);
5356        applyKeyguardPolicyLw(win, imeTarget);
5357        final int fl = PolicyControl.getWindowFlags(win, attrs);
5358        if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi
5359                && attrs.type == TYPE_INPUT_METHOD) {
5360            mForcingShowNavBar = true;
5361            mForcingShowNavBarLayer = win.getSurfaceLayer();
5362        }
5363        if (attrs.type == TYPE_STATUS_BAR) {
5364            if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
5365                mForceStatusBarFromKeyguard = true;
5366            }
5367            if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
5368                mForceStatusBarTransparent = true;
5369            }
5370        }
5371
5372        boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
5373                && attrs.type < FIRST_SYSTEM_WINDOW;
5374        final int stackId = win.getStackId();
5375        if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi) {
5376            if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
5377                mForceStatusBar = true;
5378            }
5379            if (attrs.type == TYPE_DREAM) {
5380                // If the lockscreen was showing when the dream started then wait
5381                // for the dream to draw before hiding the lockscreen.
5382                if (!mDreamingLockscreen
5383                        || (win.isVisibleLw() && win.hasDrawnLw())) {
5384                    mShowingDream = true;
5385                    appWindow = true;
5386                }
5387            }
5388
5389            // For app windows that are not attached, we decide if all windows in the app they
5390            // represent should be hidden or if we should hide the lockscreen. For attached app
5391            // windows we defer the decision to the window it is attached to.
5392            if (appWindow && attached == null) {
5393                if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
5394                    if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
5395                    mTopFullscreenOpaqueWindowState = win;
5396                    if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5397                        mTopFullscreenOpaqueOrDimmingWindowState = win;
5398                    }
5399                    if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
5400                        mAllowLockscreenWhenOn = true;
5401                    }
5402                }
5403            }
5404        }
5405
5406        // Voice interaction overrides both top fullscreen and top docked.
5407        if (affectsSystemUi && win.getAttrs().type == TYPE_VOICE_INTERACTION) {
5408            if (mTopFullscreenOpaqueWindowState == null) {
5409                mTopFullscreenOpaqueWindowState = win;
5410                if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5411                    mTopFullscreenOpaqueOrDimmingWindowState = win;
5412                }
5413            }
5414            if (mTopDockedOpaqueWindowState == null) {
5415                mTopDockedOpaqueWindowState = win;
5416                if (mTopDockedOpaqueOrDimmingWindowState == null) {
5417                    mTopDockedOpaqueOrDimmingWindowState = win;
5418                }
5419            }
5420        }
5421
5422        // Keep track of the window if it's dimming but not necessarily fullscreen.
5423        if (mTopFullscreenOpaqueOrDimmingWindowState == null && affectsSystemUi
5424                && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
5425            mTopFullscreenOpaqueOrDimmingWindowState = win;
5426        }
5427
5428        // We need to keep track of the top "fullscreen" opaque window for the docked stack
5429        // separately, because both the "real fullscreen" opaque window and the one for the docked
5430        // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
5431        if (mTopDockedOpaqueWindowState == null && affectsSystemUi && appWindow && attached == null
5432                && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
5433            mTopDockedOpaqueWindowState = win;
5434            if (mTopDockedOpaqueOrDimmingWindowState == null) {
5435                mTopDockedOpaqueOrDimmingWindowState = win;
5436            }
5437        }
5438
5439        // Also keep track of any windows that are dimming but not necessarily fullscreen in the
5440        // docked stack.
5441        if (mTopDockedOpaqueOrDimmingWindowState == null && affectsSystemUi && win.isDimming()
5442                && stackId == DOCKED_STACK_ID) {
5443            mTopDockedOpaqueOrDimmingWindowState = win;
5444        }
5445    }
5446
5447    private void applyKeyguardPolicyLw(WindowState win, WindowState imeTarget) {
5448        if (canBeHiddenByKeyguardLw(win)) {
5449            if (shouldBeHiddenByKeyguard(win, imeTarget)) {
5450                win.hideLw(false /* doAnimation */);
5451            } else {
5452                win.showLw(false /* doAnimation */);
5453            }
5454        }
5455    }
5456
5457    private boolean isFullscreen(WindowManager.LayoutParams attrs) {
5458        return attrs.x == 0 && attrs.y == 0
5459                && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
5460                && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
5461    }
5462
5463    /** {@inheritDoc} */
5464    @Override
5465    public int finishPostLayoutPolicyLw() {
5466        int changes = 0;
5467        boolean topIsFullscreen = false;
5468
5469        final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
5470                ? mTopFullscreenOpaqueWindowState.getAttrs()
5471                : null;
5472
5473        // If we are not currently showing a dream then remember the current
5474        // lockscreen state.  We will use this to determine whether the dream
5475        // started while the lockscreen was showing and remember this state
5476        // while the dream is showing.
5477        if (!mShowingDream) {
5478            mDreamingLockscreen = isKeyguardShowingAndNotOccluded();
5479            if (mDreamingSleepTokenNeeded) {
5480                mDreamingSleepTokenNeeded = false;
5481                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
5482            }
5483        } else {
5484            if (!mDreamingSleepTokenNeeded) {
5485                mDreamingSleepTokenNeeded = true;
5486                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget();
5487            }
5488        }
5489
5490        if (mStatusBar != null) {
5491            if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
5492                    + " forcefkg=" + mForceStatusBarFromKeyguard
5493                    + " top=" + mTopFullscreenOpaqueWindowState);
5494            boolean shouldBeTransparent = mForceStatusBarTransparent
5495                    && !mForceStatusBar
5496                    && !mForceStatusBarFromKeyguard;
5497            if (!shouldBeTransparent) {
5498                mStatusBarController.setShowTransparent(false /* transparent */);
5499            } else if (!mStatusBar.isVisibleLw()) {
5500                mStatusBarController.setShowTransparent(true /* transparent */);
5501            }
5502
5503            WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs();
5504            boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT
5505                    && statusBarAttrs.width == MATCH_PARENT;
5506            if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
5507                    || statusBarExpanded) {
5508                if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
5509                if (mStatusBarController.setBarShowingLw(true)) {
5510                    changes |= FINISH_LAYOUT_REDO_LAYOUT;
5511                }
5512                // Maintain fullscreen layout until incoming animation is complete.
5513                topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
5514                // Transient status bar on the lockscreen is not allowed
5515                if ((mForceStatusBarFromKeyguard || statusBarExpanded)
5516                        && mStatusBarController.isTransientShowing()) {
5517                    mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
5518                            mLastSystemUiFlags, mLastSystemUiFlags);
5519                }
5520                if (statusBarExpanded && mNavigationBar != null) {
5521                    if (mNavigationBarController.setBarShowingLw(true)) {
5522                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5523                    }
5524                }
5525            } else if (mTopFullscreenOpaqueWindowState != null) {
5526                final int fl = PolicyControl.getWindowFlags(null, lp);
5527                if (localLOGV) {
5528                    Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
5529                            + " shown position: "
5530                            + mTopFullscreenOpaqueWindowState.getShownPositionLw());
5531                    Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
5532                            + " lp.flags=0x" + Integer.toHexString(fl));
5533                }
5534                topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
5535                        || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
5536                // The subtle difference between the window for mTopFullscreenOpaqueWindowState
5537                // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
5538                // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
5539                // case though.
5540                if (mStatusBarController.isTransientShowing()) {
5541                    if (mStatusBarController.setBarShowingLw(true)) {
5542                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5543                    }
5544                } else if (topIsFullscreen
5545                        && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)
5546                        && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) {
5547                    if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
5548                    if (mStatusBarController.setBarShowingLw(false)) {
5549                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5550                    } else {
5551                        if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
5552                    }
5553                } else {
5554                    if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
5555                    if (mStatusBarController.setBarShowingLw(true)) {
5556                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5557                    }
5558                }
5559            }
5560        }
5561
5562        if (mTopIsFullscreen != topIsFullscreen) {
5563            if (!topIsFullscreen) {
5564                // Force another layout when status bar becomes fully shown.
5565                changes |= FINISH_LAYOUT_REDO_LAYOUT;
5566            }
5567            mTopIsFullscreen = topIsFullscreen;
5568        }
5569
5570        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5571            // If the navigation bar has been hidden or shown, we need to do another
5572            // layout pass to update that window.
5573            changes |= FINISH_LAYOUT_REDO_LAYOUT;
5574        }
5575
5576        if (mShowingDream != mLastShowingDream) {
5577            mLastShowingDream = mShowingDream;
5578            mWindowManagerFuncs.notifyShowingDreamChanged();
5579        }
5580
5581        // update since mAllowLockscreenWhenOn might have changed
5582        updateLockScreenTimeout();
5583        return changes;
5584    }
5585
5586    /**
5587     * Updates the occluded state of the Keyguard.
5588     *
5589     * @return Whether the flags have changed and we have to redo the layout.
5590     */
5591    private boolean setKeyguardOccludedLw(boolean isOccluded, boolean force) {
5592        if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded);
5593        final boolean wasOccluded = mKeyguardOccluded;
5594        final boolean showing = mKeyguardDelegate.isShowing();
5595        final boolean changed = wasOccluded != isOccluded || force;
5596        if (!isOccluded && changed && showing) {
5597            mKeyguardOccluded = false;
5598            mKeyguardDelegate.setOccluded(false, true /* animate */);
5599            if (mStatusBar != null) {
5600                mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
5601                if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
5602                    mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5603                }
5604            }
5605            return true;
5606        } else if (isOccluded && changed && showing) {
5607            mKeyguardOccluded = true;
5608            mKeyguardDelegate.setOccluded(true, false /* animate */);
5609            if (mStatusBar != null) {
5610                mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
5611                mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
5612            }
5613            return true;
5614        } else if (changed) {
5615            mKeyguardOccluded = isOccluded;
5616            mKeyguardDelegate.setOccluded(isOccluded, false /* animate */);
5617            return false;
5618        } else {
5619            return false;
5620        }
5621    }
5622
5623    private boolean isStatusBarKeyguard() {
5624        return mStatusBar != null
5625                && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
5626    }
5627
5628    @Override
5629    public boolean allowAppAnimationsLw() {
5630        if (mShowingDream) {
5631            // If keyguard or dreams is currently visible, no reason to animate behind it.
5632            return false;
5633        }
5634        return true;
5635    }
5636
5637    @Override
5638    public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
5639        mFocusedWindow = newFocus;
5640        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5641            // If the navigation bar has been hidden or shown, we need to do another
5642            // layout pass to update that window.
5643            return FINISH_LAYOUT_REDO_LAYOUT;
5644        }
5645        return 0;
5646    }
5647
5648    /** {@inheritDoc} */
5649    @Override
5650    public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
5651        // lid changed state
5652        final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
5653        if (newLidState == mLidState) {
5654            return;
5655        }
5656
5657        mLidState = newLidState;
5658        applyLidSwitchState();
5659        updateRotation(true);
5660
5661        if (lidOpen) {
5662            wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
5663                    "android.policy:LID");
5664        } else if (!mLidControlsSleep) {
5665            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
5666        }
5667    }
5668
5669    @Override
5670    public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
5671        int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
5672        if (mCameraLensCoverState == lensCoverState) {
5673            return;
5674        }
5675        if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
5676                lensCoverState == CAMERA_LENS_UNCOVERED) {
5677            Intent intent;
5678            final boolean keyguardActive = mKeyguardDelegate == null ? false :
5679                    mKeyguardDelegate.isShowing();
5680            if (keyguardActive) {
5681                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
5682            } else {
5683                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
5684            }
5685            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
5686                    "android.policy:CAMERA_COVER");
5687            startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
5688        }
5689        mCameraLensCoverState = lensCoverState;
5690    }
5691
5692    void setHdmiPlugged(boolean plugged) {
5693        if (mHdmiPlugged != plugged) {
5694            mHdmiPlugged = plugged;
5695            updateRotation(true, true);
5696            Intent intent = new Intent(ACTION_HDMI_PLUGGED);
5697            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
5698            intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
5699            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
5700        }
5701    }
5702
5703    void initializeHdmiState() {
5704        boolean plugged = false;
5705        // watch for HDMI plug messages if the hdmi switch exists
5706        if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
5707            mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
5708
5709            final String filename = "/sys/class/switch/hdmi/state";
5710            FileReader reader = null;
5711            try {
5712                reader = new FileReader(filename);
5713                char[] buf = new char[15];
5714                int n = reader.read(buf);
5715                if (n > 1) {
5716                    plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
5717                }
5718            } catch (IOException ex) {
5719                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5720            } catch (NumberFormatException ex) {
5721                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5722            } finally {
5723                if (reader != null) {
5724                    try {
5725                        reader.close();
5726                    } catch (IOException ex) {
5727                    }
5728                }
5729            }
5730        }
5731        // This dance forces the code in setHdmiPlugged to run.
5732        // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
5733        mHdmiPlugged = !plugged;
5734        setHdmiPlugged(!mHdmiPlugged);
5735    }
5736
5737    final Object mScreenshotLock = new Object();
5738    ServiceConnection mScreenshotConnection = null;
5739
5740    final Runnable mScreenshotTimeout = new Runnable() {
5741        @Override public void run() {
5742            synchronized (mScreenshotLock) {
5743                if (mScreenshotConnection != null) {
5744                    mContext.unbindService(mScreenshotConnection);
5745                    mScreenshotConnection = null;
5746                    notifyScreenshotError();
5747                }
5748            }
5749        }
5750    };
5751
5752    // Assume this is called from the Handler thread.
5753    private void takeScreenshot(final int screenshotType) {
5754        synchronized (mScreenshotLock) {
5755            if (mScreenshotConnection != null) {
5756                return;
5757            }
5758            final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
5759                    SYSUI_SCREENSHOT_SERVICE);
5760            final Intent serviceIntent = new Intent();
5761            serviceIntent.setComponent(serviceComponent);
5762            ServiceConnection conn = new ServiceConnection() {
5763                @Override
5764                public void onServiceConnected(ComponentName name, IBinder service) {
5765                    synchronized (mScreenshotLock) {
5766                        if (mScreenshotConnection != this) {
5767                            return;
5768                        }
5769                        Messenger messenger = new Messenger(service);
5770                        Message msg = Message.obtain(null, screenshotType);
5771                        final ServiceConnection myConn = this;
5772                        Handler h = new Handler(mHandler.getLooper()) {
5773                            @Override
5774                            public void handleMessage(Message msg) {
5775                                synchronized (mScreenshotLock) {
5776                                    if (mScreenshotConnection == myConn) {
5777                                        mContext.unbindService(mScreenshotConnection);
5778                                        mScreenshotConnection = null;
5779                                        mHandler.removeCallbacks(mScreenshotTimeout);
5780                                    }
5781                                }
5782                            }
5783                        };
5784                        msg.replyTo = new Messenger(h);
5785                        msg.arg1 = msg.arg2 = 0;
5786                        if (mStatusBar != null && mStatusBar.isVisibleLw())
5787                            msg.arg1 = 1;
5788                        if (mNavigationBar != null && mNavigationBar.isVisibleLw())
5789                            msg.arg2 = 1;
5790                        try {
5791                            messenger.send(msg);
5792                        } catch (RemoteException e) {
5793                        }
5794                    }
5795                }
5796
5797                @Override
5798                public void onServiceDisconnected(ComponentName name) {
5799                    synchronized (mScreenshotLock) {
5800                        if (mScreenshotConnection != null) {
5801                            mContext.unbindService(mScreenshotConnection);
5802                            mScreenshotConnection = null;
5803                            mHandler.removeCallbacks(mScreenshotTimeout);
5804                            notifyScreenshotError();
5805                        }
5806                    }
5807                }
5808            };
5809            if (mContext.bindServiceAsUser(serviceIntent, conn,
5810                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
5811                    UserHandle.CURRENT)) {
5812                mScreenshotConnection = conn;
5813                mHandler.postDelayed(mScreenshotTimeout, 10000);
5814            }
5815        }
5816    }
5817
5818    /**
5819     * Notifies the screenshot service to show an error.
5820     */
5821    private void notifyScreenshotError() {
5822        // If the service process is killed, then ask it to clean up after itself
5823        final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
5824                SYSUI_SCREENSHOT_ERROR_RECEIVER);
5825        Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
5826        errorIntent.setComponent(errorComponent);
5827        errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
5828                Intent.FLAG_RECEIVER_FOREGROUND);
5829        mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT);
5830    }
5831
5832    /** {@inheritDoc} */
5833    @Override
5834    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
5835        if (!mSystemBooted) {
5836            // If we have not yet booted, don't let key events do anything.
5837            return 0;
5838        }
5839
5840        final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
5841        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
5842        final boolean canceled = event.isCanceled();
5843        final int keyCode = event.getKeyCode();
5844
5845        final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
5846
5847        // If screen is off then we treat the case where the keyguard is open but hidden
5848        // the same as if it were open and in front.
5849        // This will prevent any keys other than the power button from waking the screen
5850        // when the keyguard is hidden by another activity.
5851        final boolean keyguardActive = (mKeyguardDelegate == null ? false :
5852                                            (interactive ?
5853                                                isKeyguardShowingAndNotOccluded() :
5854                                                mKeyguardDelegate.isShowing()));
5855
5856        if (DEBUG_INPUT) {
5857            Log.d(TAG, "interceptKeyTq keycode=" + keyCode
5858                    + " interactive=" + interactive + " keyguardActive=" + keyguardActive
5859                    + " policyFlags=" + Integer.toHexString(policyFlags));
5860        }
5861
5862        // Basic policy based on interactive state.
5863        int result;
5864        boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
5865                || event.isWakeKey();
5866        if (interactive || (isInjected && !isWakeKey)) {
5867            // When the device is interactive or the key is injected pass the
5868            // key to the application.
5869            result = ACTION_PASS_TO_USER;
5870            isWakeKey = false;
5871
5872            if (interactive) {
5873                // If the screen is awake, but the button pressed was the one that woke the device
5874                // then don't pass it to the application
5875                if (keyCode == mPendingWakeKey && !down) {
5876                    result = 0;
5877                }
5878                // Reset the pending key
5879                mPendingWakeKey = PENDING_KEY_NULL;
5880            }
5881        } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
5882            // If we're currently dozing with the screen on and the keyguard showing, pass the key
5883            // to the application but preserve its wake key status to make sure we still move
5884            // from dozing to fully interactive if we would normally go from off to fully
5885            // interactive.
5886            result = ACTION_PASS_TO_USER;
5887            // Since we're dispatching the input, reset the pending key
5888            mPendingWakeKey = PENDING_KEY_NULL;
5889        } else {
5890            // When the screen is off and the key is not injected, determine whether
5891            // to wake the device but don't pass the key to the application.
5892            result = 0;
5893            if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
5894                isWakeKey = false;
5895            }
5896            // Cache the wake key on down event so we can also avoid sending the up event to the app
5897            if (isWakeKey && down) {
5898                mPendingWakeKey = keyCode;
5899            }
5900        }
5901
5902        // If the key would be handled globally, just return the result, don't worry about special
5903        // key processing.
5904        if (isValidGlobalKey(keyCode)
5905                && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
5906            if (isWakeKey) {
5907                wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5908            }
5909            return result;
5910        }
5911
5912        boolean useHapticFeedback = down
5913                && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
5914                && event.getRepeatCount() == 0;
5915
5916        // Handle special keys.
5917        switch (keyCode) {
5918            case KeyEvent.KEYCODE_BACK: {
5919                if (down) {
5920                    interceptBackKeyDown();
5921                } else {
5922                    boolean handled = interceptBackKeyUp(event);
5923
5924                    // Don't pass back press to app if we've already handled it via long press
5925                    if (handled) {
5926                        result &= ~ACTION_PASS_TO_USER;
5927                    }
5928                }
5929                break;
5930            }
5931
5932            case KeyEvent.KEYCODE_VOLUME_DOWN:
5933            case KeyEvent.KEYCODE_VOLUME_UP:
5934            case KeyEvent.KEYCODE_VOLUME_MUTE: {
5935                if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
5936                    if (down) {
5937                        if (interactive && !mScreenshotChordVolumeDownKeyTriggered
5938                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5939                            mScreenshotChordVolumeDownKeyTriggered = true;
5940                            mScreenshotChordVolumeDownKeyTime = event.getDownTime();
5941                            mScreenshotChordVolumeDownKeyConsumed = false;
5942                            cancelPendingPowerKeyAction();
5943                            interceptScreenshotChord();
5944                            interceptAccessibilityShortcutChord();
5945                        }
5946                    } else {
5947                        mScreenshotChordVolumeDownKeyTriggered = false;
5948                        cancelPendingScreenshotChordAction();
5949                        cancelPendingAccessibilityShortcutAction();
5950                    }
5951                } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
5952                    if (down) {
5953                        if (interactive && !mA11yShortcutChordVolumeUpKeyTriggered
5954                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5955                            mA11yShortcutChordVolumeUpKeyTriggered = true;
5956                            mA11yShortcutChordVolumeUpKeyTime = event.getDownTime();
5957                            mA11yShortcutChordVolumeUpKeyConsumed = false;
5958                            cancelPendingPowerKeyAction();
5959                            cancelPendingScreenshotChordAction();
5960                            interceptAccessibilityShortcutChord();
5961                        }
5962                    } else {
5963                        mA11yShortcutChordVolumeUpKeyTriggered = false;
5964                        cancelPendingScreenshotChordAction();
5965                        cancelPendingAccessibilityShortcutAction();
5966                    }
5967                }
5968                if (down) {
5969                    TelecomManager telecomManager = getTelecommService();
5970                    if (telecomManager != null) {
5971                        if (telecomManager.isRinging()) {
5972                            // If an incoming call is ringing, either VOLUME key means
5973                            // "silence ringer".  We handle these keys here, rather than
5974                            // in the InCallScreen, to make sure we'll respond to them
5975                            // even if the InCallScreen hasn't come to the foreground yet.
5976                            // Look for the DOWN event here, to agree with the "fallback"
5977                            // behavior in the InCallScreen.
5978                            Log.i(TAG, "interceptKeyBeforeQueueing:"
5979                                  + " VOLUME key-down while ringing: Silence ringer!");
5980
5981                            // Silence the ringer.  (It's safe to call this
5982                            // even if the ringer has already been silenced.)
5983                            telecomManager.silenceRinger();
5984
5985                            // And *don't* pass this key thru to the current activity
5986                            // (which is probably the InCallScreen.)
5987                            result &= ~ACTION_PASS_TO_USER;
5988                            break;
5989                        }
5990                    }
5991                    int audioMode = AudioManager.MODE_NORMAL;
5992                    try {
5993                        audioMode = getAudioService().getMode();
5994                    } catch (Exception e) {
5995                        Log.e(TAG, "Error getting AudioService in interceptKeyBeforeQueueing.", e);
5996                    }
5997                    boolean isInCall = (telecomManager != null && telecomManager.isInCall()) ||
5998                            audioMode == AudioManager.MODE_IN_COMMUNICATION;
5999                    if (isInCall && (result & ACTION_PASS_TO_USER) == 0) {
6000                        // If we are in call but we decided not to pass the key to
6001                        // the application, just pass it to the session service.
6002                        MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
6003                                event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
6004                        break;
6005                    }
6006
6007                }
6008                if (mUseTvRouting || mHandleVolumeKeysInWM) {
6009                    // Defer special key handlings to
6010                    // {@link interceptKeyBeforeDispatching()}.
6011                    result |= ACTION_PASS_TO_USER;
6012                } else if ((result & ACTION_PASS_TO_USER) == 0) {
6013                    // If we aren't passing to the user and no one else
6014                    // handled it send it to the session manager to
6015                    // figure out.
6016                    MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
6017                            event, AudioManager.USE_DEFAULT_STREAM_TYPE, true);
6018                }
6019                break;
6020            }
6021
6022            case KeyEvent.KEYCODE_ENDCALL: {
6023                result &= ~ACTION_PASS_TO_USER;
6024                if (down) {
6025                    TelecomManager telecomManager = getTelecommService();
6026                    boolean hungUp = false;
6027                    if (telecomManager != null) {
6028                        hungUp = telecomManager.endCall();
6029                    }
6030                    if (interactive && !hungUp) {
6031                        mEndCallKeyHandled = false;
6032                        mHandler.postDelayed(mEndCallLongPress,
6033                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
6034                    } else {
6035                        mEndCallKeyHandled = true;
6036                    }
6037                } else {
6038                    if (!mEndCallKeyHandled) {
6039                        mHandler.removeCallbacks(mEndCallLongPress);
6040                        if (!canceled) {
6041                            if ((mEndcallBehavior
6042                                    & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
6043                                if (goHome()) {
6044                                    break;
6045                                }
6046                            }
6047                            if ((mEndcallBehavior
6048                                    & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
6049                                mPowerManager.goToSleep(event.getEventTime(),
6050                                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
6051                                isWakeKey = false;
6052                            }
6053                        }
6054                    }
6055                }
6056                break;
6057            }
6058
6059            case KeyEvent.KEYCODE_POWER: {
6060                // Any activity on the power button stops the accessibility shortcut
6061                cancelPendingAccessibilityShortcutAction();
6062                result &= ~ACTION_PASS_TO_USER;
6063                isWakeKey = false; // wake-up will be handled separately
6064                if (down) {
6065                    interceptPowerKeyDown(event, interactive);
6066                } else {
6067                    interceptPowerKeyUp(event, interactive, canceled);
6068                }
6069                break;
6070            }
6071
6072            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
6073                // fall through
6074            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
6075                // fall through
6076            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
6077                // fall through
6078            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
6079                result &= ~ACTION_PASS_TO_USER;
6080                interceptSystemNavigationKey(event);
6081                break;
6082            }
6083
6084            case KeyEvent.KEYCODE_SLEEP: {
6085                result &= ~ACTION_PASS_TO_USER;
6086                isWakeKey = false;
6087                if (!mPowerManager.isInteractive()) {
6088                    useHapticFeedback = false; // suppress feedback if already non-interactive
6089                }
6090                if (down) {
6091                    sleepPress(event.getEventTime());
6092                } else {
6093                    sleepRelease(event.getEventTime());
6094                }
6095                break;
6096            }
6097
6098            case KeyEvent.KEYCODE_SOFT_SLEEP: {
6099                result &= ~ACTION_PASS_TO_USER;
6100                isWakeKey = false;
6101                if (!down) {
6102                    mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
6103                }
6104                break;
6105            }
6106
6107            case KeyEvent.KEYCODE_WAKEUP: {
6108                result &= ~ACTION_PASS_TO_USER;
6109                isWakeKey = true;
6110                break;
6111            }
6112
6113            case KeyEvent.KEYCODE_MEDIA_PLAY:
6114            case KeyEvent.KEYCODE_MEDIA_PAUSE:
6115            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6116            case KeyEvent.KEYCODE_HEADSETHOOK:
6117            case KeyEvent.KEYCODE_MUTE:
6118            case KeyEvent.KEYCODE_MEDIA_STOP:
6119            case KeyEvent.KEYCODE_MEDIA_NEXT:
6120            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6121            case KeyEvent.KEYCODE_MEDIA_REWIND:
6122            case KeyEvent.KEYCODE_MEDIA_RECORD:
6123            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6124            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
6125                if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
6126                    // If the global session is active pass all media keys to it
6127                    // instead of the active window.
6128                    result &= ~ACTION_PASS_TO_USER;
6129                }
6130                if ((result & ACTION_PASS_TO_USER) == 0) {
6131                    // Only do this if we would otherwise not pass it to the user. In that
6132                    // case, the PhoneWindow class will do the same thing, except it will
6133                    // only do it if the showing app doesn't process the key on its own.
6134                    // Note that we need to make a copy of the key event here because the
6135                    // original key event will be recycled when we return.
6136                    mBroadcastWakeLock.acquire();
6137                    Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
6138                            new KeyEvent(event));
6139                    msg.setAsynchronous(true);
6140                    msg.sendToTarget();
6141                }
6142                break;
6143            }
6144
6145            case KeyEvent.KEYCODE_CALL: {
6146                if (down) {
6147                    TelecomManager telecomManager = getTelecommService();
6148                    if (telecomManager != null) {
6149                        if (telecomManager.isRinging()) {
6150                            Log.i(TAG, "interceptKeyBeforeQueueing:"
6151                                  + " CALL key-down while ringing: Answer the call!");
6152                            telecomManager.acceptRingingCall();
6153
6154                            // And *don't* pass this key thru to the current activity
6155                            // (which is presumably the InCallScreen.)
6156                            result &= ~ACTION_PASS_TO_USER;
6157                        }
6158                    }
6159                }
6160                break;
6161            }
6162            case KeyEvent.KEYCODE_VOICE_ASSIST: {
6163                // Only do this if we would otherwise not pass it to the user. In that case,
6164                // interceptKeyBeforeDispatching would apply a similar but different policy in
6165                // order to invoke voice assist actions. Note that we need to make a copy of the
6166                // key event here because the original key event will be recycled when we return.
6167                if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
6168                    mBroadcastWakeLock.acquire();
6169                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
6170                            keyguardActive ? 1 : 0, 0);
6171                    msg.setAsynchronous(true);
6172                    msg.sendToTarget();
6173                }
6174                break;
6175            }
6176            case KeyEvent.KEYCODE_WINDOW: {
6177                if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
6178                    if (mPictureInPictureVisible) {
6179                        // Consumes the key only if picture-in-picture is visible to show
6180                        // picture-in-picture control menu. This gives a chance to the foreground
6181                        // activity to customize PIP key behavior.
6182                        if (!down) {
6183                            showPictureInPictureMenu(event);
6184                        }
6185                        result &= ~ACTION_PASS_TO_USER;
6186                    }
6187                }
6188                break;
6189            }
6190        }
6191
6192        if (useHapticFeedback) {
6193            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
6194        }
6195
6196        if (isWakeKey) {
6197            wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
6198        }
6199
6200        return result;
6201    }
6202
6203    /**
6204     * Handle statusbar expansion events.
6205     * @param event
6206     */
6207    private void interceptSystemNavigationKey(KeyEvent event) {
6208        if (event.getAction() == KeyEvent.ACTION_UP) {
6209            if (!mAccessibilityManager.isEnabled()
6210                    || !mAccessibilityManager.sendFingerprintGesture(event.getKeyCode())) {
6211                if (areSystemNavigationKeysEnabled()) {
6212                    IStatusBarService sbar = getStatusBarService();
6213                    if (sbar != null) {
6214                        try {
6215                            sbar.handleSystemNavigationKey(event.getKeyCode());
6216                        } catch (RemoteException e1) {
6217                            // oops, no statusbar. Ignore event.
6218                        }
6219                    }
6220                }
6221            }
6222        }
6223    }
6224
6225    /**
6226     * Returns true if the key can have global actions attached to it.
6227     * We reserve all power management keys for the system since they require
6228     * very careful handling.
6229     */
6230    private static boolean isValidGlobalKey(int keyCode) {
6231        switch (keyCode) {
6232            case KeyEvent.KEYCODE_POWER:
6233            case KeyEvent.KEYCODE_WAKEUP:
6234            case KeyEvent.KEYCODE_SLEEP:
6235                return false;
6236            default:
6237                return true;
6238        }
6239    }
6240
6241    /**
6242     * When the screen is off we ignore some keys that might otherwise typically
6243     * be considered wake keys.  We filter them out here.
6244     *
6245     * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
6246     * is always considered a wake key.
6247     */
6248    private boolean isWakeKeyWhenScreenOff(int keyCode) {
6249        switch (keyCode) {
6250            // ignore volume keys unless docked
6251            case KeyEvent.KEYCODE_VOLUME_UP:
6252            case KeyEvent.KEYCODE_VOLUME_DOWN:
6253            case KeyEvent.KEYCODE_VOLUME_MUTE:
6254                return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
6255
6256            // ignore media and camera keys
6257            case KeyEvent.KEYCODE_MUTE:
6258            case KeyEvent.KEYCODE_HEADSETHOOK:
6259            case KeyEvent.KEYCODE_MEDIA_PLAY:
6260            case KeyEvent.KEYCODE_MEDIA_PAUSE:
6261            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6262            case KeyEvent.KEYCODE_MEDIA_STOP:
6263            case KeyEvent.KEYCODE_MEDIA_NEXT:
6264            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6265            case KeyEvent.KEYCODE_MEDIA_REWIND:
6266            case KeyEvent.KEYCODE_MEDIA_RECORD:
6267            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6268            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
6269            case KeyEvent.KEYCODE_CAMERA:
6270                return false;
6271        }
6272        return true;
6273    }
6274
6275
6276    /** {@inheritDoc} */
6277    @Override
6278    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
6279        if ((policyFlags & FLAG_WAKE) != 0) {
6280            if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
6281                    "android.policy:MOTION")) {
6282                return 0;
6283            }
6284        }
6285
6286        if (shouldDispatchInputWhenNonInteractive(null)) {
6287            return ACTION_PASS_TO_USER;
6288        }
6289
6290        // If we have not passed the action up and we are in theater mode without dreaming,
6291        // there will be no dream to intercept the touch and wake into ambient.  The device should
6292        // wake up in this case.
6293        if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
6294            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
6295                    "android.policy:MOTION");
6296        }
6297
6298        return 0;
6299    }
6300
6301    private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
6302        final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
6303
6304        if (displayOff && !mHasFeatureWatch) {
6305            return false;
6306        }
6307
6308        // Send events to keyguard while the screen is on and it's showing.
6309        if (isKeyguardShowingAndNotOccluded() && !displayOff) {
6310            return true;
6311        }
6312
6313        // Watches handle BACK specially
6314        if (mHasFeatureWatch
6315                && event != null
6316                && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
6317                        || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
6318            return false;
6319        }
6320
6321        // Send events to a dozing dream even if the screen is off since the dream
6322        // is in control of the state of the screen.
6323        IDreamManager dreamManager = getDreamManager();
6324
6325        try {
6326            if (dreamManager != null && dreamManager.isDreaming()) {
6327                return true;
6328            }
6329        } catch (RemoteException e) {
6330            Slog.e(TAG, "RemoteException when checking if dreaming", e);
6331        }
6332
6333        // Otherwise, consume events since the user can't see what is being
6334        // interacted with.
6335        return false;
6336    }
6337
6338    private void dispatchDirectAudioEvent(KeyEvent event) {
6339        if (event.getAction() != KeyEvent.ACTION_DOWN) {
6340            return;
6341        }
6342        int keyCode = event.getKeyCode();
6343        int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
6344                | AudioManager.FLAG_FROM_KEY;
6345        String pkgName = mContext.getOpPackageName();
6346        switch (keyCode) {
6347            case KeyEvent.KEYCODE_VOLUME_UP:
6348                try {
6349                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
6350                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6351                } catch (Exception e) {
6352                    Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
6353                }
6354                break;
6355            case KeyEvent.KEYCODE_VOLUME_DOWN:
6356                try {
6357                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
6358                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6359                } catch (Exception e) {
6360                    Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
6361                }
6362                break;
6363            case KeyEvent.KEYCODE_VOLUME_MUTE:
6364                try {
6365                    if (event.getRepeatCount() == 0) {
6366                        getAudioService().adjustSuggestedStreamVolume(
6367                                AudioManager.ADJUST_TOGGLE_MUTE,
6368                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6369                    }
6370                } catch (Exception e) {
6371                    Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
6372                }
6373                break;
6374        }
6375    }
6376
6377    void dispatchMediaKeyWithWakeLock(KeyEvent event) {
6378        if (DEBUG_INPUT) {
6379            Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
6380        }
6381
6382        if (mHavePendingMediaKeyRepeatWithWakeLock) {
6383            if (DEBUG_INPUT) {
6384                Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
6385            }
6386
6387            mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
6388            mHavePendingMediaKeyRepeatWithWakeLock = false;
6389            mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
6390        }
6391
6392        dispatchMediaKeyWithWakeLockToAudioService(event);
6393
6394        if (event.getAction() == KeyEvent.ACTION_DOWN
6395                && event.getRepeatCount() == 0) {
6396            mHavePendingMediaKeyRepeatWithWakeLock = true;
6397
6398            Message msg = mHandler.obtainMessage(
6399                    MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
6400            msg.setAsynchronous(true);
6401            mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
6402        } else {
6403            mBroadcastWakeLock.release();
6404        }
6405    }
6406
6407    void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
6408        mHavePendingMediaKeyRepeatWithWakeLock = false;
6409
6410        KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
6411                SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6412        if (DEBUG_INPUT) {
6413            Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
6414        }
6415
6416        dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
6417        mBroadcastWakeLock.release();
6418    }
6419
6420    void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
6421        if (mActivityManagerInternal.isSystemReady()) {
6422            MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
6423        }
6424    }
6425
6426    void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
6427        IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
6428                ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
6429        if (dic != null) {
6430            try {
6431                dic.exitIdle("voice-search");
6432            } catch (RemoteException e) {
6433            }
6434        }
6435        Intent voiceIntent =
6436            new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
6437        voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
6438        startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
6439        mBroadcastWakeLock.release();
6440    }
6441
6442    BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
6443        @Override
6444        public void onReceive(Context context, Intent intent) {
6445            if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
6446                mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6447                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
6448            } else {
6449                try {
6450                    IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
6451                            ServiceManager.getService(Context.UI_MODE_SERVICE));
6452                    mUiMode = uiModeService.getCurrentModeType();
6453                } catch (RemoteException e) {
6454                }
6455            }
6456            updateRotation(true);
6457            synchronized (mLock) {
6458                updateOrientationListenerLp();
6459            }
6460        }
6461    };
6462
6463    BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
6464        @Override
6465        public void onReceive(Context context, Intent intent) {
6466            if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
6467                if (mKeyguardDelegate != null) {
6468                    mKeyguardDelegate.onDreamingStarted();
6469                }
6470            } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
6471                if (mKeyguardDelegate != null) {
6472                    mKeyguardDelegate.onDreamingStopped();
6473                }
6474            }
6475        }
6476    };
6477
6478    BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
6479        @Override
6480        public void onReceive(Context context, Intent intent) {
6481            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
6482                // tickle the settings observer: this first ensures that we're
6483                // observing the relevant settings for the newly-active user,
6484                // and then updates our own bookkeeping based on the now-
6485                // current user.
6486                mSettingsObserver.onChange(false);
6487
6488                // force a re-application of focused window sysui visibility.
6489                // the window may never have been shown for this user
6490                // e.g. the keyguard when going through the new-user setup flow
6491                synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6492                    mLastSystemUiFlags = 0;
6493                    updateSystemUiVisibilityLw();
6494                }
6495            }
6496        }
6497    };
6498
6499    private final Runnable mHiddenNavPanic = new Runnable() {
6500        @Override
6501        public void run() {
6502            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6503                if (!isUserSetupComplete()) {
6504                    // Swipe-up for navigation bar is disabled during setup
6505                    return;
6506                }
6507                mPendingPanicGestureUptime = SystemClock.uptimeMillis();
6508                if (!isNavBarEmpty(mLastSystemUiFlags)) {
6509                    mNavigationBarController.showTransient();
6510                }
6511            }
6512        }
6513    };
6514
6515    private void requestTransientBars(WindowState swipeTarget) {
6516        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6517            if (!isUserSetupComplete()) {
6518                // Swipe-up for navigation bar is disabled during setup
6519                return;
6520            }
6521            boolean sb = mStatusBarController.checkShowTransientBarLw();
6522            boolean nb = mNavigationBarController.checkShowTransientBarLw()
6523                    && !isNavBarEmpty(mLastSystemUiFlags);
6524            if (sb || nb) {
6525                // Don't show status bar when swiping on already visible navigation bar
6526                if (!nb && swipeTarget == mNavigationBar) {
6527                    if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
6528                    return;
6529                }
6530                if (sb) mStatusBarController.showTransient();
6531                if (nb) mNavigationBarController.showTransient();
6532                mImmersiveModeConfirmation.confirmCurrentPrompt();
6533                updateSystemUiVisibilityLw();
6534            }
6535        }
6536    }
6537
6538    // Called on the PowerManager's Notifier thread.
6539    @Override
6540    public void startedGoingToSleep(int why) {
6541        if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
6542        mCameraGestureTriggeredDuringGoingToSleep = false;
6543        mGoingToSleep = true;
6544        if (mKeyguardDelegate != null) {
6545            mKeyguardDelegate.onStartedGoingToSleep(why);
6546        }
6547    }
6548
6549    // Called on the PowerManager's Notifier thread.
6550    @Override
6551    public void finishedGoingToSleep(int why) {
6552        EventLog.writeEvent(70000, 0);
6553        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
6554        MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
6555
6556        mGoingToSleep = false;
6557
6558        // We must get this work done here because the power manager will drop
6559        // the wake lock and let the system suspend once this function returns.
6560        synchronized (mLock) {
6561            mAwake = false;
6562            updateWakeGestureListenerLp();
6563            updateOrientationListenerLp();
6564            updateLockScreenTimeout();
6565        }
6566        if (mKeyguardDelegate != null) {
6567            mKeyguardDelegate.onFinishedGoingToSleep(why,
6568                    mCameraGestureTriggeredDuringGoingToSleep);
6569        }
6570        mCameraGestureTriggeredDuringGoingToSleep = false;
6571    }
6572
6573    // Called on the PowerManager's Notifier thread.
6574    @Override
6575    public void startedWakingUp() {
6576        EventLog.writeEvent(70000, 1);
6577        if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
6578
6579        // Since goToSleep performs these functions synchronously, we must
6580        // do the same here.  We cannot post this work to a handler because
6581        // that might cause it to become reordered with respect to what
6582        // may happen in a future call to goToSleep.
6583        synchronized (mLock) {
6584            mAwake = true;
6585
6586            updateWakeGestureListenerLp();
6587            updateOrientationListenerLp();
6588            updateLockScreenTimeout();
6589        }
6590
6591        if (mKeyguardDelegate != null) {
6592            mKeyguardDelegate.onStartedWakingUp();
6593        }
6594    }
6595
6596    // Called on the PowerManager's Notifier thread.
6597    @Override
6598    public void finishedWakingUp() {
6599        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
6600    }
6601
6602    private void wakeUpFromPowerKey(long eventTime) {
6603        wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
6604    }
6605
6606    private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
6607        final boolean theaterModeEnabled = isTheaterModeEnabled();
6608        if (!wakeInTheaterMode && theaterModeEnabled) {
6609            return false;
6610        }
6611
6612        if (theaterModeEnabled) {
6613            Settings.Global.putInt(mContext.getContentResolver(),
6614                    Settings.Global.THEATER_MODE_ON, 0);
6615        }
6616
6617        mPowerManager.wakeUp(wakeTime, reason);
6618        return true;
6619    }
6620
6621    private void finishKeyguardDrawn() {
6622        synchronized (mLock) {
6623            if (!mScreenOnEarly || mKeyguardDrawComplete) {
6624                return; // We are not awake yet or we have already informed of this event.
6625            }
6626
6627            mKeyguardDrawComplete = true;
6628            if (mKeyguardDelegate != null) {
6629                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6630            }
6631            mWindowManagerDrawComplete = false;
6632        }
6633
6634        // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
6635        // as well as enabling the orientation change logic/sensor.
6636        mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
6637                WAITING_FOR_DRAWN_TIMEOUT);
6638    }
6639
6640    // Called on the DisplayManager's DisplayPowerController thread.
6641    @Override
6642    public void screenTurnedOff() {
6643        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
6644
6645        updateScreenOffSleepToken(true);
6646        synchronized (mLock) {
6647            mScreenOnEarly = false;
6648            mScreenOnFully = false;
6649            mKeyguardDrawComplete = false;
6650            mWindowManagerDrawComplete = false;
6651            mScreenOnListener = null;
6652            updateOrientationListenerLp();
6653
6654            if (mKeyguardDelegate != null) {
6655                mKeyguardDelegate.onScreenTurnedOff();
6656            }
6657        }
6658        reportScreenStateToVrManager(false);
6659    }
6660
6661    private long getKeyguardDrawnTimeout() {
6662        final boolean bootCompleted =
6663                LocalServices.getService(SystemServiceManager.class).isBootCompleted();
6664        // Set longer timeout if it has not booted yet to prevent showing empty window.
6665        return bootCompleted ? 1000 : 5000;
6666    }
6667
6668    // Called on the DisplayManager's DisplayPowerController thread.
6669    @Override
6670    public void screenTurningOn(final ScreenOnListener screenOnListener) {
6671        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
6672
6673        updateScreenOffSleepToken(false);
6674        synchronized (mLock) {
6675            mScreenOnEarly = true;
6676            mScreenOnFully = false;
6677            mKeyguardDrawComplete = false;
6678            mWindowManagerDrawComplete = false;
6679            mScreenOnListener = screenOnListener;
6680
6681            if (mKeyguardDelegate != null) {
6682                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6683                mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT,
6684                        getKeyguardDrawnTimeout());
6685                mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
6686            } else {
6687                if (DEBUG_WAKEUP) Slog.d(TAG,
6688                        "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
6689                finishKeyguardDrawn();
6690            }
6691        }
6692    }
6693
6694    // Called on the DisplayManager's DisplayPowerController thread.
6695    @Override
6696    public void screenTurnedOn() {
6697        synchronized (mLock) {
6698            if (mKeyguardDelegate != null) {
6699                mKeyguardDelegate.onScreenTurnedOn();
6700            }
6701        }
6702        reportScreenStateToVrManager(true);
6703    }
6704
6705    @Override
6706    public void screenTurningOff(ScreenOffListener screenOffListener) {
6707        mWindowManagerFuncs.screenTurningOff(screenOffListener);
6708    }
6709
6710    private void reportScreenStateToVrManager(boolean isScreenOn) {
6711        if (mVrManagerInternal == null) {
6712            return;
6713        }
6714        mVrManagerInternal.onScreenStateChanged(isScreenOn);
6715    }
6716
6717    private void finishWindowsDrawn() {
6718        synchronized (mLock) {
6719            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
6720                return; // Screen is not turned on or we did already handle this case earlier.
6721            }
6722
6723            mWindowManagerDrawComplete = true;
6724        }
6725
6726        finishScreenTurningOn();
6727    }
6728
6729    private void finishScreenTurningOn() {
6730        synchronized (mLock) {
6731            // We have just finished drawing screen content. Since the orientation listener
6732            // gets only installed when all windows are drawn, we try to install it again.
6733            updateOrientationListenerLp();
6734        }
6735        final ScreenOnListener listener;
6736        final boolean enableScreen;
6737        synchronized (mLock) {
6738            if (DEBUG_WAKEUP) Slog.d(TAG,
6739                    "finishScreenTurningOn: mAwake=" + mAwake
6740                            + ", mScreenOnEarly=" + mScreenOnEarly
6741                            + ", mScreenOnFully=" + mScreenOnFully
6742                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
6743                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
6744
6745            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
6746                    || (mAwake && !mKeyguardDrawComplete)) {
6747                return; // spurious or not ready yet
6748            }
6749
6750            if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
6751            listener = mScreenOnListener;
6752            mScreenOnListener = null;
6753            mScreenOnFully = true;
6754
6755            // Remember the first time we draw the keyguard so we know when we're done with
6756            // the main part of booting and can enable the screen and hide boot messages.
6757            if (!mKeyguardDrawnOnce && mAwake) {
6758                mKeyguardDrawnOnce = true;
6759                enableScreen = true;
6760                if (mBootMessageNeedsHiding) {
6761                    mBootMessageNeedsHiding = false;
6762                    hideBootMessages();
6763                }
6764            } else {
6765                enableScreen = false;
6766            }
6767        }
6768
6769        if (listener != null) {
6770            listener.onScreenOn();
6771        }
6772
6773        if (enableScreen) {
6774            try {
6775                mWindowManager.enableScreenIfNeeded();
6776            } catch (RemoteException unhandled) {
6777            }
6778        }
6779    }
6780
6781    private void handleHideBootMessage() {
6782        synchronized (mLock) {
6783            if (!mKeyguardDrawnOnce) {
6784                mBootMessageNeedsHiding = true;
6785                return; // keyguard hasn't drawn the first time yet, not done booting
6786            }
6787        }
6788
6789        if (mBootMsgDialog != null) {
6790            if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
6791            mBootMsgDialog.dismiss();
6792            mBootMsgDialog = null;
6793        }
6794    }
6795
6796    @Override
6797    public boolean isScreenOn() {
6798        return mScreenOnFully;
6799    }
6800
6801    /** {@inheritDoc} */
6802    @Override
6803    public void enableKeyguard(boolean enabled) {
6804        if (mKeyguardDelegate != null) {
6805            mKeyguardDelegate.setKeyguardEnabled(enabled);
6806        }
6807    }
6808
6809    /** {@inheritDoc} */
6810    @Override
6811    public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
6812        if (mKeyguardDelegate != null) {
6813            mKeyguardDelegate.verifyUnlock(callback);
6814        }
6815    }
6816
6817    @Override
6818    public boolean isKeyguardShowingAndNotOccluded() {
6819        if (mKeyguardDelegate == null) return false;
6820        return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
6821    }
6822
6823    @Override
6824    public boolean isKeyguardTrustedLw() {
6825        if (mKeyguardDelegate == null) return false;
6826        return mKeyguardDelegate.isTrusted();
6827    }
6828
6829    /** {@inheritDoc} */
6830    @Override
6831    public boolean isKeyguardLocked() {
6832        return keyguardOn();
6833    }
6834
6835    /** {@inheritDoc} */
6836    @Override
6837    public boolean isKeyguardSecure(int userId) {
6838        if (mKeyguardDelegate == null) return false;
6839        return mKeyguardDelegate.isSecure(userId);
6840    }
6841
6842    /** {@inheritDoc} */
6843    @Override
6844    public boolean isKeyguardOccluded() {
6845        if (mKeyguardDelegate == null) return false;
6846        return mKeyguardOccluded;
6847    }
6848
6849    /** {@inheritDoc} */
6850    @Override
6851    public boolean inKeyguardRestrictedKeyInputMode() {
6852        if (mKeyguardDelegate == null) return false;
6853        return mKeyguardDelegate.isInputRestricted();
6854    }
6855
6856    @Override
6857    public void dismissKeyguardLw(IKeyguardDismissCallback callback) {
6858        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
6859            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
6860
6861            // ask the keyguard to prompt the user to authenticate if necessary
6862            mKeyguardDelegate.dismiss(callback);
6863        } else if (callback != null) {
6864            try {
6865                callback.onDismissError();
6866            } catch (RemoteException e) {
6867                Slog.w(TAG, "Failed to call callback", e);
6868            }
6869        }
6870    }
6871
6872    @Override
6873    public boolean isKeyguardDrawnLw() {
6874        synchronized (mLock) {
6875            return mKeyguardDrawnOnce;
6876        }
6877    }
6878
6879    @Override
6880    public boolean isShowingDreamLw() {
6881        return mShowingDream;
6882    }
6883
6884    @Override
6885    public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
6886        if (mKeyguardDelegate != null) {
6887            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
6888            mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
6889        }
6890    }
6891
6892    @Override
6893    public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6894            Rect outInsets) {
6895        outInsets.setEmpty();
6896
6897        // Navigation bar and status bar.
6898        getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
6899        outInsets.top = mStatusBarHeight;
6900    }
6901
6902    @Override
6903    public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6904            Rect outInsets) {
6905        outInsets.setEmpty();
6906
6907        // Only navigation bar
6908        if (mHasNavigationBar) {
6909            int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
6910            if (position == NAV_BAR_BOTTOM) {
6911                outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
6912            } else if (position == NAV_BAR_RIGHT) {
6913                outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
6914            } else if (position == NAV_BAR_LEFT) {
6915                outInsets.left = getNavigationBarWidth(displayRotation, mUiMode);
6916            }
6917        }
6918    }
6919
6920    @Override
6921    public boolean isNavBarForcedShownLw(WindowState windowState) {
6922        return mForceShowSystemBars;
6923    }
6924
6925    @Override
6926    public boolean isDockSideAllowed(int dockSide) {
6927
6928        // We do not allow all dock sides at which the navigation bar touches the docked stack.
6929        if (!mNavigationBarCanMove) {
6930            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT;
6931        } else {
6932            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT;
6933        }
6934    }
6935
6936    void sendCloseSystemWindows() {
6937        PhoneWindow.sendCloseSystemWindows(mContext, null);
6938    }
6939
6940    void sendCloseSystemWindows(String reason) {
6941        PhoneWindow.sendCloseSystemWindows(mContext, reason);
6942    }
6943
6944    @Override
6945    public int rotationForOrientationLw(int orientation, int lastRotation) {
6946        if (false) {
6947            Slog.v(TAG, "rotationForOrientationLw(orient="
6948                        + orientation + ", last=" + lastRotation
6949                        + "); user=" + mUserRotation + " "
6950                        + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
6951                            ? "USER_ROTATION_LOCKED" : "")
6952                        );
6953        }
6954
6955        if (mForceDefaultOrientation) {
6956            return Surface.ROTATION_0;
6957        }
6958
6959        synchronized (mLock) {
6960            int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
6961            if (sensorRotation < 0) {
6962                sensorRotation = lastRotation;
6963            }
6964
6965            final int preferredRotation;
6966            if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
6967                // Ignore sensor when lid switch is open and rotation is forced.
6968                preferredRotation = mLidOpenRotation;
6969            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
6970                    && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
6971                // Ignore sensor when in car dock unless explicitly enabled.
6972                // This case can override the behavior of NOSENSOR, and can also
6973                // enable 180 degree rotation while docked.
6974                preferredRotation = mCarDockEnablesAccelerometer
6975                        ? sensorRotation : mCarDockRotation;
6976            } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
6977                    || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
6978                    || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
6979                    && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
6980                // Ignore sensor when in desk dock unless explicitly enabled.
6981                // This case can override the behavior of NOSENSOR, and can also
6982                // enable 180 degree rotation while docked.
6983                preferredRotation = mDeskDockEnablesAccelerometer
6984                        ? sensorRotation : mDeskDockRotation;
6985            } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
6986                // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
6987                // Note that the dock orientation overrides the HDMI orientation.
6988                preferredRotation = mDemoHdmiRotation;
6989            } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
6990                    && mUndockedHdmiRotation >= 0) {
6991                // Ignore sensor when plugged into HDMI and an undocked orientation has
6992                // been specified in the configuration (only for legacy devices without
6993                // full multi-display support).
6994                // Note that the dock orientation overrides the HDMI orientation.
6995                preferredRotation = mUndockedHdmiRotation;
6996            } else if (mDemoRotationLock) {
6997                // Ignore sensor when demo rotation lock is enabled.
6998                // Note that the dock orientation and HDMI rotation lock override this.
6999                preferredRotation = mDemoRotation;
7000            } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
7001                // Application just wants to remain locked in the last rotation.
7002                preferredRotation = lastRotation;
7003            } else if (!mSupportAutoRotation) {
7004                // If we don't support auto-rotation then bail out here and ignore
7005                // the sensor and any rotation lock settings.
7006                preferredRotation = -1;
7007            } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
7008                            && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
7009                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
7010                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
7011                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
7012                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
7013                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
7014                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
7015                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
7016                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
7017                // Otherwise, use sensor only if requested by the application or enabled
7018                // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
7019                if (mAllowAllRotations < 0) {
7020                    // Can't read this during init() because the context doesn't
7021                    // have display metrics at that time so we cannot determine
7022                    // tablet vs. phone then.
7023                    mAllowAllRotations = mContext.getResources().getBoolean(
7024                            com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
7025                }
7026                if (sensorRotation != Surface.ROTATION_180
7027                        || mAllowAllRotations == 1
7028                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
7029                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
7030                    // In VrMode, we report the sensor as always being in default orientation so:
7031                    // 1) The orientation doesn't change as the user moves their head.
7032                    // 2) 2D apps within VR show in the device's default orientation.
7033                    // This only overwrites the sensor-provided orientation and does not affect any
7034                    // explicit orientation preferences specified by any activities.
7035                    preferredRotation =
7036                            mPersistentVrModeEnabled ? Surface.ROTATION_0 : sensorRotation;
7037                } else {
7038                    preferredRotation = lastRotation;
7039                }
7040            } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
7041                    && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
7042                // Apply rotation lock.  Does not apply to NOSENSOR.
7043                // The idea is that the user rotation expresses a weak preference for the direction
7044                // of gravity and as NOSENSOR is never affected by gravity, then neither should
7045                // NOSENSOR be affected by rotation lock (although it will be affected by docks).
7046                preferredRotation = mUserRotation;
7047            } else {
7048                // No overriding preference.
7049                // We will do exactly what the application asked us to do.
7050                preferredRotation = -1;
7051            }
7052
7053            switch (orientation) {
7054                case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
7055                    // Return portrait unless overridden.
7056                    if (isAnyPortrait(preferredRotation)) {
7057                        return preferredRotation;
7058                    }
7059                    return mPortraitRotation;
7060
7061                case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
7062                    // Return landscape unless overridden.
7063                    if (isLandscapeOrSeascape(preferredRotation)) {
7064                        return preferredRotation;
7065                    }
7066                    return mLandscapeRotation;
7067
7068                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
7069                    // Return reverse portrait unless overridden.
7070                    if (isAnyPortrait(preferredRotation)) {
7071                        return preferredRotation;
7072                    }
7073                    return mUpsideDownRotation;
7074
7075                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
7076                    // Return seascape unless overridden.
7077                    if (isLandscapeOrSeascape(preferredRotation)) {
7078                        return preferredRotation;
7079                    }
7080                    return mSeascapeRotation;
7081
7082                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
7083                case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
7084                    // Return either landscape rotation.
7085                    if (isLandscapeOrSeascape(preferredRotation)) {
7086                        return preferredRotation;
7087                    }
7088                    if (isLandscapeOrSeascape(lastRotation)) {
7089                        return lastRotation;
7090                    }
7091                    return mLandscapeRotation;
7092
7093                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
7094                case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
7095                    // Return either portrait rotation.
7096                    if (isAnyPortrait(preferredRotation)) {
7097                        return preferredRotation;
7098                    }
7099                    if (isAnyPortrait(lastRotation)) {
7100                        return lastRotation;
7101                    }
7102                    return mPortraitRotation;
7103
7104                default:
7105                    // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
7106                    // just return the preferred orientation we already calculated.
7107                    if (preferredRotation >= 0) {
7108                        return preferredRotation;
7109                    }
7110                    return Surface.ROTATION_0;
7111            }
7112        }
7113    }
7114
7115    @Override
7116    public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
7117        switch (orientation) {
7118            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
7119            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
7120            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
7121                return isAnyPortrait(rotation);
7122
7123            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
7124            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
7125            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
7126                return isLandscapeOrSeascape(rotation);
7127
7128            default:
7129                return true;
7130        }
7131    }
7132
7133    @Override
7134    public void setRotationLw(int rotation) {
7135        mOrientationListener.setCurrentRotation(rotation);
7136    }
7137
7138    private boolean isLandscapeOrSeascape(int rotation) {
7139        return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
7140    }
7141
7142    private boolean isAnyPortrait(int rotation) {
7143        return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
7144    }
7145
7146    @Override
7147    public int getUserRotationMode() {
7148        return Settings.System.getIntForUser(mContext.getContentResolver(),
7149                Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
7150                        WindowManagerPolicy.USER_ROTATION_FREE :
7151                                WindowManagerPolicy.USER_ROTATION_LOCKED;
7152    }
7153
7154    // User rotation: to be used when all else fails in assigning an orientation to the device
7155    @Override
7156    public void setUserRotationMode(int mode, int rot) {
7157        ContentResolver res = mContext.getContentResolver();
7158
7159        // mUserRotationMode and mUserRotation will be assigned by the content observer
7160        if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
7161            Settings.System.putIntForUser(res,
7162                    Settings.System.USER_ROTATION,
7163                    rot,
7164                    UserHandle.USER_CURRENT);
7165            Settings.System.putIntForUser(res,
7166                    Settings.System.ACCELEROMETER_ROTATION,
7167                    0,
7168                    UserHandle.USER_CURRENT);
7169        } else {
7170            Settings.System.putIntForUser(res,
7171                    Settings.System.ACCELEROMETER_ROTATION,
7172                    1,
7173                    UserHandle.USER_CURRENT);
7174        }
7175    }
7176
7177    @Override
7178    public void setSafeMode(boolean safeMode) {
7179        mSafeMode = safeMode;
7180        performHapticFeedbackLw(null, safeMode
7181                ? HapticFeedbackConstants.SAFE_MODE_ENABLED
7182                : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
7183    }
7184
7185    static long[] getLongIntArray(Resources r, int resid) {
7186        int[] ar = r.getIntArray(resid);
7187        if (ar == null) {
7188            return null;
7189        }
7190        long[] out = new long[ar.length];
7191        for (int i=0; i<ar.length; i++) {
7192            out[i] = ar[i];
7193        }
7194        return out;
7195    }
7196
7197    private void bindKeyguard() {
7198        synchronized (mLock) {
7199            if (mKeyguardBound) {
7200                return;
7201            }
7202            mKeyguardBound = true;
7203        }
7204        mKeyguardDelegate.bindService(mContext);
7205    }
7206
7207    @Override
7208    public void onSystemUiStarted() {
7209        bindKeyguard();
7210    }
7211
7212    /** {@inheritDoc} */
7213    @Override
7214    public void systemReady() {
7215        // In normal flow, systemReady is called before other system services are ready.
7216        // So it is better not to bind keyguard here.
7217        mKeyguardDelegate.onSystemReady();
7218
7219        mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
7220        if (mVrManagerInternal != null) {
7221            mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
7222        }
7223
7224        readCameraLensCoverState();
7225        updateUiMode();
7226        synchronized (mLock) {
7227            updateOrientationListenerLp();
7228            mSystemReady = true;
7229            mHandler.post(new Runnable() {
7230                @Override
7231                public void run() {
7232                    updateSettings();
7233                }
7234            });
7235            // If this happens, for whatever reason, systemReady came later than systemBooted.
7236            // And keyguard should be already bound from systemBooted
7237            if (mSystemBooted) {
7238                mKeyguardDelegate.onBootCompleted();
7239            }
7240        }
7241
7242        mSystemGestures.systemReady();
7243        mImmersiveModeConfirmation.systemReady();
7244    }
7245
7246    /** {@inheritDoc} */
7247    @Override
7248    public void systemBooted() {
7249        bindKeyguard();
7250        synchronized (mLock) {
7251            mSystemBooted = true;
7252            if (mSystemReady) {
7253                mKeyguardDelegate.onBootCompleted();
7254            }
7255        }
7256        startedWakingUp();
7257        screenTurningOn(null);
7258        screenTurnedOn();
7259    }
7260
7261    @Override
7262    public boolean canDismissBootAnimation() {
7263        synchronized (mLock) {
7264            return mKeyguardDrawComplete;
7265        }
7266    }
7267
7268    ProgressDialog mBootMsgDialog = null;
7269
7270    /** {@inheritDoc} */
7271    @Override
7272    public void showBootMessage(final CharSequence msg, final boolean always) {
7273        mHandler.post(new Runnable() {
7274            @Override public void run() {
7275                if (mBootMsgDialog == null) {
7276                    int theme;
7277                    if (mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK)) {
7278                        theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
7279                    } else {
7280                        theme = 0;
7281                    }
7282
7283                    mBootMsgDialog = new ProgressDialog(mContext, theme) {
7284                        // This dialog will consume all events coming in to
7285                        // it, to avoid it trying to do things too early in boot.
7286                        @Override public boolean dispatchKeyEvent(KeyEvent event) {
7287                            return true;
7288                        }
7289                        @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7290                            return true;
7291                        }
7292                        @Override public boolean dispatchTouchEvent(MotionEvent ev) {
7293                            return true;
7294                        }
7295                        @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
7296                            return true;
7297                        }
7298                        @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
7299                            return true;
7300                        }
7301                        @Override public boolean dispatchPopulateAccessibilityEvent(
7302                                AccessibilityEvent event) {
7303                            return true;
7304                        }
7305                    };
7306                    if (mContext.getPackageManager().isUpgrade()) {
7307                        mBootMsgDialog.setTitle(R.string.android_upgrading_title);
7308                    } else {
7309                        mBootMsgDialog.setTitle(R.string.android_start_title);
7310                    }
7311                    mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
7312                    mBootMsgDialog.setIndeterminate(true);
7313                    mBootMsgDialog.getWindow().setType(
7314                            WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
7315                    mBootMsgDialog.getWindow().addFlags(
7316                            WindowManager.LayoutParams.FLAG_DIM_BEHIND
7317                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
7318                    mBootMsgDialog.getWindow().setDimAmount(1);
7319                    WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
7320                    lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
7321                    mBootMsgDialog.getWindow().setAttributes(lp);
7322                    mBootMsgDialog.setCancelable(false);
7323                    mBootMsgDialog.show();
7324                }
7325                mBootMsgDialog.setMessage(msg);
7326            }
7327        });
7328    }
7329
7330    /** {@inheritDoc} */
7331    @Override
7332    public void hideBootMessages() {
7333        mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
7334    }
7335
7336    /** {@inheritDoc} */
7337    @Override
7338    public void userActivity() {
7339        // ***************************************
7340        // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
7341        // ***************************************
7342        // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
7343        // WITH ITS LOCKS HELD.
7344        //
7345        // This code must be VERY careful about the locks
7346        // it acquires.
7347        // In fact, the current code acquires way too many,
7348        // and probably has lurking deadlocks.
7349
7350        synchronized (mScreenLockTimeout) {
7351            if (mLockScreenTimerActive) {
7352                // reset the timer
7353                mHandler.removeCallbacks(mScreenLockTimeout);
7354                mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7355            }
7356        }
7357    }
7358
7359    class ScreenLockTimeout implements Runnable {
7360        Bundle options;
7361
7362        @Override
7363        public void run() {
7364            synchronized (this) {
7365                if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
7366                if (mKeyguardDelegate != null) {
7367                    mKeyguardDelegate.doKeyguardTimeout(options);
7368                }
7369                mLockScreenTimerActive = false;
7370                options = null;
7371            }
7372        }
7373
7374        public void setLockOptions(Bundle options) {
7375            this.options = options;
7376        }
7377    }
7378
7379    ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
7380
7381    @Override
7382    public void lockNow(Bundle options) {
7383        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
7384        mHandler.removeCallbacks(mScreenLockTimeout);
7385        if (options != null) {
7386            // In case multiple calls are made to lockNow, we don't wipe out the options
7387            // until the runnable actually executes.
7388            mScreenLockTimeout.setLockOptions(options);
7389        }
7390        mHandler.post(mScreenLockTimeout);
7391    }
7392
7393    private void updateLockScreenTimeout() {
7394        synchronized (mScreenLockTimeout) {
7395            boolean enable = (mAllowLockscreenWhenOn && mAwake &&
7396                    mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
7397            if (mLockScreenTimerActive != enable) {
7398                if (enable) {
7399                    if (localLOGV) Log.v(TAG, "setting lockscreen timer");
7400                    mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
7401                    mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7402                } else {
7403                    if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
7404                    mHandler.removeCallbacks(mScreenLockTimeout);
7405                }
7406                mLockScreenTimerActive = enable;
7407            }
7408        }
7409    }
7410
7411    private void updateDreamingSleepToken(boolean acquire) {
7412        if (acquire) {
7413            if (mDreamingSleepToken == null) {
7414                mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream");
7415            }
7416        } else {
7417            if (mDreamingSleepToken != null) {
7418                mDreamingSleepToken.release();
7419                mDreamingSleepToken = null;
7420            }
7421        }
7422    }
7423
7424    private void updateScreenOffSleepToken(boolean acquire) {
7425        if (acquire) {
7426            if (mScreenOffSleepToken == null) {
7427                mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff");
7428            }
7429        } else {
7430            if (mScreenOffSleepToken != null) {
7431                mScreenOffSleepToken.release();
7432                mScreenOffSleepToken = null;
7433            }
7434        }
7435    }
7436
7437    /** {@inheritDoc} */
7438    @Override
7439    public void enableScreenAfterBoot() {
7440        readLidState();
7441        applyLidSwitchState();
7442        updateRotation(true);
7443    }
7444
7445    private void applyLidSwitchState() {
7446        if (mLidState == LID_CLOSED && mLidControlsSleep) {
7447            mPowerManager.goToSleep(SystemClock.uptimeMillis(),
7448                    PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
7449                    PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
7450        } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
7451            mWindowManagerFuncs.lockDeviceNow();
7452        }
7453
7454        synchronized (mLock) {
7455            updateWakeGestureListenerLp();
7456        }
7457    }
7458
7459    void updateUiMode() {
7460        if (mUiModeManager == null) {
7461            mUiModeManager = IUiModeManager.Stub.asInterface(
7462                    ServiceManager.getService(Context.UI_MODE_SERVICE));
7463        }
7464        try {
7465            mUiMode = mUiModeManager.getCurrentModeType();
7466        } catch (RemoteException e) {
7467        }
7468    }
7469
7470    void updateRotation(boolean alwaysSendConfiguration) {
7471        try {
7472            //set orientation on WindowManager
7473            mWindowManager.updateRotation(alwaysSendConfiguration, false);
7474        } catch (RemoteException e) {
7475            // Ignore
7476        }
7477    }
7478
7479    void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
7480        try {
7481            //set orientation on WindowManager
7482            mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
7483        } catch (RemoteException e) {
7484            // Ignore
7485        }
7486    }
7487
7488    /**
7489     * Return an Intent to launch the currently active dock app as home.  Returns
7490     * null if the standard home should be launched, which is the case if any of the following is
7491     * true:
7492     * <ul>
7493     *  <li>The device is not in either car mode or desk mode
7494     *  <li>The device is in car mode but mEnableCarDockHomeCapture is false
7495     *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
7496     *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
7497     *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
7498     * </ul>
7499     * @return A dock intent.
7500     */
7501    Intent createHomeDockIntent() {
7502        Intent intent = null;
7503
7504        // What home does is based on the mode, not the dock state.  That
7505        // is, when in car mode you should be taken to car home regardless
7506        // of whether we are actually in a car dock.
7507        if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
7508            if (mEnableCarDockHomeCapture) {
7509                intent = mCarDockIntent;
7510            }
7511        } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
7512            if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
7513                intent = mDeskDockIntent;
7514            }
7515        } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
7516                && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7517                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
7518                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
7519            // Always launch dock home from home when watch is docked, if it exists.
7520            intent = mDeskDockIntent;
7521        } else if (mUiMode == Configuration.UI_MODE_TYPE_VR_HEADSET) {
7522            if (ENABLE_VR_HEADSET_HOME_CAPTURE) {
7523                intent = mVrHeadsetHomeIntent;
7524            }
7525        }
7526
7527        if (intent == null) {
7528            return null;
7529        }
7530
7531        ActivityInfo ai = null;
7532        ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
7533                intent,
7534                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
7535                mCurrentUserId);
7536        if (info != null) {
7537            ai = info.activityInfo;
7538        }
7539        if (ai != null
7540                && ai.metaData != null
7541                && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
7542            intent = new Intent(intent);
7543            intent.setClassName(ai.packageName, ai.name);
7544            return intent;
7545        }
7546
7547        return null;
7548    }
7549
7550    void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
7551        if (awakenFromDreams) {
7552            awakenDreams();
7553        }
7554
7555        Intent dock = createHomeDockIntent();
7556        if (dock != null) {
7557            try {
7558                if (fromHomeKey) {
7559                    dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7560                }
7561                startActivityAsUser(dock, UserHandle.CURRENT);
7562                return;
7563            } catch (ActivityNotFoundException e) {
7564            }
7565        }
7566
7567        Intent intent;
7568
7569        if (fromHomeKey) {
7570            intent = new Intent(mHomeIntent);
7571            intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7572        } else {
7573            intent = mHomeIntent;
7574        }
7575
7576        startActivityAsUser(intent, UserHandle.CURRENT);
7577    }
7578
7579    /**
7580     * goes to the home screen
7581     * @return whether it did anything
7582     */
7583    boolean goHome() {
7584        if (!isUserSetupComplete()) {
7585            Slog.i(TAG, "Not going home because user setup is in progress.");
7586            return false;
7587        }
7588        if (false) {
7589            // This code always brings home to the front.
7590            try {
7591                ActivityManager.getService().stopAppSwitches();
7592            } catch (RemoteException e) {
7593            }
7594            sendCloseSystemWindows();
7595            startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
7596        } else {
7597            // This code brings home to the front or, if it is already
7598            // at the front, puts the device to sleep.
7599            try {
7600                if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
7601                    /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
7602                    Log.d(TAG, "UTS-TEST-MODE");
7603                } else {
7604                    ActivityManager.getService().stopAppSwitches();
7605                    sendCloseSystemWindows();
7606                    Intent dock = createHomeDockIntent();
7607                    if (dock != null) {
7608                        int result = ActivityManager.getService()
7609                                .startActivityAsUser(null, null, dock,
7610                                        dock.resolveTypeIfNeeded(mContext.getContentResolver()),
7611                                        null, null, 0,
7612                                        ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7613                                        null, null, UserHandle.USER_CURRENT);
7614                        if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7615                            return false;
7616                        }
7617                    }
7618                }
7619                int result = ActivityManager.getService()
7620                        .startActivityAsUser(null, null, mHomeIntent,
7621                                mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
7622                                null, null, 0,
7623                                ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7624                                null, null, UserHandle.USER_CURRENT);
7625                if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7626                    return false;
7627                }
7628            } catch (RemoteException ex) {
7629                // bummer, the activity manager, which is in this process, is dead
7630            }
7631        }
7632        return true;
7633    }
7634
7635    @Override
7636    public void setCurrentOrientationLw(int newOrientation) {
7637        synchronized (mLock) {
7638            if (newOrientation != mCurrentAppOrientation) {
7639                mCurrentAppOrientation = newOrientation;
7640                updateOrientationListenerLp();
7641            }
7642        }
7643    }
7644
7645    private boolean isTheaterModeEnabled() {
7646        return Settings.Global.getInt(mContext.getContentResolver(),
7647                Settings.Global.THEATER_MODE_ON, 0) == 1;
7648    }
7649
7650    private boolean areSystemNavigationKeysEnabled() {
7651        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
7652                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 1, UserHandle.USER_CURRENT) == 1;
7653    }
7654
7655    @Override
7656    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
7657        if (!mVibrator.hasVibrator()) {
7658            return false;
7659        }
7660        final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
7661                Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
7662        if (hapticsDisabled && !always) {
7663            return false;
7664        }
7665
7666        VibrationEffect effect = getVibrationEffect(effectId);
7667        if (effect == null) {
7668            return false;
7669        }
7670
7671        int owningUid;
7672        String owningPackage;
7673        if (win != null) {
7674            owningUid = win.getOwningUid();
7675            owningPackage = win.getOwningPackage();
7676        } else {
7677            owningUid = android.os.Process.myUid();
7678            owningPackage = mContext.getOpPackageName();
7679        }
7680        mVibrator.vibrate(owningUid, owningPackage, effect, VIBRATION_ATTRIBUTES);
7681        return true;
7682    }
7683
7684    private VibrationEffect getVibrationEffect(int effectId) {
7685        long[] pattern;
7686        switch (effectId) {
7687            case HapticFeedbackConstants.VIRTUAL_KEY:
7688                return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
7689            case HapticFeedbackConstants.LONG_PRESS:
7690                pattern = mLongPressVibePattern;
7691                break;
7692            case HapticFeedbackConstants.KEYBOARD_TAP:
7693                return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
7694            case HapticFeedbackConstants.CLOCK_TICK:
7695                pattern = mClockTickVibePattern;
7696                break;
7697            case HapticFeedbackConstants.CALENDAR_DATE:
7698                pattern = mCalendarDateVibePattern;
7699                break;
7700            case HapticFeedbackConstants.SAFE_MODE_DISABLED:
7701                pattern = mSafeModeDisabledVibePattern;
7702                break;
7703            case HapticFeedbackConstants.SAFE_MODE_ENABLED:
7704                pattern = mSafeModeEnabledVibePattern;
7705                break;
7706            case HapticFeedbackConstants.CONTEXT_CLICK:
7707                pattern = mContextClickVibePattern;
7708                break;
7709            default:
7710                return null;
7711        }
7712        if (pattern.length == 0) {
7713            // No vibration
7714            return null;
7715        } else if (pattern.length == 1) {
7716            // One-shot vibration
7717            return VibrationEffect.createOneShot(pattern[0], VibrationEffect.DEFAULT_AMPLITUDE);
7718        } else {
7719            // Pattern vibration
7720            return VibrationEffect.createWaveform(pattern, -1);
7721        }
7722    }
7723
7724    @Override
7725    public void keepScreenOnStartedLw() {
7726    }
7727
7728    @Override
7729    public void keepScreenOnStoppedLw() {
7730        if (isKeyguardShowingAndNotOccluded()) {
7731            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
7732        }
7733    }
7734
7735    private int updateSystemUiVisibilityLw() {
7736        // If there is no window focused, there will be nobody to handle the events
7737        // anyway, so just hang on in whatever state we're in until things settle down.
7738        WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
7739                : mTopFullscreenOpaqueWindowState;
7740        if (winCandidate == null) {
7741            return 0;
7742        }
7743        if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
7744            // The immersive mode confirmation should never affect the system bar visibility,
7745            // otherwise it will unhide the navigation bar and hide itself.
7746            winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState;
7747            if (winCandidate == null) {
7748                return 0;
7749            }
7750        }
7751        final WindowState win = winCandidate;
7752        if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mKeyguardOccluded) {
7753            // We are updating at a point where the keyguard has gotten
7754            // focus, but we were last in a state where the top window is
7755            // hiding it.  This is probably because the keyguard as been
7756            // shown while the top window was displayed, so we want to ignore
7757            // it here because this is just a very transient change and it
7758            // will quickly lose focus once it correctly gets hidden.
7759            return 0;
7760        }
7761
7762        int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
7763                & ~mResettingSystemUiFlags
7764                & ~mForceClearedSystemUiFlags;
7765        if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
7766            tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
7767        }
7768
7769        final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
7770                mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
7771        final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
7772                mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
7773        mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);
7774        mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);
7775        final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
7776        final int diff = visibility ^ mLastSystemUiFlags;
7777        final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
7778        final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
7779        final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
7780        if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
7781                && mFocusedApp == win.getAppToken()
7782                && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
7783                && mLastDockedStackBounds.equals(mDockedStackBounds)) {
7784            return 0;
7785        }
7786        mLastSystemUiFlags = visibility;
7787        mLastFullscreenStackSysUiFlags = fullscreenVisibility;
7788        mLastDockedStackSysUiFlags = dockedVisibility;
7789        mLastFocusNeedsMenu = needsMenu;
7790        mFocusedApp = win.getAppToken();
7791        final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
7792        final Rect dockedStackBounds = new Rect(mDockedStackBounds);
7793        mHandler.post(new Runnable() {
7794                @Override
7795                public void run() {
7796                    StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
7797                    if (statusbar != null) {
7798                        statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
7799                                dockedVisibility, 0xffffffff, fullscreenStackBounds,
7800                                dockedStackBounds, win.toString());
7801                        statusbar.topAppWindowChanged(needsMenu);
7802                    }
7803                }
7804            });
7805        return diff;
7806    }
7807
7808    private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
7809        WindowState statusColorWin = isStatusBarKeyguard() && !mKeyguardOccluded
7810                ? mStatusBar
7811                : opaqueOrDimming;
7812
7813        if (statusColorWin != null) {
7814            if (statusColorWin == opaque) {
7815                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7816                // its light flag.
7817                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7818                vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
7819                        & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7820            } else if (statusColorWin != null && statusColorWin.isDimming()) {
7821                // Otherwise if it's dimming, clear the light flag.
7822                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7823            }
7824        }
7825        return vis;
7826    }
7827
7828    private int updateLightNavigationBarLw(int vis, WindowState opaque,
7829            WindowState opaqueOrDimming) {
7830        final WindowState imeWin = mWindowManagerFuncs.getInputMethodWindowLw();
7831
7832        final WindowState navColorWin;
7833        if (imeWin != null && imeWin.isVisibleLw()) {
7834            navColorWin = imeWin;
7835        } else {
7836            navColorWin = opaqueOrDimming;
7837        }
7838
7839        if (navColorWin != null) {
7840            if (navColorWin == opaque) {
7841                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7842                // its light flag.
7843                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7844                vis |= PolicyControl.getSystemUiVisibility(navColorWin, null)
7845                        & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7846            } else if (navColorWin.isDimming() || navColorWin == imeWin) {
7847                // Otherwise if it's dimming or it's the IME window, clear the light flag.
7848                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7849            }
7850        }
7851        return vis;
7852    }
7853
7854    private boolean drawsSystemBarBackground(WindowState win) {
7855        return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
7856    }
7857
7858    private boolean forcesDrawStatusBarBackground(WindowState win) {
7859        return win == null || (win.getAttrs().privateFlags
7860                & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
7861    }
7862
7863    private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
7864        final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
7865        final boolean freeformStackVisible =
7866                mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
7867        final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
7868
7869        // We need to force system bars when the docked stack is visible, when the freeform stack
7870        // is visible but also when we are resizing for the transitions when docked stack
7871        // visibility changes.
7872        mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
7873        final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
7874
7875        // apply translucent bar vis flags
7876        WindowState fullscreenTransWin = isStatusBarKeyguard() && !mKeyguardOccluded
7877                ? mStatusBar
7878                : mTopFullscreenOpaqueWindowState;
7879        vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7880        vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7881        final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
7882                mTopDockedOpaqueWindowState, 0, 0);
7883
7884        final boolean fullscreenDrawsStatusBarBackground =
7885                (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
7886                        && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
7887                || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
7888        final boolean dockedDrawsStatusBarBackground =
7889                (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
7890                        && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
7891                || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
7892
7893        // prevent status bar interaction from clearing certain flags
7894        int type = win.getAttrs().type;
7895        boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
7896        if (statusBarHasFocus && !isStatusBarKeyguard()) {
7897            int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
7898                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
7899                    | View.SYSTEM_UI_FLAG_IMMERSIVE
7900                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
7901                    | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7902            if (mKeyguardOccluded) {
7903                flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
7904            }
7905            vis = (vis & ~flags) | (oldVis & flags);
7906        }
7907
7908        if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
7909            vis |= View.STATUS_BAR_TRANSPARENT;
7910            vis &= ~View.STATUS_BAR_TRANSLUCENT;
7911        } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
7912                || forceOpaqueStatusBar) {
7913            vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
7914        }
7915
7916        vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
7917
7918        // update status bar
7919        boolean immersiveSticky =
7920                (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7921        final boolean hideStatusBarWM =
7922                mTopFullscreenOpaqueWindowState != null
7923                && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
7924                        & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
7925        final boolean hideStatusBarSysui =
7926                (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
7927        final boolean hideNavBarSysui =
7928                (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
7929
7930        final boolean transientStatusBarAllowed = mStatusBar != null
7931                && (statusBarHasFocus || (!mForceShowSystemBars
7932                        && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
7933
7934        final boolean transientNavBarAllowed = mNavigationBar != null
7935                && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
7936
7937        final long now = SystemClock.uptimeMillis();
7938        final boolean pendingPanic = mPendingPanicGestureUptime != 0
7939                && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
7940        if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
7941            // The user performed the panic gesture recently, we're about to hide the bars,
7942            // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
7943            mPendingPanicGestureUptime = 0;
7944            mStatusBarController.showTransient();
7945            if (!isNavBarEmpty(vis)) {
7946                mNavigationBarController.showTransient();
7947            }
7948        }
7949
7950        final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
7951                && !transientStatusBarAllowed && hideStatusBarSysui;
7952        final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
7953                && !transientNavBarAllowed;
7954        if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
7955            // clear the clearable flags instead
7956            clearClearableFlagsLw();
7957            vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
7958        }
7959
7960        final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
7961        immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7962        final boolean navAllowedHidden = immersive || immersiveSticky;
7963
7964        if (hideNavBarSysui && !navAllowedHidden
7965                && getWindowLayerLw(win) > getWindowLayerFromTypeLw(TYPE_INPUT_CONSUMER)) {
7966            // We can't hide the navbar from this window otherwise the input consumer would not get
7967            // the input events.
7968            vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
7969        }
7970
7971        vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
7972
7973        // update navigation bar
7974        boolean oldImmersiveMode = isImmersiveMode(oldVis);
7975        boolean newImmersiveMode = isImmersiveMode(vis);
7976        if (win != null && oldImmersiveMode != newImmersiveMode) {
7977            final String pkg = win.getOwningPackage();
7978            mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
7979                    isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility()));
7980        }
7981
7982        vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
7983
7984        vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState,
7985                mTopFullscreenOpaqueOrDimmingWindowState);
7986
7987        return vis;
7988    }
7989
7990    /**
7991     * @return the current visibility flags with the nav-bar opacity related flags toggled based
7992     *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
7993     */
7994    private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
7995            boolean freeformStackVisible, boolean isDockedDividerResizing) {
7996        if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
7997            if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
7998                visibility = setNavBarOpaqueFlag(visibility);
7999            }
8000        } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
8001            if (isDockedDividerResizing) {
8002                visibility = setNavBarOpaqueFlag(visibility);
8003            } else if (freeformStackVisible) {
8004                visibility = setNavBarTranslucentFlag(visibility);
8005            } else {
8006                visibility = setNavBarOpaqueFlag(visibility);
8007            }
8008        }
8009
8010        if (!areTranslucentBarsAllowed()) {
8011            visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
8012        }
8013        return visibility;
8014    }
8015
8016    private int setNavBarOpaqueFlag(int visibility) {
8017        return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
8018    }
8019
8020    private int setNavBarTranslucentFlag(int visibility) {
8021        visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
8022        return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
8023    }
8024
8025    private void clearClearableFlagsLw() {
8026        int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
8027        if (newVal != mResettingSystemUiFlags) {
8028            mResettingSystemUiFlags = newVal;
8029            mWindowManagerFuncs.reevaluateStatusBarVisibility();
8030        }
8031    }
8032
8033    private boolean isImmersiveMode(int vis) {
8034        final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
8035        return mNavigationBar != null
8036                && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
8037                && (vis & flags) != 0
8038                && canHideNavigationBar();
8039    }
8040
8041    private static boolean isNavBarEmpty(int systemUiFlags) {
8042        final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
8043                | View.STATUS_BAR_DISABLE_BACK
8044                | View.STATUS_BAR_DISABLE_RECENT);
8045
8046        return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
8047    }
8048
8049    /**
8050     * @return whether the navigation or status bar can be made translucent
8051     *
8052     * This should return true unless touch exploration is not enabled or
8053     * R.boolean.config_enableTranslucentDecor is false.
8054     */
8055    private boolean areTranslucentBarsAllowed() {
8056        return mTranslucentDecorEnabled;
8057    }
8058
8059    // Use this instead of checking config_showNavigationBar so that it can be consistently
8060    // overridden by qemu.hw.mainkeys in the emulator.
8061    @Override
8062    public boolean hasNavigationBar() {
8063        return mHasNavigationBar;
8064    }
8065
8066    @Override
8067    public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
8068        mLastInputMethodWindow = ime;
8069        mLastInputMethodTargetWindow = target;
8070    }
8071
8072    @Override
8073    public void setDismissImeOnBackKeyPressed(boolean newValue) {
8074        mDismissImeOnBackKeyPressed = newValue;
8075    }
8076
8077    @Override
8078    public int getInputMethodWindowVisibleHeightLw() {
8079        return mDockBottom - mCurBottom;
8080    }
8081
8082    @Override
8083    public void setCurrentUserLw(int newUserId) {
8084        mCurrentUserId = newUserId;
8085        if (mKeyguardDelegate != null) {
8086            mKeyguardDelegate.setCurrentUser(newUserId);
8087        }
8088        if (mAccessibilityShortcutController != null) {
8089            mAccessibilityShortcutController.setCurrentUser(newUserId);
8090        }
8091        StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
8092        if (statusBar != null) {
8093            statusBar.setCurrentUser(newUserId);
8094        }
8095        setLastInputMethodWindowLw(null, null);
8096    }
8097
8098    @Override
8099    public void setSwitchingUser(boolean switching) {
8100        mKeyguardDelegate.setSwitchingUser(switching);
8101    }
8102
8103    @Override
8104    public boolean canMagnifyWindow(int windowType) {
8105        switch (windowType) {
8106            case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
8107            case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
8108            case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
8109            case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
8110                return false;
8111            }
8112        }
8113        return true;
8114    }
8115
8116    @Override
8117    public boolean isTopLevelWindow(int windowType) {
8118        if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
8119                && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
8120            return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
8121        }
8122        return true;
8123    }
8124
8125    @Override
8126    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
8127        // For the upside down rotation we don't rotate seamlessly as the navigation
8128        // bar moves position.
8129        // Note most apps (using orientation:sensor or user as opposed to fullSensor)
8130        // will not enter the reverse portrait orientation, so actually the
8131        // orientation won't change at all.
8132        if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
8133            return false;
8134        }
8135        // If the navigation bar can't change sides, then it will
8136        // jump when we change orientations and we don't rotate
8137        // seamlessly.
8138        if (!mNavigationBarCanMove) {
8139            return false;
8140        }
8141        int delta = newRotation - oldRotation;
8142        if (delta < 0) delta += 4;
8143        // Likewise we don't rotate seamlessly for 180 degree rotations
8144        // in this case the surfaces never resize, and our logic to
8145        // revert the transformations on size change will fail. We could
8146        // fix this in the future with the "tagged" frames idea.
8147        if (delta == Surface.ROTATION_180) {
8148            return false;
8149        }
8150
8151        final WindowState w = mTopFullscreenOpaqueWindowState;
8152        if (w != mFocusedWindow) {
8153            return false;
8154        }
8155
8156        // We only enable seamless rotation if the top window has requested
8157        // it and is in the fullscreen opaque state. Seamless rotation
8158        // requires freezing various Surface states and won't work well
8159        // with animations, so we disable it in the animation case for now.
8160        if (w != null && !w.isAnimatingLw() &&
8161                ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) ||
8162                        (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) {
8163            return true;
8164        }
8165        return false;
8166    }
8167
8168    @Override
8169    public void dump(String prefix, PrintWriter pw, String[] args) {
8170        pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
8171                pw.print(" mSystemReady="); pw.print(mSystemReady);
8172                pw.print(" mSystemBooted="); pw.println(mSystemBooted);
8173        pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
8174                pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
8175                pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
8176                pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
8177        if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
8178                || mForceClearedSystemUiFlags != 0) {
8179            pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
8180                    pw.print(Integer.toHexString(mLastSystemUiFlags));
8181                    pw.print(" mResettingSystemUiFlags=0x");
8182                    pw.print(Integer.toHexString(mResettingSystemUiFlags));
8183                    pw.print(" mForceClearedSystemUiFlags=0x");
8184                    pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
8185        }
8186        if (mLastFocusNeedsMenu) {
8187            pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
8188                    pw.println(mLastFocusNeedsMenu);
8189        }
8190        pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
8191                pw.println(mWakeGestureEnabledSetting);
8192
8193        pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
8194        pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
8195                pw.print(" mDockMode="); pw.print(mDockMode);
8196                pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
8197                pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
8198                pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
8199        pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
8200                pw.print(" mUserRotation="); pw.print(mUserRotation);
8201                pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
8202        pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
8203        pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
8204                pw.print(mCarDockEnablesAccelerometer);
8205                pw.print(" mDeskDockEnablesAccelerometer=");
8206                pw.println(mDeskDockEnablesAccelerometer);
8207        pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
8208                pw.print(mLidKeyboardAccessibility);
8209                pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
8210                pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
8211                pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
8212        pw.print(prefix);
8213                pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
8214        pw.print(prefix);
8215                pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
8216                pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
8217        pw.print(prefix);
8218                pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
8219                pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
8220        pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
8221        pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
8222        pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
8223                pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
8224        pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
8225                pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
8226        pw.print(prefix); pw.print("mOrientationSensorEnabled=");
8227                pw.println(mOrientationSensorEnabled);
8228        pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
8229                pw.print(","); pw.print(mOverscanScreenTop);
8230                pw.print(") "); pw.print(mOverscanScreenWidth);
8231                pw.print("x"); pw.println(mOverscanScreenHeight);
8232        if (mOverscanLeft != 0 || mOverscanTop != 0
8233                || mOverscanRight != 0 || mOverscanBottom != 0) {
8234            pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
8235                    pw.print(" top="); pw.print(mOverscanTop);
8236                    pw.print(" right="); pw.print(mOverscanRight);
8237                    pw.print(" bottom="); pw.println(mOverscanBottom);
8238        }
8239        pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
8240                pw.print(mRestrictedOverscanScreenLeft);
8241                pw.print(","); pw.print(mRestrictedOverscanScreenTop);
8242                pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
8243                pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
8244        pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
8245                pw.print(","); pw.print(mUnrestrictedScreenTop);
8246                pw.print(") "); pw.print(mUnrestrictedScreenWidth);
8247                pw.print("x"); pw.println(mUnrestrictedScreenHeight);
8248        pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
8249                pw.print(","); pw.print(mRestrictedScreenTop);
8250                pw.print(") "); pw.print(mRestrictedScreenWidth);
8251                pw.print("x"); pw.println(mRestrictedScreenHeight);
8252        pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
8253                pw.print(","); pw.print(mStableFullscreenTop);
8254                pw.print(")-("); pw.print(mStableFullscreenRight);
8255                pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
8256        pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
8257                pw.print(","); pw.print(mStableTop);
8258                pw.print(")-("); pw.print(mStableRight);
8259                pw.print(","); pw.print(mStableBottom); pw.println(")");
8260        pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
8261                pw.print(","); pw.print(mSystemTop);
8262                pw.print(")-("); pw.print(mSystemRight);
8263                pw.print(","); pw.print(mSystemBottom); pw.println(")");
8264        pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
8265                pw.print(","); pw.print(mCurTop);
8266                pw.print(")-("); pw.print(mCurRight);
8267                pw.print(","); pw.print(mCurBottom); pw.println(")");
8268        pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
8269                pw.print(","); pw.print(mContentTop);
8270                pw.print(")-("); pw.print(mContentRight);
8271                pw.print(","); pw.print(mContentBottom); pw.println(")");
8272        pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft);
8273                pw.print(","); pw.print(mVoiceContentTop);
8274                pw.print(")-("); pw.print(mVoiceContentRight);
8275                pw.print(","); pw.print(mVoiceContentBottom); pw.println(")");
8276        pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
8277                pw.print(","); pw.print(mDockTop);
8278                pw.print(")-("); pw.print(mDockRight);
8279                pw.print(","); pw.print(mDockBottom); pw.println(")");
8280        pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
8281                pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
8282        pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
8283                pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
8284                pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
8285        if (mLastInputMethodWindow != null) {
8286            pw.print(prefix); pw.print("mLastInputMethodWindow=");
8287                    pw.println(mLastInputMethodWindow);
8288        }
8289        if (mLastInputMethodTargetWindow != null) {
8290            pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
8291                    pw.println(mLastInputMethodTargetWindow);
8292        }
8293        pw.print(prefix); pw.print("mDismissImeOnBackKeyPressed=");
8294                pw.println(mDismissImeOnBackKeyPressed);
8295        if (mStatusBar != null) {
8296            pw.print(prefix); pw.print("mStatusBar=");
8297                    pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
8298                    pw.println(isStatusBarKeyguard());
8299        }
8300        if (mNavigationBar != null) {
8301            pw.print(prefix); pw.print("mNavigationBar=");
8302                    pw.println(mNavigationBar);
8303        }
8304        if (mFocusedWindow != null) {
8305            pw.print(prefix); pw.print("mFocusedWindow=");
8306                    pw.println(mFocusedWindow);
8307        }
8308        if (mFocusedApp != null) {
8309            pw.print(prefix); pw.print("mFocusedApp=");
8310                    pw.println(mFocusedApp);
8311        }
8312        if (mTopFullscreenOpaqueWindowState != null) {
8313            pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
8314                    pw.println(mTopFullscreenOpaqueWindowState);
8315        }
8316        if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
8317            pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
8318                    pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
8319        }
8320        if (mForcingShowNavBar) {
8321            pw.print(prefix); pw.print("mForcingShowNavBar=");
8322                    pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
8323                    pw.println(mForcingShowNavBarLayer);
8324        }
8325        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
8326                pw.print(" mKeyguardOccluded="); pw.println(mKeyguardOccluded);
8327                pw.print(" mKeyguardOccludedChanged="); pw.println(mKeyguardOccludedChanged);
8328                pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded);
8329        pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
8330                pw.print(" mForceStatusBarFromKeyguard=");
8331                pw.println(mForceStatusBarFromKeyguard);
8332        pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
8333        pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
8334                pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
8335                pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
8336        pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
8337                pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
8338                pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior);
8339                pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
8340        pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
8341                pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
8342        pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
8343                pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
8344        pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
8345                pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
8346        pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
8347        if (mHasFeatureLeanback) {
8348            pw.print(prefix);
8349            pw.print("mAccessibilityTvKey1Pressed="); pw.println(mAccessibilityTvKey1Pressed);
8350            pw.print(prefix);
8351            pw.print("mAccessibilityTvKey2Pressed="); pw.println(mAccessibilityTvKey2Pressed);
8352            pw.print(prefix);
8353            pw.print("mAccessibilityTvScheduled="); pw.println(mAccessibilityTvScheduled);
8354        }
8355
8356        mGlobalKeyManager.dump(prefix, pw);
8357        mStatusBarController.dump(pw, prefix);
8358        mNavigationBarController.dump(pw, prefix);
8359        PolicyControl.dump(prefix, pw);
8360
8361        if (mWakeGestureListener != null) {
8362            mWakeGestureListener.dump(pw, prefix);
8363        }
8364        if (mOrientationListener != null) {
8365            mOrientationListener.dump(pw, prefix);
8366        }
8367        if (mBurnInProtectionHelper != null) {
8368            mBurnInProtectionHelper.dump(prefix, pw);
8369        }
8370        if (mKeyguardDelegate != null) {
8371            mKeyguardDelegate.dump(prefix, pw);
8372        }
8373    }
8374}
8375