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