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