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