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