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