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