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