PhoneWindowManager.java revision ac52f2892d5c72c26387d510093ddfc741a8a632
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 mPictureInPictureVisible;
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_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_PICTURE_IN_PICTURE_MENU:
884                    showPictureInPictureMenuInternal();
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(isKeyguardLocked())
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 showPictureInPictureMenu(KeyEvent event) {
1730        if (DEBUG_INPUT) Log.d(TAG, "showPictureInPictureMenu event=" + event);
1731        mHandler.removeMessages(MSG_SHOW_PICTURE_IN_PICTURE_MENU);
1732        Message msg = mHandler.obtainMessage(MSG_SHOW_PICTURE_IN_PICTURE_MENU);
1733        msg.setAsynchronous(true);
1734        msg.sendToTarget();
1735    }
1736
1737    private void showPictureInPictureMenuInternal() {
1738        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
1739        if (statusbar != null) {
1740            statusbar.showPictureInPictureMenu();
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(), mCurrentUserId);
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().getApplicationInfoAsUser(
2406                            attrs.packageName,
2407                            0 /* flags */,
2408                            UserHandle.getUserId(callingUid));
2409        } catch (PackageManager.NameNotFoundException e) {
2410            appInfo = null;
2411        }
2412
2413        if (appInfo == null || (type != TYPE_APPLICATION_OVERLAY && appInfo.targetSdkVersion >= O)) {
2414            /**
2415             * Apps targeting >= {@link Build.VERSION_CODES#O} are required to hold
2416             * {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW} (system signature apps)
2417             * permission to add alert windows that aren't
2418             * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY}.
2419             */
2420            return (mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
2421                    == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
2422        }
2423
2424        // check if user has enabled this operation. SecurityException will be thrown if this app
2425        // has not been allowed by the user
2426        final int mode = mAppOpsManager.checkOpNoThrow(outAppOp[0], callingUid, attrs.packageName);
2427        switch (mode) {
2428            case AppOpsManager.MODE_ALLOWED:
2429            case AppOpsManager.MODE_IGNORED:
2430                // although we return ADD_OKAY for MODE_IGNORED, the added window will
2431                // actually be hidden in WindowManagerService
2432                return ADD_OKAY;
2433            case AppOpsManager.MODE_ERRORED:
2434                // Don't crash legacy apps
2435                if (appInfo.targetSdkVersion < M) {
2436                    return ADD_OKAY;
2437                }
2438                return ADD_PERMISSION_DENIED;
2439            default:
2440                // in the default mode, we will make a decision here based on
2441                // checkCallingPermission()
2442                return (mContext.checkCallingOrSelfPermission(SYSTEM_ALERT_WINDOW)
2443                        == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
2444        }
2445    }
2446
2447    @Override
2448    public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) {
2449
2450        // If this switch statement is modified, modify the comment in the declarations of
2451        // the type in {@link WindowManager.LayoutParams} as well.
2452        switch (attrs.type) {
2453            default:
2454                // These are the windows that by default are shown only to the user that created
2455                // them. If this needs to be overridden, set
2456                // {@link WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS} in
2457                // {@link WindowManager.LayoutParams}. Note that permission
2458                // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well.
2459                if ((attrs.privateFlags & PRIVATE_FLAG_SHOW_FOR_ALL_USERS) == 0) {
2460                    return true;
2461                }
2462                break;
2463
2464            // These are the windows that by default are shown to all users. However, to
2465            // protect against spoofing, check permissions below.
2466            case TYPE_APPLICATION_STARTING:
2467            case TYPE_BOOT_PROGRESS:
2468            case TYPE_DISPLAY_OVERLAY:
2469            case TYPE_INPUT_CONSUMER:
2470            case TYPE_KEYGUARD_DIALOG:
2471            case TYPE_MAGNIFICATION_OVERLAY:
2472            case TYPE_NAVIGATION_BAR:
2473            case TYPE_NAVIGATION_BAR_PANEL:
2474            case TYPE_PHONE:
2475            case TYPE_POINTER:
2476            case TYPE_PRIORITY_PHONE:
2477            case TYPE_SEARCH_BAR:
2478            case TYPE_STATUS_BAR:
2479            case TYPE_STATUS_BAR_PANEL:
2480            case TYPE_STATUS_BAR_SUB_PANEL:
2481            case TYPE_SYSTEM_DIALOG:
2482            case TYPE_VOLUME_OVERLAY:
2483            case TYPE_PRESENTATION:
2484            case TYPE_PRIVATE_PRESENTATION:
2485            case TYPE_DOCK_DIVIDER:
2486                break;
2487        }
2488
2489        // Check if third party app has set window to system window type.
2490        return mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW) != PERMISSION_GRANTED;
2491    }
2492
2493    @Override
2494    public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
2495        switch (attrs.type) {
2496            case TYPE_SYSTEM_OVERLAY:
2497            case TYPE_SECURE_SYSTEM_OVERLAY:
2498                // These types of windows can't receive input events.
2499                attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2500                        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
2501                attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
2502                break;
2503            case TYPE_STATUS_BAR:
2504
2505                // If the Keyguard is in a hidden state (occluded by another window), we force to
2506                // remove the wallpaper and keyguard flag so that any change in-flight after setting
2507                // the keyguard as occluded wouldn't set these flags again.
2508                // See {@link #processKeyguardSetHiddenResultLw}.
2509                if (mKeyguardOccluded) {
2510                    attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
2511                    attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2512                }
2513                break;
2514
2515            case TYPE_SCREENSHOT:
2516                attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
2517                break;
2518
2519            case TYPE_TOAST:
2520                // While apps should use the dedicated toast APIs to add such windows
2521                // it possible legacy apps to add the window directly. Therefore, we
2522                // make windows added directly by the app behave as a toast as much
2523                // as possible in terms of timeout and animation.
2524                if (attrs.hideTimeoutMilliseconds < 0
2525                        || attrs.hideTimeoutMilliseconds > TOAST_WINDOW_TIMEOUT) {
2526                    attrs.hideTimeoutMilliseconds = TOAST_WINDOW_TIMEOUT;
2527                }
2528                attrs.windowAnimations = com.android.internal.R.style.Animation_Toast;
2529                break;
2530        }
2531
2532        if (attrs.type != TYPE_STATUS_BAR) {
2533            // The status bar is the only window allowed to exhibit keyguard behavior.
2534            attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2535        }
2536
2537        if (ActivityManager.isHighEndGfx()) {
2538            if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
2539                attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
2540            }
2541            final boolean forceWindowDrawsStatusBarBackground =
2542                    (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND)
2543                            != 0;
2544            if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
2545                    || forceWindowDrawsStatusBarBackground
2546                            && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) {
2547                attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2548            }
2549        }
2550    }
2551
2552    void readLidState() {
2553        mLidState = mWindowManagerFuncs.getLidState();
2554    }
2555
2556    private void readCameraLensCoverState() {
2557        mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState();
2558    }
2559
2560    private boolean isHidden(int accessibilityMode) {
2561        switch (accessibilityMode) {
2562            case 1:
2563                return mLidState == LID_CLOSED;
2564            case 2:
2565                return mLidState == LID_OPEN;
2566            default:
2567                return false;
2568        }
2569    }
2570
2571    /** {@inheritDoc} */
2572    @Override
2573    public void adjustConfigurationLw(Configuration config, int keyboardPresence,
2574            int navigationPresence) {
2575        mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0;
2576
2577        readConfigurationDependentBehaviors();
2578        readLidState();
2579
2580        if (config.keyboard == Configuration.KEYBOARD_NOKEYS
2581                || (keyboardPresence == PRESENCE_INTERNAL
2582                        && isHidden(mLidKeyboardAccessibility))) {
2583            config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
2584            if (!mHasSoftInput) {
2585                config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
2586            }
2587        }
2588
2589        if (config.navigation == Configuration.NAVIGATION_NONAV
2590                || (navigationPresence == PRESENCE_INTERNAL
2591                        && isHidden(mLidNavigationAccessibility))) {
2592            config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
2593        }
2594    }
2595
2596    @Override
2597    public void onConfigurationChanged() {
2598        // TODO(multi-display): Define policy for secondary displays.
2599        final Resources res = mContext.getResources();
2600
2601        mStatusBarHeight =
2602                res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
2603
2604        // Height of the navigation bar when presented horizontally at bottom
2605        mNavigationBarHeightForRotationDefault[mPortraitRotation] =
2606        mNavigationBarHeightForRotationDefault[mUpsideDownRotation] =
2607                res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
2608        mNavigationBarHeightForRotationDefault[mLandscapeRotation] =
2609        mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize(
2610                com.android.internal.R.dimen.navigation_bar_height_landscape);
2611
2612        // Width of the navigation bar when presented vertically along one side
2613        mNavigationBarWidthForRotationDefault[mPortraitRotation] =
2614        mNavigationBarWidthForRotationDefault[mUpsideDownRotation] =
2615        mNavigationBarWidthForRotationDefault[mLandscapeRotation] =
2616        mNavigationBarWidthForRotationDefault[mSeascapeRotation] =
2617                res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
2618
2619        if (ALTERNATE_CAR_MODE_NAV_SIZE) {
2620            // Height of the navigation bar when presented horizontally at bottom
2621            mNavigationBarHeightForRotationInCarMode[mPortraitRotation] =
2622            mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] =
2623                    res.getDimensionPixelSize(
2624                            com.android.internal.R.dimen.navigation_bar_height_car_mode);
2625            mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] =
2626            mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize(
2627                    com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode);
2628
2629            // Width of the navigation bar when presented vertically along one side
2630            mNavigationBarWidthForRotationInCarMode[mPortraitRotation] =
2631            mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] =
2632            mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] =
2633            mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] =
2634                    res.getDimensionPixelSize(
2635                            com.android.internal.R.dimen.navigation_bar_width_car_mode);
2636        }
2637    }
2638
2639    @Override
2640    public int getMaxWallpaperLayer() {
2641        return getWindowLayerFromTypeLw(TYPE_STATUS_BAR);
2642    }
2643
2644    private int getNavigationBarWidth(int rotation, int uiMode) {
2645        if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2646            return mNavigationBarWidthForRotationInCarMode[rotation];
2647        } else {
2648            return mNavigationBarWidthForRotationDefault[rotation];
2649        }
2650    }
2651
2652    @Override
2653    public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
2654            int displayId) {
2655        // TODO(multi-display): Support navigation bar on secondary displays.
2656        if (displayId == Display.DEFAULT_DISPLAY && mHasNavigationBar) {
2657            // For a basic navigation bar, when we are in landscape mode we place
2658            // the navigation bar to the side.
2659            if (mNavigationBarCanMove && fullWidth > fullHeight) {
2660                return fullWidth - getNavigationBarWidth(rotation, uiMode);
2661            }
2662        }
2663        return fullWidth;
2664    }
2665
2666    private int getNavigationBarHeight(int rotation, int uiMode) {
2667        if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2668            return mNavigationBarHeightForRotationInCarMode[rotation];
2669        } else {
2670            return mNavigationBarHeightForRotationDefault[rotation];
2671        }
2672    }
2673
2674    @Override
2675    public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
2676            int displayId) {
2677        // TODO(multi-display): Support navigation bar on secondary displays.
2678        if (displayId == Display.DEFAULT_DISPLAY && mHasNavigationBar) {
2679            // For a basic navigation bar, when we are in portrait mode we place
2680            // the navigation bar to the bottom.
2681            if (!mNavigationBarCanMove || fullWidth < fullHeight) {
2682                return fullHeight - getNavigationBarHeight(rotation, uiMode);
2683            }
2684        }
2685        return fullHeight;
2686    }
2687
2688    @Override
2689    public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
2690            int displayId) {
2691        return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode, displayId);
2692    }
2693
2694    @Override
2695    public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
2696            int displayId) {
2697        // There is a separate status bar at the top of the display.  We don't count that as part
2698        // of the fixed decor, since it can hide; however, for purposes of configurations,
2699        // we do want to exclude it since applications can't generally use that part
2700        // of the screen.
2701        // TODO(multi-display): Support status bars on secondary displays.
2702        if (displayId == Display.DEFAULT_DISPLAY) {
2703            return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayId)
2704                    - mStatusBarHeight;
2705        }
2706        return fullHeight;
2707    }
2708
2709    @Override
2710    public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) {
2711        return attrs.type == TYPE_STATUS_BAR;
2712    }
2713
2714    @Override
2715    public boolean canBeHiddenByKeyguardLw(WindowState win) {
2716        switch (win.getAttrs().type) {
2717            case TYPE_STATUS_BAR:
2718            case TYPE_NAVIGATION_BAR:
2719            case TYPE_WALLPAPER:
2720            case TYPE_DREAM:
2721                return false;
2722            default:
2723                // Hide only windows below the keyguard host window.
2724                return getWindowLayerLw(win) < getWindowLayerFromTypeLw(TYPE_STATUS_BAR);
2725        }
2726    }
2727
2728    private boolean shouldBeHiddenByKeyguard(WindowState win, WindowState imeTarget) {
2729
2730        // Keyguard visibility of window from activities are determined over activity visibility.
2731        if (win.getAppToken() != null) {
2732            return false;
2733        }
2734
2735        final LayoutParams attrs = win.getAttrs();
2736        final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleLw() &&
2737                ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0
2738                        || !canBeHiddenByKeyguardLw(imeTarget));
2739
2740        // Show IME over the keyguard if the target allows it
2741        boolean allowWhenLocked = (win.isInputMethodWindow() || imeTarget == this)
2742                && showImeOverKeyguard;;
2743
2744        if (isKeyguardLocked() && isKeyguardOccluded()) {
2745            // Show SHOW_WHEN_LOCKED windows if Keyguard is occluded.
2746            allowWhenLocked |= (attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
2747                    // Show error dialogs over apps that are shown on lockscreen
2748                    || (attrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
2749        }
2750
2751        boolean keyguardLocked = isKeyguardLocked();
2752        boolean hideDockDivider = attrs.type == TYPE_DOCK_DIVIDER
2753                && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
2754        return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == Display.DEFAULT_DISPLAY)
2755                || hideDockDivider;
2756    }
2757
2758    /** {@inheritDoc} */
2759    @Override
2760    public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme,
2761            CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon,
2762            int logo, int windowFlags, Configuration overrideConfig, int displayId) {
2763        if (!SHOW_SPLASH_SCREENS) {
2764            return null;
2765        }
2766        if (packageName == null) {
2767            return null;
2768        }
2769
2770        WindowManager wm = null;
2771        View view = null;
2772
2773        try {
2774            Context context = mContext;
2775            if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen " + packageName
2776                    + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
2777                    + Integer.toHexString(theme));
2778
2779            // Obtain proper context to launch on the right display.
2780            final Context displayContext = getDisplayContext(context, displayId);
2781            if (displayContext == null) {
2782                // Can't show splash screen on requested display, so skip showing at all.
2783                return null;
2784            }
2785            context = displayContext;
2786
2787            if (theme != context.getThemeResId() || labelRes != 0) {
2788                try {
2789                    context = context.createPackageContext(packageName, 0);
2790                    context.setTheme(theme);
2791                } catch (PackageManager.NameNotFoundException e) {
2792                    // Ignore
2793                }
2794            }
2795
2796            if (overrideConfig != null && !overrideConfig.equals(EMPTY)) {
2797                if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: creating context based"
2798                        + " on overrideConfig" + overrideConfig + " for splash screen");
2799                final Context overrideContext = context.createConfigurationContext(overrideConfig);
2800                overrideContext.setTheme(theme);
2801                final TypedArray typedArray = overrideContext.obtainStyledAttributes(
2802                        com.android.internal.R.styleable.Window);
2803                final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
2804                if (resId != 0 && overrideContext.getDrawable(resId) != null) {
2805                    // We want to use the windowBackground for the override context if it is
2806                    // available, otherwise we use the default one to make sure a themed starting
2807                    // window is displayed for the app.
2808                    if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: apply overrideConfig"
2809                            + overrideConfig + " to starting window resId=" + resId);
2810                    context = overrideContext;
2811                }
2812            }
2813
2814            final PhoneWindow win = new PhoneWindow(context);
2815            win.setIsStartingWindow(true);
2816
2817            CharSequence label = context.getResources().getText(labelRes, null);
2818            // Only change the accessibility title if the label is localized
2819            if (label != null) {
2820                win.setTitle(label, true);
2821            } else {
2822                win.setTitle(nonLocalizedLabel, false);
2823            }
2824
2825            win.setType(
2826                WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
2827
2828            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
2829                // Assumes it's safe to show starting windows of launched apps while
2830                // the keyguard is being hidden. This is okay because starting windows never show
2831                // secret information.
2832                if (mKeyguardOccluded) {
2833                    windowFlags |= FLAG_SHOW_WHEN_LOCKED;
2834                }
2835            }
2836
2837            // Force the window flags: this is a fake window, so it is not really
2838            // touchable or focusable by the user.  We also add in the ALT_FOCUSABLE_IM
2839            // flag because we do know that the next window will take input
2840            // focus, so we want to get the IME window up on top of us right away.
2841            win.setFlags(
2842                windowFlags|
2843                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2844                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2845                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
2846                windowFlags|
2847                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2848                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2849                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
2850
2851            win.setDefaultIcon(icon);
2852            win.setDefaultLogo(logo);
2853
2854            win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
2855                    WindowManager.LayoutParams.MATCH_PARENT);
2856
2857            final WindowManager.LayoutParams params = win.getAttributes();
2858            params.token = appToken;
2859            params.packageName = packageName;
2860            params.windowAnimations = win.getWindowStyle().getResourceId(
2861                    com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
2862            params.privateFlags |=
2863                    WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
2864            params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
2865
2866            if (!compatInfo.supportsScreen()) {
2867                params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
2868            }
2869
2870            params.setTitle("Splash Screen " + packageName);
2871            wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
2872            view = win.getDecorView();
2873
2874            if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "Adding splash screen window for "
2875                + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null));
2876
2877            wm.addView(view, params);
2878
2879            // Only return the view if it was successfully added to the
2880            // window manager... which we can tell by it having a parent.
2881            return view.getParent() != null ? new SplashScreenSurface(view, appToken) : null;
2882        } catch (WindowManager.BadTokenException e) {
2883            // ignore
2884            Log.w(TAG, appToken + " already running, starting window not displayed. " +
2885                    e.getMessage());
2886        } catch (RuntimeException e) {
2887            // don't crash if something else bad happens, for example a
2888            // failure loading resources because we are loading from an app
2889            // on external storage that has been unmounted.
2890            Log.w(TAG, appToken + " failed creating starting window", e);
2891        } finally {
2892            if (view != null && view.getParent() == null) {
2893                Log.w(TAG, "view not successfully added to wm, removing view");
2894                wm.removeViewImmediate(view);
2895            }
2896        }
2897
2898        return null;
2899    }
2900
2901    /** Obtain proper context for showing splash screen on the provided display. */
2902    private Context getDisplayContext(Context context, int displayId) {
2903        if (displayId == Display.DEFAULT_DISPLAY) {
2904            // The default context fits.
2905            return context;
2906        }
2907
2908        final DisplayManager dm = (DisplayManager) context.getSystemService(DISPLAY_SERVICE);
2909        final Display targetDisplay = dm.getDisplay(displayId);
2910        if (targetDisplay == null) {
2911            // Failed to obtain the non-default display where splash screen should be shown,
2912            // lets not show at all.
2913            return null;
2914        }
2915
2916        return context.createDisplayContext(targetDisplay);
2917    }
2918
2919    /**
2920     * Preflight adding a window to the system.
2921     *
2922     * Currently enforces that three window types are singletons:
2923     * <ul>
2924     * <li>STATUS_BAR_TYPE</li>
2925     * <li>KEYGUARD_TYPE</li>
2926     * </ul>
2927     *
2928     * @param win The window to be added
2929     * @param attrs Information about the window to be added
2930     *
2931     * @return If ok, WindowManagerImpl.ADD_OKAY.  If too many singletons,
2932     * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
2933     */
2934    @Override
2935    public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
2936        switch (attrs.type) {
2937            case TYPE_STATUS_BAR:
2938                mContext.enforceCallingOrSelfPermission(
2939                        android.Manifest.permission.STATUS_BAR_SERVICE,
2940                        "PhoneWindowManager");
2941                if (mStatusBar != null) {
2942                    if (mStatusBar.isAlive()) {
2943                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2944                    }
2945                }
2946                mStatusBar = win;
2947                mStatusBarController.setWindow(win);
2948                break;
2949            case TYPE_NAVIGATION_BAR:
2950                mContext.enforceCallingOrSelfPermission(
2951                        android.Manifest.permission.STATUS_BAR_SERVICE,
2952                        "PhoneWindowManager");
2953                if (mNavigationBar != null) {
2954                    if (mNavigationBar.isAlive()) {
2955                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2956                    }
2957                }
2958                mNavigationBar = win;
2959                mNavigationBarController.setWindow(win);
2960                mNavigationBarController.setOnBarVisibilityChangedListener(
2961                        mNavBarVisibilityListener);
2962                if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
2963                break;
2964            case TYPE_NAVIGATION_BAR_PANEL:
2965            case TYPE_STATUS_BAR_PANEL:
2966            case TYPE_STATUS_BAR_SUB_PANEL:
2967            case TYPE_VOICE_INTERACTION_STARTING:
2968                mContext.enforceCallingOrSelfPermission(
2969                        android.Manifest.permission.STATUS_BAR_SERVICE,
2970                        "PhoneWindowManager");
2971                break;
2972        }
2973        return ADD_OKAY;
2974    }
2975
2976    /** {@inheritDoc} */
2977    @Override
2978    public void removeWindowLw(WindowState win) {
2979        if (mStatusBar == win) {
2980            mStatusBar = null;
2981            mStatusBarController.setWindow(null);
2982        } else if (mNavigationBar == win) {
2983            mNavigationBar = null;
2984            mNavigationBarController.setWindow(null);
2985        }
2986    }
2987
2988    static final boolean PRINT_ANIM = false;
2989
2990    /** {@inheritDoc} */
2991    @Override
2992    public int selectAnimationLw(WindowState win, int transit) {
2993        if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
2994              + ": transit=" + transit);
2995        if (win == mStatusBar) {
2996            boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
2997            if (transit == TRANSIT_EXIT
2998                    || transit == TRANSIT_HIDE) {
2999                return isKeyguard ? -1 : R.anim.dock_top_exit;
3000            } else if (transit == TRANSIT_ENTER
3001                    || transit == TRANSIT_SHOW) {
3002                return isKeyguard ? -1 : R.anim.dock_top_enter;
3003            }
3004        } else if (win == mNavigationBar) {
3005            if (win.getAttrs().windowAnimations != 0) {
3006                return 0;
3007            }
3008            // This can be on either the bottom or the right or the left.
3009            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
3010                if (transit == TRANSIT_EXIT
3011                        || transit == TRANSIT_HIDE) {
3012                    if (isKeyguardShowingAndNotOccluded()) {
3013                        return R.anim.dock_bottom_exit_keyguard;
3014                    } else {
3015                        return R.anim.dock_bottom_exit;
3016                    }
3017                } else if (transit == TRANSIT_ENTER
3018                        || transit == TRANSIT_SHOW) {
3019                    return R.anim.dock_bottom_enter;
3020                }
3021            } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
3022                if (transit == TRANSIT_EXIT
3023                        || transit == TRANSIT_HIDE) {
3024                    return R.anim.dock_right_exit;
3025                } else if (transit == TRANSIT_ENTER
3026                        || transit == TRANSIT_SHOW) {
3027                    return R.anim.dock_right_enter;
3028                }
3029            } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
3030                if (transit == TRANSIT_EXIT
3031                        || transit == TRANSIT_HIDE) {
3032                    return R.anim.dock_left_exit;
3033                } else if (transit == TRANSIT_ENTER
3034                        || transit == TRANSIT_SHOW) {
3035                    return R.anim.dock_left_enter;
3036                }
3037            }
3038        } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) {
3039            return selectDockedDividerAnimationLw(win, transit);
3040        }
3041
3042        if (transit == TRANSIT_PREVIEW_DONE) {
3043            if (win.hasAppShownWindows()) {
3044                if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
3045                return com.android.internal.R.anim.app_starting_exit;
3046            }
3047        } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
3048                && transit == TRANSIT_ENTER) {
3049            // Special case: we are animating in a dream, while the keyguard
3050            // is shown.  We don't want an animation on the dream, because
3051            // we need it shown immediately with the keyguard animating away
3052            // to reveal it.
3053            return -1;
3054        }
3055
3056        return 0;
3057    }
3058
3059    private int selectDockedDividerAnimationLw(WindowState win, int transit) {
3060        int insets = mWindowManagerFuncs.getDockedDividerInsetsLw();
3061
3062        // If the divider is behind the navigation bar, don't animate.
3063        final Rect frame = win.getFrameLw();
3064        final boolean behindNavBar = mNavigationBar != null
3065                && ((mNavigationBarPosition == NAV_BAR_BOTTOM
3066                        && frame.top + insets >= mNavigationBar.getFrameLw().top)
3067                || (mNavigationBarPosition == NAV_BAR_RIGHT
3068                        && frame.left + insets >= mNavigationBar.getFrameLw().left)
3069                || (mNavigationBarPosition == NAV_BAR_LEFT
3070                        && frame.right - insets <= mNavigationBar.getFrameLw().right));
3071        final boolean landscape = frame.height() > frame.width();
3072        final boolean offscreenLandscape = landscape && (frame.right - insets <= 0
3073                || frame.left + insets >= win.getDisplayFrameLw().right);
3074        final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0
3075                || frame.bottom + insets >= win.getDisplayFrameLw().bottom);
3076        final boolean offscreen = offscreenLandscape || offscreenPortrait;
3077        if (behindNavBar || offscreen) {
3078            return 0;
3079        }
3080        if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
3081            return R.anim.fade_in;
3082        } else if (transit == TRANSIT_EXIT) {
3083            return R.anim.fade_out;
3084        } else {
3085            return 0;
3086        }
3087    }
3088
3089    @Override
3090    public void selectRotationAnimationLw(int anim[]) {
3091        if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
3092                + mTopFullscreenOpaqueWindowState + " rotationAnimation="
3093                + (mTopFullscreenOpaqueWindowState == null ?
3094                        "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation));
3095        if (mTopFullscreenOpaqueWindowState != null) {
3096            int animationHint = mTopFullscreenOpaqueWindowState.getRotationAnimationHint();
3097            if (animationHint < 0 && mTopIsFullscreen) {
3098                animationHint = mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation;
3099            }
3100            switch (animationHint) {
3101                case ROTATION_ANIMATION_CROSSFADE:
3102                case ROTATION_ANIMATION_SEAMLESS: // Crossfade is fallback for seamless.
3103                    anim[0] = R.anim.rotation_animation_xfade_exit;
3104                    anim[1] = R.anim.rotation_animation_enter;
3105                    break;
3106                case ROTATION_ANIMATION_JUMPCUT:
3107                    anim[0] = R.anim.rotation_animation_jump_exit;
3108                    anim[1] = R.anim.rotation_animation_enter;
3109                    break;
3110                case ROTATION_ANIMATION_ROTATE:
3111                default:
3112                    anim[0] = anim[1] = 0;
3113                    break;
3114            }
3115        } else {
3116            anim[0] = anim[1] = 0;
3117        }
3118    }
3119
3120    @Override
3121    public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId,
3122            boolean forceDefault) {
3123        switch (exitAnimId) {
3124            case R.anim.rotation_animation_xfade_exit:
3125            case R.anim.rotation_animation_jump_exit:
3126                // These are the only cases that matter.
3127                if (forceDefault) {
3128                    return false;
3129                }
3130                int anim[] = new int[2];
3131                selectRotationAnimationLw(anim);
3132                return (exitAnimId == anim[0] && enterAnimId == anim[1]);
3133            default:
3134                return true;
3135        }
3136    }
3137
3138    @Override
3139    public Animation createHiddenByKeyguardExit(boolean onWallpaper,
3140            boolean goingToNotificationShade) {
3141        if (goingToNotificationShade) {
3142            return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
3143        }
3144
3145        AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ?
3146                    R.anim.lock_screen_behind_enter_wallpaper :
3147                    R.anim.lock_screen_behind_enter);
3148
3149        // TODO: Use XML interpolators when we have log interpolators available in XML.
3150        final List<Animation> animations = set.getAnimations();
3151        for (int i = animations.size() - 1; i >= 0; --i) {
3152            animations.get(i).setInterpolator(mLogDecelerateInterpolator);
3153        }
3154
3155        return set;
3156    }
3157
3158
3159    @Override
3160    public Animation createKeyguardWallpaperExit(boolean goingToNotificationShade) {
3161        if (goingToNotificationShade) {
3162            return null;
3163        } else {
3164            return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
3165        }
3166    }
3167
3168    private static void awakenDreams() {
3169        IDreamManager dreamManager = getDreamManager();
3170        if (dreamManager != null) {
3171            try {
3172                dreamManager.awaken();
3173            } catch (RemoteException e) {
3174                // fine, stay asleep then
3175            }
3176        }
3177    }
3178
3179    static IDreamManager getDreamManager() {
3180        return IDreamManager.Stub.asInterface(
3181                ServiceManager.checkService(DreamService.DREAM_SERVICE));
3182    }
3183
3184    TelecomManager getTelecommService() {
3185        return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
3186    }
3187
3188    static IAudioService getAudioService() {
3189        IAudioService audioService = IAudioService.Stub.asInterface(
3190                ServiceManager.checkService(Context.AUDIO_SERVICE));
3191        if (audioService == null) {
3192            Log.w(TAG, "Unable to find IAudioService interface.");
3193        }
3194        return audioService;
3195    }
3196
3197    boolean keyguardOn() {
3198        return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode();
3199    }
3200
3201    private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
3202            WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
3203            WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
3204        };
3205
3206    /** {@inheritDoc} */
3207    @Override
3208    public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
3209        final boolean keyguardOn = keyguardOn();
3210        final int keyCode = event.getKeyCode();
3211        final int repeatCount = event.getRepeatCount();
3212        final int metaState = event.getMetaState();
3213        final int flags = event.getFlags();
3214        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
3215        final boolean canceled = event.isCanceled();
3216
3217        if (DEBUG_INPUT) {
3218            Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
3219                    + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
3220                    + " canceled=" + canceled);
3221        }
3222
3223        // If we think we might have a volume down & power key chord on the way
3224        // but we're not sure, then tell the dispatcher to wait a little while and
3225        // try again later before dispatching.
3226        if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
3227            if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
3228                final long now = SystemClock.uptimeMillis();
3229                final long timeoutTime = mScreenshotChordVolumeDownKeyTime
3230                        + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
3231                if (now < timeoutTime) {
3232                    return timeoutTime - now;
3233                }
3234            }
3235            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3236                    && mScreenshotChordVolumeDownKeyConsumed) {
3237                if (!down) {
3238                    mScreenshotChordVolumeDownKeyConsumed = false;
3239                }
3240                return -1;
3241            }
3242        }
3243
3244        // If an accessibility shortcut might be partially complete, hold off dispatching until we
3245        // know if it is complete or not
3246        if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(false)
3247                && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
3248            if (mScreenshotChordVolumeDownKeyTriggered ^ mA11yShortcutChordVolumeUpKeyTriggered) {
3249                final long now = SystemClock.uptimeMillis();
3250                final long timeoutTime = (mScreenshotChordVolumeDownKeyTriggered
3251                        ? mScreenshotChordVolumeDownKeyTime : mA11yShortcutChordVolumeUpKeyTime)
3252                        + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
3253                if (now < timeoutTime) {
3254                    return timeoutTime - now;
3255                }
3256            }
3257            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && mScreenshotChordVolumeDownKeyConsumed) {
3258                if (!down) {
3259                    mScreenshotChordVolumeDownKeyConsumed = false;
3260                }
3261                return -1;
3262            }
3263            if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mA11yShortcutChordVolumeUpKeyConsumed) {
3264                if (!down) {
3265                    mA11yShortcutChordVolumeUpKeyConsumed = false;
3266                }
3267                return -1;
3268            }
3269        }
3270
3271        // Cancel any pending meta actions if we see any other keys being pressed between the down
3272        // of the meta key and its corresponding up.
3273        if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
3274            mPendingMetaAction = false;
3275        }
3276        // Any key that is not Alt or Meta cancels Caps Lock combo tracking.
3277        if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) {
3278            mPendingCapsLockToggle = false;
3279        }
3280
3281        // First we always handle the home key here, so applications
3282        // can never break it, although if keyguard is on, we do let
3283        // it handle it, because that gives us the correct 5 second
3284        // timeout.
3285        if (keyCode == KeyEvent.KEYCODE_HOME) {
3286
3287            // If we have released the home key, and didn't do anything else
3288            // while it was pressed, then it is time to go home!
3289            if (!down) {
3290                cancelPreloadRecentApps();
3291
3292                mHomePressed = false;
3293                if (mHomeConsumed) {
3294                    mHomeConsumed = false;
3295                    return -1;
3296                }
3297
3298                if (canceled) {
3299                    Log.i(TAG, "Ignoring HOME; event canceled.");
3300                    return -1;
3301                }
3302
3303                // Delay handling home if a double-tap is possible.
3304                if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
3305                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
3306                    mHomeDoubleTapPending = true;
3307                    mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
3308                            ViewConfiguration.getDoubleTapTimeout());
3309                    return -1;
3310                }
3311
3312                handleShortPressOnHome();
3313                return -1;
3314            }
3315
3316            // If a system window has focus, then it doesn't make sense
3317            // right now to interact with applications.
3318            WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
3319            if (attrs != null) {
3320                final int type = attrs.type;
3321                if (type == TYPE_KEYGUARD_DIALOG
3322                        || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
3323                    // the "app" is keyguard, so give it the key
3324                    return 0;
3325                }
3326                final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
3327                for (int i=0; i<typeCount; i++) {
3328                    if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
3329                        // don't do anything, but also don't pass it to the app
3330                        return -1;
3331                    }
3332                }
3333            }
3334
3335            // Remember that home is pressed and handle special actions.
3336            if (repeatCount == 0) {
3337                mHomePressed = true;
3338                if (mHomeDoubleTapPending) {
3339                    mHomeDoubleTapPending = false;
3340                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
3341                    handleDoubleTapOnHome();
3342                } else if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
3343                    preloadRecentApps();
3344                }
3345            } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
3346                if (!keyguardOn) {
3347                    handleLongPressOnHome(event.getDeviceId());
3348                }
3349            }
3350            return -1;
3351        } else if (keyCode == KeyEvent.KEYCODE_MENU) {
3352            // Hijack modified menu keys for debugging features
3353            final int chordBug = KeyEvent.META_SHIFT_ON;
3354
3355            if (down && repeatCount == 0) {
3356                if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
3357                    Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
3358                    mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
3359                            null, null, null, 0, null, null);
3360                    return -1;
3361                }
3362            }
3363        } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
3364            if (down) {
3365                if (repeatCount == 0) {
3366                    mSearchKeyShortcutPending = true;
3367                    mConsumeSearchKeyUp = false;
3368                }
3369            } else {
3370                mSearchKeyShortcutPending = false;
3371                if (mConsumeSearchKeyUp) {
3372                    mConsumeSearchKeyUp = false;
3373                    return -1;
3374                }
3375            }
3376            return 0;
3377        } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
3378            if (!keyguardOn) {
3379                if (down && repeatCount == 0) {
3380                    preloadRecentApps();
3381                } else if (!down) {
3382                    toggleRecentApps();
3383                }
3384            }
3385            return -1;
3386        } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) {
3387            if (down) {
3388                IStatusBarService service = getStatusBarService();
3389                if (service != null) {
3390                    try {
3391                        service.expandNotificationsPanel();
3392                    } catch (RemoteException e) {
3393                        // do nothing.
3394                    }
3395                }
3396            }
3397        } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed()
3398                && event.isCtrlPressed()) {
3399            if (down && repeatCount == 0) {
3400                int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION
3401                        : TAKE_SCREENSHOT_FULLSCREEN;
3402                mScreenshotRunnable.setScreenshotType(type);
3403                mHandler.post(mScreenshotRunnable);
3404                return -1;
3405            }
3406        } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
3407            if (down && repeatCount == 0 && !isKeyguardLocked()) {
3408                toggleKeyboardShortcutsMenu(event.getDeviceId());
3409            }
3410        } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
3411            if (down) {
3412                if (repeatCount == 0) {
3413                    mAssistKeyLongPressed = false;
3414                } else if (repeatCount == 1) {
3415                    mAssistKeyLongPressed = true;
3416                    if (!keyguardOn) {
3417                         launchAssistLongPressAction();
3418                    }
3419                }
3420            } else {
3421                if (mAssistKeyLongPressed) {
3422                    mAssistKeyLongPressed = false;
3423                } else {
3424                    if (!keyguardOn) {
3425                        launchAssistAction(null, event.getDeviceId());
3426                    }
3427                }
3428            }
3429            return -1;
3430        } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
3431            if (!down) {
3432                Intent voiceIntent;
3433                if (!keyguardOn) {
3434                    voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
3435                } else {
3436                    IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
3437                            ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
3438                    if (dic != null) {
3439                        try {
3440                            dic.exitIdle("voice-search");
3441                        } catch (RemoteException e) {
3442                        }
3443                    }
3444                    voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
3445                    voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
3446                }
3447                startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
3448            }
3449        } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
3450            if (down && repeatCount == 0) {
3451                mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
3452                mHandler.post(mScreenshotRunnable);
3453            }
3454            return -1;
3455        } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP
3456                || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) {
3457            if (down) {
3458                int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
3459
3460                // Disable autobrightness if it's on
3461                int auto = Settings.System.getIntForUser(
3462                        mContext.getContentResolver(),
3463                        Settings.System.SCREEN_BRIGHTNESS_MODE,
3464                        Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3465                        UserHandle.USER_CURRENT_OR_SELF);
3466                if (auto != 0) {
3467                    Settings.System.putIntForUser(mContext.getContentResolver(),
3468                            Settings.System.SCREEN_BRIGHTNESS_MODE,
3469                            Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3470                            UserHandle.USER_CURRENT_OR_SELF);
3471                }
3472
3473                int min = mPowerManager.getMinimumScreenBrightnessSetting();
3474                int max = mPowerManager.getMaximumScreenBrightnessSetting();
3475                int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction;
3476                int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
3477                        Settings.System.SCREEN_BRIGHTNESS,
3478                        mPowerManager.getDefaultScreenBrightnessSetting(),
3479                        UserHandle.USER_CURRENT_OR_SELF);
3480                brightness += step;
3481                // Make sure we don't go beyond the limits.
3482                brightness = Math.min(max, brightness);
3483                brightness = Math.max(min, brightness);
3484
3485                Settings.System.putIntForUser(mContext.getContentResolver(),
3486                        Settings.System.SCREEN_BRIGHTNESS, brightness,
3487                        UserHandle.USER_CURRENT_OR_SELF);
3488                startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
3489                        UserHandle.CURRENT_OR_SELF);
3490            }
3491            return -1;
3492        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
3493                || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3494                || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
3495            if (mUseTvRouting) {
3496                // On TVs volume keys never go to the foreground app.
3497                dispatchDirectAudioEvent(event);
3498                return -1;
3499            }
3500        } else if (keyCode == KeyEvent.KEYCODE_TAB && event.isMetaPressed()) {
3501            // Pass through keyboard navigation keys.
3502            return 0;
3503        } else if (mHasFeatureLeanback && interceptBugreportGestureTv(keyCode, down)) {
3504            return -1;
3505        }
3506
3507        // Toggle Caps Lock on META-ALT.
3508        boolean actionTriggered = false;
3509        if (KeyEvent.isModifierKey(keyCode)) {
3510            if (!mPendingCapsLockToggle) {
3511                // Start tracking meta state for combo.
3512                mInitialMetaState = mMetaState;
3513                mPendingCapsLockToggle = true;
3514            } else if (event.getAction() == KeyEvent.ACTION_UP) {
3515                int altOnMask = mMetaState & KeyEvent.META_ALT_MASK;
3516                int metaOnMask = mMetaState & KeyEvent.META_META_MASK;
3517
3518                // Check for Caps Lock toggle
3519                if ((metaOnMask != 0) && (altOnMask != 0)) {
3520                    // Check if nothing else is pressed
3521                    if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) {
3522                        // Handle Caps Lock Toggle
3523                        mInputManagerInternal.toggleCapsLock(event.getDeviceId());
3524                        actionTriggered = true;
3525                    }
3526                }
3527
3528                // Always stop tracking when key goes up.
3529                mPendingCapsLockToggle = false;
3530            }
3531        }
3532        // Store current meta state to be able to evaluate it later.
3533        mMetaState = metaState;
3534
3535        if (actionTriggered) {
3536            return -1;
3537        }
3538
3539        if (KeyEvent.isMetaKey(keyCode)) {
3540            if (down) {
3541                mPendingMetaAction = true;
3542            } else if (mPendingMetaAction) {
3543                launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId());
3544            }
3545            return -1;
3546        }
3547
3548        // Shortcuts are invoked through Search+key, so intercept those here
3549        // Any printing key that is chorded with Search should be consumed
3550        // even if no shortcut was invoked.  This prevents text from being
3551        // inadvertently inserted when using a keyboard that has built-in macro
3552        // shortcut keys (that emit Search+x) and some of them are not registered.
3553        if (mSearchKeyShortcutPending) {
3554            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3555            if (kcm.isPrintingKey(keyCode)) {
3556                mConsumeSearchKeyUp = true;
3557                mSearchKeyShortcutPending = false;
3558                if (down && repeatCount == 0 && !keyguardOn) {
3559                    Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
3560                    if (shortcutIntent != null) {
3561                        shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3562                        try {
3563                            startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3564                            dismissKeyboardShortcutsMenu();
3565                        } catch (ActivityNotFoundException ex) {
3566                            Slog.w(TAG, "Dropping shortcut key combination because "
3567                                    + "the activity to which it is registered was not found: "
3568                                    + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);
3569                        }
3570                    } else {
3571                        Slog.i(TAG, "Dropping unregistered shortcut key combination: "
3572                                + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));
3573                    }
3574                }
3575                return -1;
3576            }
3577        }
3578
3579        // Invoke shortcuts using Meta.
3580        if (down && repeatCount == 0 && !keyguardOn
3581                && (metaState & KeyEvent.META_META_ON) != 0) {
3582            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3583            if (kcm.isPrintingKey(keyCode)) {
3584                Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
3585                        metaState & ~(KeyEvent.META_META_ON
3586                                | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
3587                if (shortcutIntent != null) {
3588                    shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3589                    try {
3590                        startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3591                        dismissKeyboardShortcutsMenu();
3592                    } catch (ActivityNotFoundException ex) {
3593                        Slog.w(TAG, "Dropping shortcut key combination because "
3594                                + "the activity to which it is registered was not found: "
3595                                + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
3596                    }
3597                    return -1;
3598                }
3599            }
3600        }
3601
3602        // Handle application launch keys.
3603        if (down && repeatCount == 0 && !keyguardOn) {
3604            String category = sApplicationLaunchKeyCategories.get(keyCode);
3605            if (category != null) {
3606                Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
3607                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3608                try {
3609                    startActivityAsUser(intent, UserHandle.CURRENT);
3610                    dismissKeyboardShortcutsMenu();
3611                } catch (ActivityNotFoundException ex) {
3612                    Slog.w(TAG, "Dropping application launch key because "
3613                            + "the activity to which it is registered was not found: "
3614                            + "keyCode=" + keyCode + ", category=" + category, ex);
3615                }
3616                return -1;
3617            }
3618        }
3619
3620        // Display task switcher for ALT-TAB.
3621        if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
3622            if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
3623                final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
3624                if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
3625                    mRecentAppsHeldModifiers = shiftlessModifiers;
3626                    showRecentApps(true, false);
3627                    return -1;
3628                }
3629            }
3630        } else if (!down && mRecentAppsHeldModifiers != 0
3631                && (metaState & mRecentAppsHeldModifiers) == 0) {
3632            mRecentAppsHeldModifiers = 0;
3633            hideRecentApps(true, false);
3634        }
3635
3636        // Handle input method switching.
3637        if (down && repeatCount == 0
3638                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3639                        || (keyCode == KeyEvent.KEYCODE_SPACE
3640                                && (metaState & KeyEvent.META_META_MASK) != 0))) {
3641            final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0;
3642            mWindowManagerFuncs.switchInputMethod(forwardDirection);
3643            return -1;
3644        }
3645        if (mLanguageSwitchKeyPressed && !down
3646                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3647                        || keyCode == KeyEvent.KEYCODE_SPACE)) {
3648            mLanguageSwitchKeyPressed = false;
3649            return -1;
3650        }
3651
3652        if (isValidGlobalKey(keyCode)
3653                && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
3654            return -1;
3655        }
3656
3657        if (down) {
3658            long shortcutCode = keyCode;
3659            if (event.isCtrlPressed()) {
3660                shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
3661            }
3662
3663            if (event.isAltPressed()) {
3664                shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
3665            }
3666
3667            if (event.isShiftPressed()) {
3668                shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
3669            }
3670
3671            if (event.isMetaPressed()) {
3672                shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE;
3673            }
3674
3675            IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode);
3676            if (shortcutService != null) {
3677                try {
3678                    if (isUserSetupComplete()) {
3679                        shortcutService.notifyShortcutKeyPressed(shortcutCode);
3680                    }
3681                } catch (RemoteException e) {
3682                    mShortcutKeyServices.delete(shortcutCode);
3683                }
3684                return -1;
3685            }
3686        }
3687
3688        // Reserve all the META modifier combos for system behavior
3689        if ((metaState & KeyEvent.META_META_ON) != 0) {
3690            return -1;
3691        }
3692
3693        // Let the application handle the key.
3694        return 0;
3695    }
3696
3697    /**
3698     * TV only: recognizes a remote control gesture for capturing a bug report.
3699     */
3700    private boolean interceptBugreportGestureTv(int keyCode, boolean down) {
3701        // The bugreport capture chord is a long press on DPAD CENTER and BACK simultaneously.
3702        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
3703            mBugreportTvKey1Pressed = down;
3704        } else if (keyCode == KeyEvent.KEYCODE_BACK) {
3705            mBugreportTvKey2Pressed = down;
3706        }
3707
3708        if (mBugreportTvKey1Pressed && mBugreportTvKey2Pressed) {
3709            if (!mBugreportTvScheduled) {
3710                mBugreportTvScheduled = true;
3711                Message msg = Message.obtain(mHandler, MSG_BUGREPORT_TV);
3712                msg.setAsynchronous(true);
3713                mHandler.sendMessageDelayed(msg, BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS);
3714            }
3715        } else if (mBugreportTvScheduled) {
3716            mHandler.removeMessages(MSG_BUGREPORT_TV);
3717            mBugreportTvScheduled = false;
3718        }
3719
3720        return mBugreportTvScheduled;
3721    }
3722
3723    private void takeBugreport() {
3724        if ("1".equals(SystemProperties.get("ro.debuggable"))
3725                || Settings.Global.getInt(mContext.getContentResolver(),
3726                        Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) == 1) {
3727            try {
3728                ActivityManager.getService()
3729                        .requestBugReport(ActivityManager.BUGREPORT_OPTION_INTERACTIVE);
3730            } catch (RemoteException e) {
3731                Slog.e(TAG, "Error taking bugreport", e);
3732            }
3733        }
3734    }
3735
3736    /** {@inheritDoc} */
3737    @Override
3738    public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
3739        // Note: This method is only called if the initial down was unhandled.
3740        if (DEBUG_INPUT) {
3741            Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
3742                    + ", flags=" + event.getFlags()
3743                    + ", keyCode=" + event.getKeyCode()
3744                    + ", scanCode=" + event.getScanCode()
3745                    + ", metaState=" + event.getMetaState()
3746                    + ", repeatCount=" + event.getRepeatCount()
3747                    + ", policyFlags=" + policyFlags);
3748        }
3749
3750        KeyEvent fallbackEvent = null;
3751        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3752            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3753            final int keyCode = event.getKeyCode();
3754            final int metaState = event.getMetaState();
3755            final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
3756                    && event.getRepeatCount() == 0;
3757
3758            // Check for fallback actions specified by the key character map.
3759            final FallbackAction fallbackAction;
3760            if (initialDown) {
3761                fallbackAction = kcm.getFallbackAction(keyCode, metaState);
3762            } else {
3763                fallbackAction = mFallbackActions.get(keyCode);
3764            }
3765
3766            if (fallbackAction != null) {
3767                if (DEBUG_INPUT) {
3768                    Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode
3769                            + " metaState=" + Integer.toHexString(fallbackAction.metaState));
3770                }
3771
3772                final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
3773                fallbackEvent = KeyEvent.obtain(
3774                        event.getDownTime(), event.getEventTime(),
3775                        event.getAction(), fallbackAction.keyCode,
3776                        event.getRepeatCount(), fallbackAction.metaState,
3777                        event.getDeviceId(), event.getScanCode(),
3778                        flags, event.getSource(), null);
3779
3780                if (!interceptFallback(win, fallbackEvent, policyFlags)) {
3781                    fallbackEvent.recycle();
3782                    fallbackEvent = null;
3783                }
3784
3785                if (initialDown) {
3786                    mFallbackActions.put(keyCode, fallbackAction);
3787                } else if (event.getAction() == KeyEvent.ACTION_UP) {
3788                    mFallbackActions.remove(keyCode);
3789                    fallbackAction.recycle();
3790                }
3791            }
3792        }
3793
3794        if (DEBUG_INPUT) {
3795            if (fallbackEvent == null) {
3796                Slog.d(TAG, "No fallback.");
3797            } else {
3798                Slog.d(TAG, "Performing fallback: " + fallbackEvent);
3799            }
3800        }
3801        return fallbackEvent;
3802    }
3803
3804    private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
3805        int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
3806        if ((actions & ACTION_PASS_TO_USER) != 0) {
3807            long delayMillis = interceptKeyBeforeDispatching(
3808                    win, fallbackEvent, policyFlags);
3809            if (delayMillis == 0) {
3810                return true;
3811            }
3812        }
3813        return false;
3814    }
3815
3816    @Override
3817    public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
3818            throws RemoteException {
3819        synchronized (mLock) {
3820            IShortcutService service = mShortcutKeyServices.get(shortcutCode);
3821            if (service != null && service.asBinder().pingBinder()) {
3822                throw new RemoteException("Key already exists.");
3823            }
3824
3825            mShortcutKeyServices.put(shortcutCode, shortcutService);
3826        }
3827    }
3828
3829    @Override
3830    public void onKeyguardOccludedChangedLw(boolean occluded) {
3831        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
3832            mPendingKeyguardOccluded = occluded;
3833            mKeyguardOccludedChanged = true;
3834        } else {
3835            setKeyguardOccludedLw(occluded);
3836        }
3837    }
3838
3839    private int handleStartTransitionForKeyguardLw(int transit, @Nullable Animation anim) {
3840        if (mKeyguardOccludedChanged) {
3841            if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded="
3842                    + mPendingKeyguardOccluded);
3843            mKeyguardOccludedChanged = false;
3844            if (setKeyguardOccludedLw(mPendingKeyguardOccluded)) {
3845                return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER;
3846            }
3847        }
3848        if (AppTransition.isKeyguardGoingAwayTransit(transit)) {
3849            if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation");
3850            final long startTime = anim != null
3851                    ? SystemClock.uptimeMillis() + anim.getStartOffset()
3852                    : SystemClock.uptimeMillis();
3853            final long duration = anim != null
3854                    ? anim.getDuration()
3855                    : 0;
3856            startKeyguardExitAnimation(startTime, duration);
3857        }
3858        return 0;
3859    }
3860
3861    private void launchAssistLongPressAction() {
3862        performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
3863        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
3864
3865        // launch the search activity
3866        Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
3867        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3868        try {
3869            // TODO: This only stops the factory-installed search manager.
3870            // Need to formalize an API to handle others
3871            SearchManager searchManager = getSearchManager();
3872            if (searchManager != null) {
3873                searchManager.stopSearch();
3874            }
3875            startActivityAsUser(intent, UserHandle.CURRENT);
3876        } catch (ActivityNotFoundException e) {
3877            Slog.w(TAG, "No activity to handle assist long press action.", e);
3878        }
3879    }
3880
3881    private void launchAssistAction(String hint, int deviceId) {
3882        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
3883        if (!isUserSetupComplete()) {
3884            // Disable opening assist window during setup
3885            return;
3886        }
3887        Bundle args = null;
3888        if (deviceId > Integer.MIN_VALUE) {
3889            args = new Bundle();
3890            args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
3891        }
3892        if ((mContext.getResources().getConfiguration().uiMode
3893                & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
3894            // On TV, use legacy handling until assistants are implemented in the proper way.
3895            ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
3896                    .launchLegacyAssist(hint, UserHandle.myUserId(), args);
3897        } else {
3898            if (hint != null) {
3899                if (args == null) {
3900                    args = new Bundle();
3901                }
3902                args.putBoolean(hint, true);
3903            }
3904            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3905            if (statusbar != null) {
3906                statusbar.startAssist(args);
3907            }
3908        }
3909    }
3910
3911    private void startActivityAsUser(Intent intent, UserHandle handle) {
3912        if (isUserSetupComplete()) {
3913            mContext.startActivityAsUser(intent, handle);
3914        } else {
3915            Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent);
3916        }
3917    }
3918
3919    private SearchManager getSearchManager() {
3920        if (mSearchManager == null) {
3921            mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
3922        }
3923        return mSearchManager;
3924    }
3925
3926    private void preloadRecentApps() {
3927        mPreloadedRecentApps = true;
3928        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3929        if (statusbar != null) {
3930            statusbar.preloadRecentApps();
3931        }
3932    }
3933
3934    private void cancelPreloadRecentApps() {
3935        if (mPreloadedRecentApps) {
3936            mPreloadedRecentApps = false;
3937            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3938            if (statusbar != null) {
3939                statusbar.cancelPreloadRecentApps();
3940            }
3941        }
3942    }
3943
3944    private void toggleRecentApps() {
3945        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3946        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3947        if (statusbar != null) {
3948            statusbar.toggleRecentApps();
3949        }
3950    }
3951
3952    @Override
3953    public void showRecentApps(boolean fromHome) {
3954        mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
3955        mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget();
3956    }
3957
3958    private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
3959        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3960        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3961        if (statusbar != null) {
3962            statusbar.showRecentApps(triggeredFromAltTab, fromHome);
3963        }
3964    }
3965
3966    private void toggleKeyboardShortcutsMenu(int deviceId) {
3967        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3968        if (statusbar != null) {
3969            statusbar.toggleKeyboardShortcutsMenu(deviceId);
3970        }
3971    }
3972
3973    private void dismissKeyboardShortcutsMenu() {
3974        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3975        if (statusbar != null) {
3976            statusbar.dismissKeyboardShortcutsMenu();
3977        }
3978    }
3979
3980    private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
3981        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3982        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3983        if (statusbar != null) {
3984            statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
3985        }
3986    }
3987
3988    void launchHomeFromHotKey() {
3989        launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/);
3990    }
3991
3992    /**
3993     * A home key -> launch home action was detected.  Take the appropriate action
3994     * given the situation with the keyguard.
3995     */
3996    void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) {
3997        if (respectKeyguard) {
3998            if (isKeyguardShowingAndNotOccluded()) {
3999                // don't launch home if keyguard showing
4000                return;
4001            }
4002
4003            if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) {
4004                // when in keyguard restricted mode, must first verify unlock
4005                // before launching home
4006                mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
4007                    @Override
4008                    public void onKeyguardExitResult(boolean success) {
4009                        if (success) {
4010                            try {
4011                                ActivityManager.getService().stopAppSwitches();
4012                            } catch (RemoteException e) {
4013                            }
4014                            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
4015                            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
4016                        }
4017                    }
4018                });
4019                return;
4020            }
4021        }
4022
4023        // no keyguard stuff to worry about, just launch home!
4024        try {
4025            ActivityManager.getService().stopAppSwitches();
4026        } catch (RemoteException e) {
4027        }
4028        if (mRecentsVisible) {
4029            // Hide Recents and notify it to launch Home
4030            if (awakenFromDreams) {
4031                awakenDreams();
4032            }
4033            hideRecentApps(false, true);
4034        } else {
4035            // Otherwise, just launch Home
4036            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
4037            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
4038        }
4039    }
4040
4041    private final Runnable mClearHideNavigationFlag = new Runnable() {
4042        @Override
4043        public void run() {
4044            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
4045                // Clear flags.
4046                mForceClearedSystemUiFlags &=
4047                        ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
4048            }
4049            mWindowManagerFuncs.reevaluateStatusBarVisibility();
4050        }
4051    };
4052
4053    /**
4054     * Input handler used while nav bar is hidden.  Captures any touch on the screen,
4055     * to determine when the nav bar should be shown and prevent applications from
4056     * receiving those touches.
4057     */
4058    final class HideNavInputEventReceiver extends InputEventReceiver {
4059        public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
4060            super(inputChannel, looper);
4061        }
4062
4063        @Override
4064        public void onInputEvent(InputEvent event) {
4065            boolean handled = false;
4066            try {
4067                if (event instanceof MotionEvent
4068                        && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
4069                    final MotionEvent motionEvent = (MotionEvent)event;
4070                    if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
4071                        // When the user taps down, we re-show the nav bar.
4072                        boolean changed = false;
4073                        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
4074                            if (mInputConsumer == null) {
4075                                return;
4076                            }
4077                            // Any user activity always causes us to show the
4078                            // navigation controls, if they had been hidden.
4079                            // We also clear the low profile and only content
4080                            // flags so that tapping on the screen will atomically
4081                            // restore all currently hidden screen decorations.
4082                            int newVal = mResettingSystemUiFlags |
4083                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
4084                                    View.SYSTEM_UI_FLAG_LOW_PROFILE |
4085                                    View.SYSTEM_UI_FLAG_FULLSCREEN;
4086                            if (mResettingSystemUiFlags != newVal) {
4087                                mResettingSystemUiFlags = newVal;
4088                                changed = true;
4089                            }
4090                            // We don't allow the system's nav bar to be hidden
4091                            // again for 1 second, to prevent applications from
4092                            // spamming us and keeping it from being shown.
4093                            newVal = mForceClearedSystemUiFlags |
4094                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
4095                            if (mForceClearedSystemUiFlags != newVal) {
4096                                mForceClearedSystemUiFlags = newVal;
4097                                changed = true;
4098                                mHandler.postDelayed(mClearHideNavigationFlag, 1000);
4099                            }
4100                        }
4101                        if (changed) {
4102                            mWindowManagerFuncs.reevaluateStatusBarVisibility();
4103                        }
4104                    }
4105                }
4106            } finally {
4107                finishInputEvent(event, handled);
4108            }
4109        }
4110    }
4111
4112    @Override
4113    public void setRecentsVisibilityLw(boolean visible) {
4114        mRecentsVisible = visible;
4115    }
4116
4117    @Override
4118    public void setPipVisibilityLw(boolean visible) {
4119        mPictureInPictureVisible = visible;
4120    }
4121
4122    @Override
4123    public int adjustSystemUiVisibilityLw(int visibility) {
4124        mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4125        mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4126
4127        // Reset any bits in mForceClearingStatusBarVisibility that
4128        // are now clear.
4129        mResettingSystemUiFlags &= visibility;
4130        // Clear any bits in the new visibility that are currently being
4131        // force cleared, before reporting it.
4132        return visibility & ~mResettingSystemUiFlags
4133                & ~mForceClearedSystemUiFlags;
4134    }
4135
4136    @Override
4137    public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
4138            int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets,
4139            Rect outStableInsets, Rect outOutsets) {
4140        final int fl = PolicyControl.getWindowFlags(null, attrs);
4141        final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
4142        final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
4143
4144        final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
4145        if (useOutsets) {
4146            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
4147            if (outset > 0) {
4148                if (displayRotation == Surface.ROTATION_0) {
4149                    outOutsets.bottom += outset;
4150                } else if (displayRotation == Surface.ROTATION_90) {
4151                    outOutsets.right += outset;
4152                } else if (displayRotation == Surface.ROTATION_180) {
4153                    outOutsets.top += outset;
4154                } else if (displayRotation == Surface.ROTATION_270) {
4155                    outOutsets.left += outset;
4156                }
4157            }
4158        }
4159
4160        if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4161                == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4162            int availRight, availBottom;
4163            if (canHideNavigationBar() &&
4164                    (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
4165                availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4166                availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4167            } else {
4168                availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
4169                availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4170            }
4171            if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4172                if ((fl & FLAG_FULLSCREEN) != 0) {
4173                    outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop,
4174                            availRight - mStableFullscreenRight,
4175                            availBottom - mStableFullscreenBottom);
4176                } else {
4177                    outContentInsets.set(mStableLeft, mStableTop,
4178                            availRight - mStableRight, availBottom - mStableBottom);
4179                }
4180            } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
4181                outContentInsets.setEmpty();
4182            } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
4183                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
4184                outContentInsets.set(mCurLeft, mCurTop,
4185                        availRight - mCurRight, availBottom - mCurBottom);
4186            } else {
4187                outContentInsets.set(mCurLeft, mCurTop,
4188                        availRight - mCurRight, availBottom - mCurBottom);
4189            }
4190
4191            outStableInsets.set(mStableLeft, mStableTop,
4192                    availRight - mStableRight, availBottom - mStableBottom);
4193            if (taskBounds != null) {
4194                calculateRelevantTaskInsets(taskBounds, outContentInsets,
4195                        displayWidth, displayHeight);
4196                calculateRelevantTaskInsets(taskBounds, outStableInsets,
4197                        displayWidth, displayHeight);
4198            }
4199            return mForceShowSystemBars;
4200        }
4201        outContentInsets.setEmpty();
4202        outStableInsets.setEmpty();
4203        return mForceShowSystemBars;
4204    }
4205
4206    /**
4207     * For any given task bounds, the insets relevant for these bounds given the insets relevant
4208     * for the entire display.
4209     */
4210    private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth,
4211            int displayHeight) {
4212        mTmpRect.set(0, 0, displayWidth, displayHeight);
4213        mTmpRect.inset(inOutInsets);
4214        mTmpRect.intersect(taskBounds);
4215        int leftInset = mTmpRect.left - taskBounds.left;
4216        int topInset = mTmpRect.top - taskBounds.top;
4217        int rightInset = taskBounds.right - mTmpRect.right;
4218        int bottomInset = taskBounds.bottom - mTmpRect.bottom;
4219        inOutInsets.set(leftInset, topInset, rightInset, bottomInset);
4220    }
4221
4222    private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
4223        return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
4224                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
4225    }
4226
4227    /** {@inheritDoc} */
4228    @Override
4229    public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
4230                              int displayRotation, int uiMode) {
4231        mDisplayRotation = displayRotation;
4232        final int overscanLeft, overscanTop, overscanRight, overscanBottom;
4233        if (isDefaultDisplay) {
4234            switch (displayRotation) {
4235                case Surface.ROTATION_90:
4236                    overscanLeft = mOverscanTop;
4237                    overscanTop = mOverscanRight;
4238                    overscanRight = mOverscanBottom;
4239                    overscanBottom = mOverscanLeft;
4240                    break;
4241                case Surface.ROTATION_180:
4242                    overscanLeft = mOverscanRight;
4243                    overscanTop = mOverscanBottom;
4244                    overscanRight = mOverscanLeft;
4245                    overscanBottom = mOverscanTop;
4246                    break;
4247                case Surface.ROTATION_270:
4248                    overscanLeft = mOverscanBottom;
4249                    overscanTop = mOverscanLeft;
4250                    overscanRight = mOverscanTop;
4251                    overscanBottom = mOverscanRight;
4252                    break;
4253                default:
4254                    overscanLeft = mOverscanLeft;
4255                    overscanTop = mOverscanTop;
4256                    overscanRight = mOverscanRight;
4257                    overscanBottom = mOverscanBottom;
4258                    break;
4259            }
4260        } else {
4261            overscanLeft = 0;
4262            overscanTop = 0;
4263            overscanRight = 0;
4264            overscanBottom = 0;
4265        }
4266        mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0;
4267        mOverscanScreenTop = mRestrictedOverscanScreenTop = 0;
4268        mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth;
4269        mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight;
4270        mSystemLeft = 0;
4271        mSystemTop = 0;
4272        mSystemRight = displayWidth;
4273        mSystemBottom = displayHeight;
4274        mUnrestrictedScreenLeft = overscanLeft;
4275        mUnrestrictedScreenTop = overscanTop;
4276        mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight;
4277        mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom;
4278        mRestrictedScreenLeft = mUnrestrictedScreenLeft;
4279        mRestrictedScreenTop = mUnrestrictedScreenTop;
4280        mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth;
4281        mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight;
4282        mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft
4283                = mCurLeft = mUnrestrictedScreenLeft;
4284        mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop
4285                = mCurTop = mUnrestrictedScreenTop;
4286        mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight
4287                = mCurRight = displayWidth - overscanRight;
4288        mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom
4289                = mCurBottom = displayHeight - overscanBottom;
4290        mDockLayer = 0x10000000;
4291        mStatusBarLayer = -1;
4292
4293        // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
4294        final Rect pf = mTmpParentFrame;
4295        final Rect df = mTmpDisplayFrame;
4296        final Rect of = mTmpOverscanFrame;
4297        final Rect vf = mTmpVisibleFrame;
4298        final Rect dcf = mTmpDecorFrame;
4299        pf.left = df.left = of.left = vf.left = mDockLeft;
4300        pf.top = df.top = of.top = vf.top = mDockTop;
4301        pf.right = df.right = of.right = vf.right = mDockRight;
4302        pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom;
4303        dcf.setEmpty();  // Decor frame N/A for system bars.
4304
4305        if (isDefaultDisplay) {
4306            // For purposes of putting out fake window up to steal focus, we will
4307            // drive nav being hidden only by whether it is requested.
4308            final int sysui = mLastSystemUiFlags;
4309            boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
4310            boolean navTranslucent = (sysui
4311                    & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
4312            boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
4313            boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
4314            boolean navAllowedHidden = immersive || immersiveSticky;
4315            navTranslucent &= !immersiveSticky;  // transient trumps translucent
4316            boolean isKeyguardShowing = isStatusBarKeyguard() && !mKeyguardOccluded;
4317            if (!isKeyguardShowing) {
4318                navTranslucent &= areTranslucentBarsAllowed();
4319            }
4320            boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null
4321                    && mStatusBar.getAttrs().height == MATCH_PARENT
4322                    && mStatusBar.getAttrs().width == MATCH_PARENT;
4323
4324            // When the navigation bar isn't visible, we put up a fake
4325            // input window to catch all touch events.  This way we can
4326            // detect when the user presses anywhere to bring back the nav
4327            // bar and ensure the application doesn't see the event.
4328            if (navVisible || navAllowedHidden) {
4329                if (mInputConsumer != null) {
4330                    mHandler.sendMessage(
4331                            mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
4332                    mInputConsumer = null;
4333                }
4334            } else if (mInputConsumer == null) {
4335                mInputConsumer = mWindowManagerFuncs.createInputConsumer(mHandler.getLooper(),
4336                        INPUT_CONSUMER_NAVIGATION,
4337                        (channel, looper) -> new HideNavInputEventReceiver(channel, looper));
4338                // As long as mInputConsumer is active, hover events are not dispatched to the app
4339                // and the pointer icon is likely to become stale. Hide it to avoid confusion.
4340                InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL);
4341            }
4342
4343            // For purposes of positioning and showing the nav bar, if we have
4344            // decided that it can't be hidden (because of the screen aspect ratio),
4345            // then take that into account.
4346            navVisible |= !canHideNavigationBar();
4347
4348            boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight,
4349                    displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom, dcf, navVisible, navTranslucent,
4350                    navAllowedHidden, statusBarExpandedNotKeyguard);
4351            if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
4352                    mDockLeft, mDockTop, mDockRight, mDockBottom));
4353            updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing);
4354            if (updateSysUiVisibility) {
4355                updateSystemUiVisibilityLw();
4356            }
4357        }
4358    }
4359
4360    private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui,
4361            boolean isKeyguardShowing) {
4362        // decide where the status bar goes ahead of time
4363        if (mStatusBar != null) {
4364            // apply any navigation bar insets
4365            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4366            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4367            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4368            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
4369                    + mUnrestrictedScreenTop;
4370            vf.left = mStableLeft;
4371            vf.top = mStableTop;
4372            vf.right = mStableRight;
4373            vf.bottom = mStableBottom;
4374
4375            mStatusBarLayer = mStatusBar.getSurfaceLayer();
4376
4377            // Let the status bar determine its size.
4378            mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
4379                    vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
4380                    dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */);
4381
4382            // For layout, the status bar is always at the top with our fixed height.
4383            mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
4384
4385            boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
4386            boolean statusBarTranslucent = (sysui
4387                    & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
4388            if (!isKeyguardShowing) {
4389                statusBarTranslucent &= areTranslucentBarsAllowed();
4390            }
4391
4392            // If the status bar is hidden, we don't want to cause
4393            // windows behind it to scroll.
4394            if (mStatusBar.isVisibleLw() && !statusBarTransient) {
4395                // Status bar may go away, so the screen area it occupies
4396                // is available to apps but just covering them when the
4397                // status bar is visible.
4398                mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
4399
4400                mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4401                mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4402                mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4403                mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4404
4405                if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " +
4406                        String.format(
4407                                "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
4408                                mDockLeft, mDockTop, mDockRight, mDockBottom,
4409                                mContentLeft, mContentTop, mContentRight, mContentBottom,
4410                                mCurLeft, mCurTop, mCurRight, mCurBottom));
4411            }
4412            if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
4413                    && !statusBarTransient && !statusBarTranslucent
4414                    && !mStatusBarController.wasRecentlyTranslucent()) {
4415                // If the opaque status bar is currently requested to be visible,
4416                // and not in the process of animating on or off, then
4417                // we can tell the app that it is covered by it.
4418                mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
4419            }
4420            if (mStatusBarController.checkHiddenLw()) {
4421                return true;
4422            }
4423        }
4424        return false;
4425    }
4426
4427    private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation,
4428            int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf,
4429            boolean navVisible, boolean navTranslucent, boolean navAllowedHidden,
4430            boolean statusBarExpandedNotKeyguard) {
4431        if (mNavigationBar != null) {
4432            boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
4433            // Force the navigation bar to its appropriate place and
4434            // size.  We need to do this directly, instead of relying on
4435            // it to bubble up from the nav bar, because this needs to
4436            // change atomically with screen rotations.
4437            mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight,
4438                    displayRotation);
4439            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
4440                // It's a system nav bar or a portrait screen; nav bar goes on bottom.
4441                int top = displayHeight - overscanBottom
4442                        - getNavigationBarHeight(displayRotation, uiMode);
4443                mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
4444                mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
4445                if (transientNavBarShowing) {
4446                    mNavigationBarController.setBarShowingLw(true);
4447                } else if (navVisible) {
4448                    mNavigationBarController.setBarShowingLw(true);
4449                    mDockBottom = mTmpNavigationFrame.top;
4450                    mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
4451                    mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
4452                } else {
4453                    // We currently want to hide the navigation UI - unless we expanded the status
4454                    // bar.
4455                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4456                }
4457                if (navVisible && !navTranslucent && !navAllowedHidden
4458                        && !mNavigationBar.isAnimatingLw()
4459                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4460                    // If the opaque nav bar is currently requested to be visible,
4461                    // and not in the process of animating on or off, then
4462                    // we can tell the app that it is covered by it.
4463                    mSystemBottom = mTmpNavigationFrame.top;
4464                }
4465            } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4466                // Landscape screen; nav bar goes to the right.
4467                int left = displayWidth - overscanRight
4468                        - getNavigationBarWidth(displayRotation, uiMode);
4469                mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
4470                mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
4471                if (transientNavBarShowing) {
4472                    mNavigationBarController.setBarShowingLw(true);
4473                } else if (navVisible) {
4474                    mNavigationBarController.setBarShowingLw(true);
4475                    mDockRight = mTmpNavigationFrame.left;
4476                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4477                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4478                } else {
4479                    // We currently want to hide the navigation UI - unless we expanded the status
4480                    // bar.
4481                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4482                }
4483                if (navVisible && !navTranslucent && !navAllowedHidden
4484                        && !mNavigationBar.isAnimatingLw()
4485                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4486                    // If the nav bar is currently requested to be visible,
4487                    // and not in the process of animating on or off, then
4488                    // we can tell the app that it is covered by it.
4489                    mSystemRight = mTmpNavigationFrame.left;
4490                }
4491            } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4492                // Seascape screen; nav bar goes to the left.
4493                int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode);
4494                mTmpNavigationFrame.set(overscanLeft, 0, right, displayHeight);
4495                mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right;
4496                if (transientNavBarShowing) {
4497                    mNavigationBarController.setBarShowingLw(true);
4498                } else if (navVisible) {
4499                    mNavigationBarController.setBarShowingLw(true);
4500                    mDockLeft = mTmpNavigationFrame.right;
4501                    // TODO: not so sure about those:
4502                    mRestrictedScreenLeft = mRestrictedOverscanScreenLeft = mDockLeft;
4503                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4504                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4505                } else {
4506                    // We currently want to hide the navigation UI - unless we expanded the status
4507                    // bar.
4508                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4509                }
4510                if (navVisible && !navTranslucent && !navAllowedHidden
4511                        && !mNavigationBar.isAnimatingLw()
4512                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4513                    // If the nav bar is currently requested to be visible,
4514                    // and not in the process of animating on or off, then
4515                    // we can tell the app that it is covered by it.
4516                    mSystemLeft = mTmpNavigationFrame.right;
4517                }
4518            }
4519            // Make sure the content and current rectangles are updated to
4520            // account for the restrictions from the navigation bar.
4521            mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4522            mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4523            mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4524            mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4525            mStatusBarLayer = mNavigationBar.getSurfaceLayer();
4526            // And compute the final frame.
4527            mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
4528                    mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
4529                    mTmpNavigationFrame, mTmpNavigationFrame);
4530            if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
4531            if (mNavigationBarController.checkHiddenLw()) {
4532                return true;
4533            }
4534        }
4535        return false;
4536    }
4537
4538    private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
4539        if (mNavigationBarCanMove && displayWidth > displayHeight) {
4540            if (displayRotation == Surface.ROTATION_270) {
4541                return NAV_BAR_LEFT;
4542            } else {
4543                return NAV_BAR_RIGHT;
4544            }
4545        }
4546        return NAV_BAR_BOTTOM;
4547    }
4548
4549    /** {@inheritDoc} */
4550    @Override
4551    public int getSystemDecorLayerLw() {
4552        if (mStatusBar != null && mStatusBar.isVisibleLw()) {
4553            return mStatusBar.getSurfaceLayer();
4554        }
4555
4556        if (mNavigationBar != null && mNavigationBar.isVisibleLw()) {
4557            return mNavigationBar.getSurfaceLayer();
4558        }
4559
4560        return 0;
4561    }
4562
4563    @Override
4564    public void getContentRectLw(Rect r) {
4565        r.set(mContentLeft, mContentTop, mContentRight, mContentBottom);
4566    }
4567
4568    void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
4569            boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
4570        if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
4571            // Here's a special case: if this attached window is a panel that is
4572            // above the dock window, and the window it is attached to is below
4573            // the dock window, then the frames we computed for the window it is
4574            // attached to can not be used because the dock is effectively part
4575            // of the underlying window and the attached window is floating on top
4576            // of the whole thing.  So, we ignore the attached window and explicitly
4577            // compute the frames that would be appropriate without the dock.
4578            df.left = of.left = cf.left = vf.left = mDockLeft;
4579            df.top = of.top = cf.top = vf.top = mDockTop;
4580            df.right = of.right = cf.right = vf.right = mDockRight;
4581            df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom;
4582        } else {
4583            // The effective display frame of the attached window depends on
4584            // whether it is taking care of insetting its content.  If not,
4585            // we need to use the parent's content frame so that the entire
4586            // window is positioned within that content.  Otherwise we can use
4587            // the overscan frame and let the attached window take care of
4588            // positioning its content appropriately.
4589            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4590                // Set the content frame of the attached window to the parent's decor frame
4591                // (same as content frame when IME isn't present) if specifically requested by
4592                // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
4593                // Otherwise, use the overscan frame.
4594                cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
4595                        ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
4596            } else {
4597                // If the window is resizing, then we want to base the content
4598                // frame on our attached content frame to resize...  however,
4599                // things can be tricky if the attached window is NOT in resize
4600                // mode, in which case its content frame will be larger.
4601                // Ungh.  So to deal with that, make sure the content frame
4602                // we end up using is not covering the IM dock.
4603                cf.set(attached.getContentFrameLw());
4604                if (attached.isVoiceInteraction()) {
4605                    if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft;
4606                    if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop;
4607                    if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight;
4608                    if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom;
4609                } else if (attached.getSurfaceLayer() < mDockLayer) {
4610                    if (cf.left < mContentLeft) cf.left = mContentLeft;
4611                    if (cf.top < mContentTop) cf.top = mContentTop;
4612                    if (cf.right > mContentRight) cf.right = mContentRight;
4613                    if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
4614                }
4615            }
4616            df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
4617            of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
4618            vf.set(attached.getVisibleFrameLw());
4619        }
4620        // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
4621        // window should be positioned relative to its parent or the entire
4622        // screen.
4623        pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
4624                ? attached.getFrameLw() : df);
4625    }
4626
4627    private void applyStableConstraints(int sysui, int fl, Rect r) {
4628        if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4629            // If app is requesting a stable layout, don't let the
4630            // content insets go below the stable values.
4631            if ((fl & FLAG_FULLSCREEN) != 0) {
4632                if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft;
4633                if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop;
4634                if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight;
4635                if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom;
4636            } else {
4637                if (r.left < mStableLeft) r.left = mStableLeft;
4638                if (r.top < mStableTop) r.top = mStableTop;
4639                if (r.right > mStableRight) r.right = mStableRight;
4640                if (r.bottom > mStableBottom) r.bottom = mStableBottom;
4641            }
4642        }
4643    }
4644
4645    private boolean canReceiveInput(WindowState win) {
4646        boolean notFocusable =
4647                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
4648        boolean altFocusableIm =
4649                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
4650        boolean notFocusableForIm = notFocusable ^ altFocusableIm;
4651        return !notFocusableForIm;
4652    }
4653
4654    /** {@inheritDoc} */
4655    @Override
4656    public void layoutWindowLw(WindowState win, WindowState attached) {
4657        // We've already done the navigation bar and status bar. If the status bar can receive
4658        // input, we need to layout it again to accomodate for the IME window.
4659        if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) {
4660            return;
4661        }
4662        final WindowManager.LayoutParams attrs = win.getAttrs();
4663        final boolean isDefaultDisplay = win.isDefaultDisplay();
4664        final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
4665                (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
4666        if (needsToOffsetInputMethodTarget) {
4667            if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
4668            offsetInputMethodWindowLw(mLastInputMethodWindow);
4669        }
4670
4671        final int fl = PolicyControl.getWindowFlags(win, attrs);
4672        final int pfl = attrs.privateFlags;
4673        final int sim = attrs.softInputMode;
4674        final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
4675
4676        final Rect pf = mTmpParentFrame;
4677        final Rect df = mTmpDisplayFrame;
4678        final Rect of = mTmpOverscanFrame;
4679        final Rect cf = mTmpContentFrame;
4680        final Rect vf = mTmpVisibleFrame;
4681        final Rect dcf = mTmpDecorFrame;
4682        final Rect sf = mTmpStableFrame;
4683        Rect osf = null;
4684        dcf.setEmpty();
4685
4686        final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
4687                && mNavigationBar != null && mNavigationBar.isVisibleLw());
4688
4689        final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
4690
4691        if (isDefaultDisplay) {
4692            sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom);
4693        } else {
4694            sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom);
4695        }
4696
4697        if (!isDefaultDisplay) {
4698            if (attached != null) {
4699                // If this window is attached to another, our display
4700                // frame is the same as the one we are attached to.
4701                setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4702            } else {
4703                // Give the window full screen.
4704                pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4705                pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4706                pf.right = df.right = of.right = cf.right
4707                        = mOverscanScreenLeft + mOverscanScreenWidth;
4708                pf.bottom = df.bottom = of.bottom = cf.bottom
4709                        = mOverscanScreenTop + mOverscanScreenHeight;
4710            }
4711        } else if (attrs.type == TYPE_INPUT_METHOD) {
4712            pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
4713            pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
4714            pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
4715            // IM dock windows layout below the nav bar...
4716            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4717            // ...with content insets above the nav bar
4718            cf.bottom = vf.bottom = mStableBottom;
4719            if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
4720                // The status bar forces the navigation bar while it's visible. Make sure the IME
4721                // avoids the navigation bar in that case.
4722                if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4723                    pf.right = df.right = of.right = cf.right = vf.right = mStableRight;
4724                } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4725                    pf.left = df.left = of.left = cf.left = vf.left = mStableLeft;
4726                }
4727            }
4728            // IM dock windows always go to the bottom of the screen.
4729            attrs.gravity = Gravity.BOTTOM;
4730            mDockLayer = win.getSurfaceLayer();
4731        } else if (attrs.type == TYPE_VOICE_INTERACTION) {
4732            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4733            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4734            pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4735            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4736            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4737                cf.left = mDockLeft;
4738                cf.top = mDockTop;
4739                cf.right = mDockRight;
4740                cf.bottom = mDockBottom;
4741            } else {
4742                cf.left = mContentLeft;
4743                cf.top = mContentTop;
4744                cf.right = mContentRight;
4745                cf.bottom = mContentBottom;
4746            }
4747            if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4748                vf.left = mCurLeft;
4749                vf.top = mCurTop;
4750                vf.right = mCurRight;
4751                vf.bottom = mCurBottom;
4752            } else {
4753                vf.set(cf);
4754            }
4755        } else if (attrs.type == TYPE_WALLPAPER) {
4756           layoutWallpaper(win, pf, df, of, cf);
4757        } else if (win == mStatusBar) {
4758            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4759            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4760            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4761            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop;
4762            cf.left = vf.left = mStableLeft;
4763            cf.top = vf.top = mStableTop;
4764            cf.right = vf.right = mStableRight;
4765            vf.bottom = mStableBottom;
4766
4767            if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
4768                cf.bottom = mContentBottom;
4769            } else {
4770                cf.bottom = mDockBottom;
4771                vf.bottom = mContentBottom;
4772            }
4773        } else {
4774
4775            // Default policy decor for the default display
4776            dcf.left = mSystemLeft;
4777            dcf.top = mSystemTop;
4778            dcf.right = mSystemRight;
4779            dcf.bottom = mSystemBottom;
4780            final boolean inheritTranslucentDecor = (attrs.privateFlags
4781                    & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0;
4782            final boolean isAppWindow =
4783                    attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW &&
4784                    attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
4785            final boolean topAtRest =
4786                    win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
4787            if (isAppWindow && !inheritTranslucentDecor && !topAtRest) {
4788                if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
4789                        && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0
4790                        && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
4791                        && (fl & WindowManager.LayoutParams.
4792                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
4793                        && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) {
4794                    // Ensure policy decor includes status bar
4795                    dcf.top = mStableTop;
4796                }
4797                if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0
4798                        && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
4799                        && (fl & WindowManager.LayoutParams.
4800                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
4801                    // Ensure policy decor includes navigation bar
4802                    dcf.bottom = mStableBottom;
4803                    dcf.right = mStableRight;
4804                }
4805            }
4806
4807            if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4808                    == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4809                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
4810                            + "): IN_SCREEN, INSET_DECOR");
4811                // This is the case for a normal activity window: we want it
4812                // to cover all of the screen space, and it can take care of
4813                // moving its contents to account for screen decorations that
4814                // intrude into that space.
4815                if (attached != null) {
4816                    // If this window is attached to another, our display
4817                    // frame is the same as the one we are attached to.
4818                    setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4819                } else {
4820                    if (attrs.type == TYPE_STATUS_BAR_PANEL
4821                            || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
4822                        // Status bar panels are the only windows who can go on top of
4823                        // the status bar.  They are protected by the STATUS_BAR_SERVICE
4824                        // permission, so they have the same privileges as the status
4825                        // bar itself.
4826                        //
4827                        // However, they should still dodge the navigation bar if it exists.
4828
4829                        pf.left = df.left = of.left = hasNavBar
4830                                ? mDockLeft : mUnrestrictedScreenLeft;
4831                        pf.top = df.top = of.top = mUnrestrictedScreenTop;
4832                        pf.right = df.right = of.right = hasNavBar
4833                                ? mRestrictedScreenLeft+mRestrictedScreenWidth
4834                                : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4835                        pf.bottom = df.bottom = of.bottom = hasNavBar
4836                                ? mRestrictedScreenTop+mRestrictedScreenHeight
4837                                : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4838
4839                        if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4840                                        "Laying out status bar window: (%d,%d - %d,%d)",
4841                                        pf.left, pf.top, pf.right, pf.bottom));
4842                    } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4843                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4844                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4845                        // Asking to layout into the overscan region, so give it that pure
4846                        // unrestricted area.
4847                        pf.left = df.left = of.left = mOverscanScreenLeft;
4848                        pf.top = df.top = of.top = mOverscanScreenTop;
4849                        pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth;
4850                        pf.bottom = df.bottom = of.bottom = mOverscanScreenTop
4851                                + mOverscanScreenHeight;
4852                    } else if (canHideNavigationBar()
4853                            && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4854                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4855                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4856                        // Asking for layout as if the nav bar is hidden, lets the
4857                        // application extend into the unrestricted overscan screen area.  We
4858                        // only do this for application windows to ensure no window that
4859                        // can be above the nav bar can do this.
4860                        pf.left = df.left = mOverscanScreenLeft;
4861                        pf.top = df.top = mOverscanScreenTop;
4862                        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
4863                        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
4864                        // We need to tell the app about where the frame inside the overscan
4865                        // is, so it can inset its content by that amount -- it didn't ask
4866                        // to actually extend itself into the overscan region.
4867                        of.left = mUnrestrictedScreenLeft;
4868                        of.top = mUnrestrictedScreenTop;
4869                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4870                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4871                    } else {
4872                        pf.left = df.left = mRestrictedOverscanScreenLeft;
4873                        pf.top = df.top = mRestrictedOverscanScreenTop;
4874                        pf.right = df.right = mRestrictedOverscanScreenLeft
4875                                + mRestrictedOverscanScreenWidth;
4876                        pf.bottom = df.bottom = mRestrictedOverscanScreenTop
4877                                + mRestrictedOverscanScreenHeight;
4878                        // We need to tell the app about where the frame inside the overscan
4879                        // is, so it can inset its content by that amount -- it didn't ask
4880                        // to actually extend itself into the overscan region.
4881                        of.left = mUnrestrictedScreenLeft;
4882                        of.top = mUnrestrictedScreenTop;
4883                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4884                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4885                    }
4886
4887                    if ((fl & FLAG_FULLSCREEN) == 0) {
4888                        if (win.isVoiceInteraction()) {
4889                            cf.left = mVoiceContentLeft;
4890                            cf.top = mVoiceContentTop;
4891                            cf.right = mVoiceContentRight;
4892                            cf.bottom = mVoiceContentBottom;
4893                        } else {
4894                            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4895                                cf.left = mDockLeft;
4896                                cf.top = mDockTop;
4897                                cf.right = mDockRight;
4898                                cf.bottom = mDockBottom;
4899                            } else {
4900                                cf.left = mContentLeft;
4901                                cf.top = mContentTop;
4902                                cf.right = mContentRight;
4903                                cf.bottom = mContentBottom;
4904                            }
4905                        }
4906                    } else {
4907                        // Full screen windows are always given a layout that is as if the
4908                        // status bar and other transient decors are gone.  This is to avoid
4909                        // bad states when moving from a window that is not hding the
4910                        // status bar to one that is.
4911                        cf.left = mRestrictedScreenLeft;
4912                        cf.top = mRestrictedScreenTop;
4913                        cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
4914                        cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4915                    }
4916                    applyStableConstraints(sysUiFl, fl, cf);
4917                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4918                        vf.left = mCurLeft;
4919                        vf.top = mCurTop;
4920                        vf.right = mCurRight;
4921                        vf.bottom = mCurBottom;
4922                    } else {
4923                        vf.set(cf);
4924                    }
4925                }
4926            } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
4927                    & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
4928                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
4929                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4930                        "): IN_SCREEN");
4931                // A window that has requested to fill the entire screen just
4932                // gets everything, period.
4933                if (attrs.type == TYPE_STATUS_BAR_PANEL
4934                        || attrs.type == TYPE_STATUS_BAR_SUB_PANEL
4935                        || attrs.type == TYPE_VOLUME_OVERLAY) {
4936                    pf.left = df.left = of.left = cf.left = hasNavBar
4937                            ? mDockLeft : mUnrestrictedScreenLeft;
4938                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
4939                    pf.right = df.right = of.right = cf.right = hasNavBar
4940                                        ? mRestrictedScreenLeft+mRestrictedScreenWidth
4941                                        : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4942                    pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar
4943                                          ? mRestrictedScreenTop+mRestrictedScreenHeight
4944                                          : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4945                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4946                                    "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
4947                                    pf.left, pf.top, pf.right, pf.bottom));
4948                } else if (attrs.type == TYPE_NAVIGATION_BAR
4949                        || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
4950                    // The navigation bar has Real Ultimate Power.
4951                    pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4952                    pf.top = df.top = of.top = mUnrestrictedScreenTop;
4953                    pf.right = df.right = of.right = mUnrestrictedScreenLeft
4954                            + mUnrestrictedScreenWidth;
4955                    pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop
4956                            + mUnrestrictedScreenHeight;
4957                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4958                                    "Laying out navigation bar window: (%d,%d - %d,%d)",
4959                                    pf.left, pf.top, pf.right, pf.bottom));
4960                } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
4961                                || attrs.type == TYPE_BOOT_PROGRESS
4962                                || attrs.type == TYPE_SCREENSHOT)
4963                        && ((fl & FLAG_FULLSCREEN) != 0)) {
4964                    // Fullscreen secure system overlays get what they ask for. Screenshot region
4965                    // selection overlay should also expand to full screen.
4966                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4967                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4968                    pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
4969                            + mOverscanScreenWidth;
4970                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
4971                            + mOverscanScreenHeight;
4972                } else if (attrs.type == TYPE_BOOT_PROGRESS) {
4973                    // Boot progress screen always covers entire display.
4974                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4975                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4976                    pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
4977                            + mOverscanScreenWidth;
4978                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
4979                            + mOverscanScreenHeight;
4980                } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4981                        && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4982                        && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4983                    // Asking to layout into the overscan region, so give it that pure
4984                    // unrestricted area.
4985                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4986                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4987                    pf.right = df.right = of.right = cf.right
4988                            = mOverscanScreenLeft + mOverscanScreenWidth;
4989                    pf.bottom = df.bottom = of.bottom = cf.bottom
4990                            = mOverscanScreenTop + mOverscanScreenHeight;
4991                } else if (canHideNavigationBar()
4992                        && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4993                        && (attrs.type == TYPE_STATUS_BAR
4994                            || attrs.type == TYPE_TOAST
4995                            || attrs.type == TYPE_DOCK_DIVIDER
4996                            || attrs.type == TYPE_VOICE_INTERACTION_STARTING
4997                            || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4998                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
4999                    // Asking for layout as if the nav bar is hidden, lets the
5000                    // application extend into the unrestricted screen area.  We
5001                    // only do this for application windows (or toasts) to ensure no window that
5002                    // can be above the nav bar can do this.
5003                    // XXX This assumes that an app asking for this will also
5004                    // ask for layout in only content.  We can't currently figure out
5005                    // what the screen would be if only laying out to hide the nav bar.
5006                    pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
5007                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
5008                    pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft
5009                            + mUnrestrictedScreenWidth;
5010                    pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
5011                            + mUnrestrictedScreenHeight;
5012                } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
5013                    pf.left = df.left = of.left = mRestrictedScreenLeft;
5014                    pf.top = df.top = of.top  = mRestrictedScreenTop;
5015                    pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
5016                    pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop
5017                            + mRestrictedScreenHeight;
5018                    if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5019                        cf.left = mDockLeft;
5020                        cf.top = mDockTop;
5021                        cf.right = mDockRight;
5022                        cf.bottom = mDockBottom;
5023                    } else {
5024                        cf.left = mContentLeft;
5025                        cf.top = mContentTop;
5026                        cf.right = mContentRight;
5027                        cf.bottom = mContentBottom;
5028                    }
5029                } else {
5030                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
5031                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
5032                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
5033                            + mRestrictedScreenWidth;
5034                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
5035                            + mRestrictedScreenHeight;
5036                }
5037
5038                applyStableConstraints(sysUiFl, fl, cf);
5039
5040                if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5041                    vf.left = mCurLeft;
5042                    vf.top = mCurTop;
5043                    vf.right = mCurRight;
5044                    vf.bottom = mCurBottom;
5045                } else {
5046                    vf.set(cf);
5047                }
5048            } else if (attached != null) {
5049                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5050                        "): attached to " + attached);
5051                // A child window should be placed inside of the same visible
5052                // frame that its parent had.
5053                setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf);
5054            } else {
5055                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5056                        "): normal window");
5057                // Otherwise, a normal window must be placed inside the content
5058                // of all screen decorations.
5059                if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) {
5060                    // Status bar panels and the volume dialog are the only windows who can go on
5061                    // top of the status bar.  They are protected by the STATUS_BAR_SERVICE
5062                    // permission, so they have the same privileges as the status
5063                    // bar itself.
5064                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
5065                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
5066                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
5067                            + mRestrictedScreenWidth;
5068                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
5069                            + mRestrictedScreenHeight;
5070                } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) {
5071                    // These dialogs are stable to interim decor changes.
5072                    pf.left = df.left = of.left = cf.left = mStableLeft;
5073                    pf.top = df.top = of.top = cf.top = mStableTop;
5074                    pf.right = df.right = of.right = cf.right = mStableRight;
5075                    pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom;
5076                } else {
5077                    pf.left = mContentLeft;
5078                    pf.top = mContentTop;
5079                    pf.right = mContentRight;
5080                    pf.bottom = mContentBottom;
5081                    if (win.isVoiceInteraction()) {
5082                        df.left = of.left = cf.left = mVoiceContentLeft;
5083                        df.top = of.top = cf.top = mVoiceContentTop;
5084                        df.right = of.right = cf.right = mVoiceContentRight;
5085                        df.bottom = of.bottom = cf.bottom = mVoiceContentBottom;
5086                    } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5087                        df.left = of.left = cf.left = mDockLeft;
5088                        df.top = of.top = cf.top = mDockTop;
5089                        df.right = of.right = cf.right = mDockRight;
5090                        df.bottom = of.bottom = cf.bottom = mDockBottom;
5091                    } else {
5092                        df.left = of.left = cf.left = mContentLeft;
5093                        df.top = of.top = cf.top = mContentTop;
5094                        df.right = of.right = cf.right = mContentRight;
5095                        df.bottom = of.bottom = cf.bottom = mContentBottom;
5096                    }
5097                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5098                        vf.left = mCurLeft;
5099                        vf.top = mCurTop;
5100                        vf.right = mCurRight;
5101                        vf.bottom = mCurBottom;
5102                    } else {
5103                        vf.set(cf);
5104                    }
5105                }
5106            }
5107        }
5108
5109        // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
5110        // Also, we don't allow windows in multi-window mode to extend out of the screen.
5111        if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR
5112                && !win.isInMultiWindowMode()) {
5113            df.left = df.top = -10000;
5114            df.right = df.bottom = 10000;
5115            if (attrs.type != TYPE_WALLPAPER) {
5116                of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
5117                of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
5118            }
5119        }
5120
5121        // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we
5122        // need to provide information to the clients that want to pretend that you can draw there.
5123        // We only want to apply outsets to certain types of windows. For example, we never want to
5124        // apply the outsets to floating dialogs, because they wouldn't make sense there.
5125        final boolean useOutsets = shouldUseOutsets(attrs, fl);
5126        if (isDefaultDisplay && useOutsets) {
5127            osf = mTmpOutsetFrame;
5128            osf.set(cf.left, cf.top, cf.right, cf.bottom);
5129            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
5130            if (outset > 0) {
5131                int rotation = mDisplayRotation;
5132                if (rotation == Surface.ROTATION_0) {
5133                    osf.bottom += outset;
5134                } else if (rotation == Surface.ROTATION_90) {
5135                    osf.right += outset;
5136                } else if (rotation == Surface.ROTATION_180) {
5137                    osf.top -= outset;
5138                } else if (rotation == Surface.ROTATION_270) {
5139                    osf.left -= outset;
5140                }
5141                if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset
5142                        + " with rotation " + rotation + ", result: " + osf);
5143            }
5144        }
5145
5146        if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
5147                + ": sim=#" + Integer.toHexString(sim)
5148                + " attach=" + attached + " type=" + attrs.type
5149                + String.format(" flags=0x%08x", fl)
5150                + " pf=" + pf.toShortString() + " df=" + df.toShortString()
5151                + " of=" + of.toShortString()
5152                + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
5153                + " dcf=" + dcf.toShortString()
5154                + " sf=" + sf.toShortString()
5155                + " osf=" + (osf == null ? "null" : osf.toShortString()));
5156
5157        win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf);
5158
5159        // Dock windows carve out the bottom of the screen, so normal windows
5160        // can't appear underneath them.
5161        if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleLw()
5162                && !win.getGivenInsetsPendingLw()) {
5163            setLastInputMethodWindowLw(null, null);
5164            offsetInputMethodWindowLw(win);
5165        }
5166        if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleLw()
5167                && !win.getGivenInsetsPendingLw()) {
5168            offsetVoiceInputWindowLw(win);
5169        }
5170    }
5171
5172    private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) {
5173
5174        // The wallpaper also has Real Ultimate Power, but we want to tell
5175        // it about the overscan area.
5176        pf.left = df.left = mOverscanScreenLeft;
5177        pf.top = df.top = mOverscanScreenTop;
5178        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
5179        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
5180        of.left = cf.left = mUnrestrictedScreenLeft;
5181        of.top = cf.top = mUnrestrictedScreenTop;
5182        of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5183        of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5184    }
5185
5186    private void offsetInputMethodWindowLw(WindowState win) {
5187        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5188        top += win.getGivenContentInsetsLw().top;
5189        if (mContentBottom > top) {
5190            mContentBottom = top;
5191        }
5192        if (mVoiceContentBottom > top) {
5193            mVoiceContentBottom = top;
5194        }
5195        top = win.getVisibleFrameLw().top;
5196        top += win.getGivenVisibleInsetsLw().top;
5197        if (mCurBottom > top) {
5198            mCurBottom = top;
5199        }
5200        if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
5201                + mDockBottom + " mContentBottom="
5202                + mContentBottom + " mCurBottom=" + mCurBottom);
5203    }
5204
5205    private void offsetVoiceInputWindowLw(WindowState win) {
5206        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5207        top += win.getGivenContentInsetsLw().top;
5208        if (mVoiceContentBottom > top) {
5209            mVoiceContentBottom = top;
5210        }
5211    }
5212
5213    /** {@inheritDoc} */
5214    @Override
5215    public void finishLayoutLw() {
5216        return;
5217    }
5218
5219    /** {@inheritDoc} */
5220    @Override
5221    public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
5222        mTopFullscreenOpaqueWindowState = null;
5223        mTopFullscreenOpaqueOrDimmingWindowState = null;
5224        mTopDockedOpaqueWindowState = null;
5225        mTopDockedOpaqueOrDimmingWindowState = null;
5226        mForceStatusBar = false;
5227        mForceStatusBarFromKeyguard = false;
5228        mForceStatusBarTransparent = false;
5229        mForcingShowNavBar = false;
5230        mForcingShowNavBarLayer = -1;
5231
5232        mAllowLockscreenWhenOn = false;
5233        mShowingDream = false;
5234    }
5235
5236    /** {@inheritDoc} */
5237    @Override
5238    public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
5239            WindowState attached, WindowState imeTarget) {
5240        final boolean visible = !win.isGoneForLayoutLw();
5241        if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisible=" + visible);
5242        applyKeyguardPolicyLw(win, imeTarget);
5243        final int fl = PolicyControl.getWindowFlags(win, attrs);
5244        if (mTopFullscreenOpaqueWindowState == null && visible && attrs.type == TYPE_INPUT_METHOD) {
5245            mForcingShowNavBar = true;
5246            mForcingShowNavBarLayer = win.getSurfaceLayer();
5247        }
5248        if (attrs.type == TYPE_STATUS_BAR) {
5249            if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
5250                mForceStatusBarFromKeyguard = true;
5251            }
5252            if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
5253                mForceStatusBarTransparent = true;
5254            }
5255        }
5256
5257        // Don't allow snapshots to influence SystemUI visibility flags.
5258        // TODO: Revisit this once SystemUI flags for snapshots are handled correctly
5259        boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
5260                && attrs.type < FIRST_SYSTEM_WINDOW
5261                && (attrs.privateFlags & PRIVATE_FLAG_TASK_SNAPSHOT) == 0;
5262        final int stackId = win.getStackId();
5263        if (mTopFullscreenOpaqueWindowState == null && visible) {
5264            if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
5265                mForceStatusBar = true;
5266            }
5267            if (attrs.type == TYPE_DREAM) {
5268                // If the lockscreen was showing when the dream started then wait
5269                // for the dream to draw before hiding the lockscreen.
5270                if (!mDreamingLockscreen
5271                        || (win.isVisibleLw() && win.hasDrawnLw())) {
5272                    mShowingDream = true;
5273                    appWindow = true;
5274                }
5275            }
5276
5277            // For app windows that are not attached, we decide if all windows in the app they
5278            // represent should be hidden or if we should hide the lockscreen. For attached app
5279            // windows we defer the decision to the window it is attached to.
5280            if (appWindow && attached == null) {
5281                if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
5282                    if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
5283                    mTopFullscreenOpaqueWindowState = win;
5284                    if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5285                        mTopFullscreenOpaqueOrDimmingWindowState = win;
5286                    }
5287                    if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
5288                        mAllowLockscreenWhenOn = true;
5289                    }
5290                }
5291            }
5292        }
5293
5294        // Voice interaction overrides both top fullscreen and top docked.
5295        if (visible && win.getAttrs().type == TYPE_VOICE_INTERACTION) {
5296            if (mTopFullscreenOpaqueWindowState == null) {
5297                mTopFullscreenOpaqueWindowState = win;
5298                if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5299                    mTopFullscreenOpaqueOrDimmingWindowState = win;
5300                }
5301            }
5302            if (mTopDockedOpaqueWindowState == null) {
5303                mTopDockedOpaqueWindowState = win;
5304                if (mTopDockedOpaqueOrDimmingWindowState == null) {
5305                    mTopDockedOpaqueOrDimmingWindowState = win;
5306                }
5307            }
5308        }
5309
5310        // Keep track of the window if it's dimming but not necessarily fullscreen.
5311        if (mTopFullscreenOpaqueOrDimmingWindowState == null && visible
5312                && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
5313            mTopFullscreenOpaqueOrDimmingWindowState = win;
5314        }
5315
5316        // We need to keep track of the top "fullscreen" opaque window for the docked stack
5317        // separately, because both the "real fullscreen" opaque window and the one for the docked
5318        // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
5319        if (mTopDockedOpaqueWindowState == null && visible && appWindow && attached == null
5320                && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
5321            mTopDockedOpaqueWindowState = win;
5322            if (mTopDockedOpaqueOrDimmingWindowState == null) {
5323                mTopDockedOpaqueOrDimmingWindowState = win;
5324            }
5325        }
5326
5327        // Also keep track of any windows that are dimming but not necessarily fullscreen in the
5328        // docked stack.
5329        if (mTopDockedOpaqueOrDimmingWindowState == null && visible && win.isDimming()
5330                && stackId == DOCKED_STACK_ID) {
5331            mTopDockedOpaqueOrDimmingWindowState = win;
5332        }
5333    }
5334
5335    private void applyKeyguardPolicyLw(WindowState win, WindowState imeTarget) {
5336        if (canBeHiddenByKeyguardLw(win)) {
5337            if (shouldBeHiddenByKeyguard(win, imeTarget)) {
5338                win.hideLw(false /* doAnimation */);
5339            } else {
5340                win.showLw(false /* doAnimation */);
5341            }
5342        }
5343    }
5344
5345    private boolean isFullscreen(WindowManager.LayoutParams attrs) {
5346        return attrs.x == 0 && attrs.y == 0
5347                && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
5348                && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
5349    }
5350
5351    /** {@inheritDoc} */
5352    @Override
5353    public int finishPostLayoutPolicyLw() {
5354        int changes = 0;
5355        boolean topIsFullscreen = false;
5356
5357        final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
5358                ? mTopFullscreenOpaqueWindowState.getAttrs()
5359                : null;
5360
5361        // If we are not currently showing a dream then remember the current
5362        // lockscreen state.  We will use this to determine whether the dream
5363        // started while the lockscreen was showing and remember this state
5364        // while the dream is showing.
5365        if (!mShowingDream) {
5366            mDreamingLockscreen = isKeyguardShowingAndNotOccluded();
5367            if (mDreamingSleepTokenNeeded) {
5368                mDreamingSleepTokenNeeded = false;
5369                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
5370            }
5371        } else {
5372            if (!mDreamingSleepTokenNeeded) {
5373                mDreamingSleepTokenNeeded = true;
5374                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget();
5375            }
5376        }
5377
5378        if (mStatusBar != null) {
5379            if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
5380                    + " forcefkg=" + mForceStatusBarFromKeyguard
5381                    + " top=" + mTopFullscreenOpaqueWindowState);
5382            boolean shouldBeTransparent = mForceStatusBarTransparent
5383                    && !mForceStatusBar
5384                    && !mForceStatusBarFromKeyguard;
5385            if (!shouldBeTransparent) {
5386                mStatusBarController.setShowTransparent(false /* transparent */);
5387            } else if (!mStatusBar.isVisibleLw()) {
5388                mStatusBarController.setShowTransparent(true /* transparent */);
5389            }
5390
5391            WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs();
5392            boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT
5393                    && statusBarAttrs.width == MATCH_PARENT;
5394            if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
5395                    || statusBarExpanded) {
5396                if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
5397                if (mStatusBarController.setBarShowingLw(true)) {
5398                    changes |= FINISH_LAYOUT_REDO_LAYOUT;
5399                }
5400                // Maintain fullscreen layout until incoming animation is complete.
5401                topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
5402                // Transient status bar on the lockscreen is not allowed
5403                if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) {
5404                    mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
5405                            mLastSystemUiFlags, mLastSystemUiFlags);
5406                }
5407                if (statusBarExpanded && mNavigationBar != null) {
5408                    if (mNavigationBarController.setBarShowingLw(true)) {
5409                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5410                    }
5411                }
5412            } else if (mTopFullscreenOpaqueWindowState != null) {
5413                final int fl = PolicyControl.getWindowFlags(null, lp);
5414                if (localLOGV) {
5415                    Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
5416                            + " shown position: "
5417                            + mTopFullscreenOpaqueWindowState.getShownPositionLw());
5418                    Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
5419                            + " lp.flags=0x" + Integer.toHexString(fl));
5420                }
5421                topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
5422                        || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
5423                // The subtle difference between the window for mTopFullscreenOpaqueWindowState
5424                // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
5425                // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
5426                // case though.
5427                if (mStatusBarController.isTransientShowing()) {
5428                    if (mStatusBarController.setBarShowingLw(true)) {
5429                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5430                    }
5431                } else if (topIsFullscreen
5432                        && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)
5433                        && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) {
5434                    if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
5435                    if (mStatusBarController.setBarShowingLw(false)) {
5436                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5437                    } else {
5438                        if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
5439                    }
5440                } else {
5441                    if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
5442                    if (mStatusBarController.setBarShowingLw(true)) {
5443                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5444                    }
5445                }
5446            }
5447        }
5448
5449        if (mTopIsFullscreen != topIsFullscreen) {
5450            if (!topIsFullscreen) {
5451                // Force another layout when status bar becomes fully shown.
5452                changes |= FINISH_LAYOUT_REDO_LAYOUT;
5453            }
5454            mTopIsFullscreen = topIsFullscreen;
5455        }
5456
5457        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5458            // If the navigation bar has been hidden or shown, we need to do another
5459            // layout pass to update that window.
5460            changes |= FINISH_LAYOUT_REDO_LAYOUT;
5461        }
5462
5463        if (mShowingDream != mLastShowingDream) {
5464            mLastShowingDream = mShowingDream;
5465            mWindowManagerFuncs.notifyShowingDreamChanged();
5466        }
5467
5468        // update since mAllowLockscreenWhenOn might have changed
5469        updateLockScreenTimeout();
5470        return changes;
5471    }
5472
5473    /**
5474     * Updates the occluded state of the Keyguard.
5475     *
5476     * @return Whether the flags have changed and we have to redo the layout.
5477     */
5478    private boolean setKeyguardOccludedLw(boolean isOccluded) {
5479        if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded);
5480        boolean wasOccluded = mKeyguardOccluded;
5481        boolean showing = mKeyguardDelegate.isShowing();
5482        if (wasOccluded && !isOccluded && showing) {
5483            mKeyguardOccluded = false;
5484            mKeyguardDelegate.setOccluded(false, true /* animate */);
5485            mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
5486            if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
5487                mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5488            }
5489            return true;
5490        } else if (!wasOccluded && isOccluded && showing) {
5491            mKeyguardOccluded = true;
5492            mKeyguardDelegate.setOccluded(true, false /* animate */);
5493            mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
5494            mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
5495            return true;
5496        } else if (wasOccluded != isOccluded) {
5497            mKeyguardOccluded = isOccluded;
5498            mKeyguardDelegate.setOccluded(isOccluded, false /* animate */);
5499            return false;
5500        } else {
5501            return false;
5502        }
5503    }
5504
5505    private boolean isStatusBarKeyguard() {
5506        return mStatusBar != null
5507                && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
5508    }
5509
5510    @Override
5511    public boolean allowAppAnimationsLw() {
5512        if (mShowingDream) {
5513            // If keyguard or dreams is currently visible, no reason to animate behind it.
5514            return false;
5515        }
5516        return true;
5517    }
5518
5519    @Override
5520    public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
5521        mFocusedWindow = newFocus;
5522        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5523            // If the navigation bar has been hidden or shown, we need to do another
5524            // layout pass to update that window.
5525            return FINISH_LAYOUT_REDO_LAYOUT;
5526        }
5527        return 0;
5528    }
5529
5530    /** {@inheritDoc} */
5531    @Override
5532    public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
5533        // lid changed state
5534        final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
5535        if (newLidState == mLidState) {
5536            return;
5537        }
5538
5539        mLidState = newLidState;
5540        applyLidSwitchState();
5541        updateRotation(true);
5542
5543        if (lidOpen) {
5544            wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
5545                    "android.policy:LID");
5546        } else if (!mLidControlsSleep) {
5547            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
5548        }
5549    }
5550
5551    @Override
5552    public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
5553        int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
5554        if (mCameraLensCoverState == lensCoverState) {
5555            return;
5556        }
5557        if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
5558                lensCoverState == CAMERA_LENS_UNCOVERED) {
5559            Intent intent;
5560            final boolean keyguardActive = mKeyguardDelegate == null ? false :
5561                    mKeyguardDelegate.isShowing();
5562            if (keyguardActive) {
5563                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
5564            } else {
5565                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
5566            }
5567            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
5568                    "android.policy:CAMERA_COVER");
5569            startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
5570        }
5571        mCameraLensCoverState = lensCoverState;
5572    }
5573
5574    void setHdmiPlugged(boolean plugged) {
5575        if (mHdmiPlugged != plugged) {
5576            mHdmiPlugged = plugged;
5577            updateRotation(true, true);
5578            Intent intent = new Intent(ACTION_HDMI_PLUGGED);
5579            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
5580            intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
5581            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
5582        }
5583    }
5584
5585    void initializeHdmiState() {
5586        boolean plugged = false;
5587        // watch for HDMI plug messages if the hdmi switch exists
5588        if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
5589            mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
5590
5591            final String filename = "/sys/class/switch/hdmi/state";
5592            FileReader reader = null;
5593            try {
5594                reader = new FileReader(filename);
5595                char[] buf = new char[15];
5596                int n = reader.read(buf);
5597                if (n > 1) {
5598                    plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
5599                }
5600            } catch (IOException ex) {
5601                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5602            } catch (NumberFormatException ex) {
5603                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5604            } finally {
5605                if (reader != null) {
5606                    try {
5607                        reader.close();
5608                    } catch (IOException ex) {
5609                    }
5610                }
5611            }
5612        }
5613        // This dance forces the code in setHdmiPlugged to run.
5614        // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
5615        mHdmiPlugged = !plugged;
5616        setHdmiPlugged(!mHdmiPlugged);
5617    }
5618
5619    final Object mScreenshotLock = new Object();
5620    ServiceConnection mScreenshotConnection = null;
5621
5622    final Runnable mScreenshotTimeout = new Runnable() {
5623        @Override public void run() {
5624            synchronized (mScreenshotLock) {
5625                if (mScreenshotConnection != null) {
5626                    mContext.unbindService(mScreenshotConnection);
5627                    mScreenshotConnection = null;
5628                    notifyScreenshotError();
5629                }
5630            }
5631        }
5632    };
5633
5634    // Assume this is called from the Handler thread.
5635    private void takeScreenshot(final int screenshotType) {
5636        synchronized (mScreenshotLock) {
5637            if (mScreenshotConnection != null) {
5638                return;
5639            }
5640            final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
5641                    SYSUI_SCREENSHOT_SERVICE);
5642            final Intent serviceIntent = new Intent();
5643            serviceIntent.setComponent(serviceComponent);
5644            ServiceConnection conn = new ServiceConnection() {
5645                @Override
5646                public void onServiceConnected(ComponentName name, IBinder service) {
5647                    synchronized (mScreenshotLock) {
5648                        if (mScreenshotConnection != this) {
5649                            return;
5650                        }
5651                        Messenger messenger = new Messenger(service);
5652                        Message msg = Message.obtain(null, screenshotType);
5653                        final ServiceConnection myConn = this;
5654                        Handler h = new Handler(mHandler.getLooper()) {
5655                            @Override
5656                            public void handleMessage(Message msg) {
5657                                synchronized (mScreenshotLock) {
5658                                    if (mScreenshotConnection == myConn) {
5659                                        mContext.unbindService(mScreenshotConnection);
5660                                        mScreenshotConnection = null;
5661                                        mHandler.removeCallbacks(mScreenshotTimeout);
5662                                    }
5663                                }
5664                            }
5665                        };
5666                        msg.replyTo = new Messenger(h);
5667                        msg.arg1 = msg.arg2 = 0;
5668                        if (mStatusBar != null && mStatusBar.isVisibleLw())
5669                            msg.arg1 = 1;
5670                        if (mNavigationBar != null && mNavigationBar.isVisibleLw())
5671                            msg.arg2 = 1;
5672                        try {
5673                            messenger.send(msg);
5674                        } catch (RemoteException e) {
5675                        }
5676                    }
5677                }
5678
5679                @Override
5680                public void onServiceDisconnected(ComponentName name) {
5681                    synchronized (mScreenshotLock) {
5682                        if (mScreenshotConnection != null) {
5683                            mContext.unbindService(mScreenshotConnection);
5684                            mScreenshotConnection = null;
5685                            mHandler.removeCallbacks(mScreenshotTimeout);
5686                            notifyScreenshotError();
5687                        }
5688                    }
5689                }
5690            };
5691            if (mContext.bindServiceAsUser(serviceIntent, conn,
5692                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
5693                    UserHandle.CURRENT)) {
5694                mScreenshotConnection = conn;
5695                mHandler.postDelayed(mScreenshotTimeout, 10000);
5696            }
5697        }
5698    }
5699
5700    /**
5701     * Notifies the screenshot service to show an error.
5702     */
5703    private void notifyScreenshotError() {
5704        // If the service process is killed, then ask it to clean up after itself
5705        final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
5706                SYSUI_SCREENSHOT_ERROR_RECEIVER);
5707        Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
5708        errorIntent.setComponent(errorComponent);
5709        errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
5710                Intent.FLAG_RECEIVER_FOREGROUND);
5711        mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT);
5712    }
5713
5714    /** {@inheritDoc} */
5715    @Override
5716    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
5717        if (!mSystemBooted) {
5718            // If we have not yet booted, don't let key events do anything.
5719            return 0;
5720        }
5721
5722        final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
5723        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
5724        final boolean canceled = event.isCanceled();
5725        final int keyCode = event.getKeyCode();
5726
5727        final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
5728
5729        // If screen is off then we treat the case where the keyguard is open but hidden
5730        // the same as if it were open and in front.
5731        // This will prevent any keys other than the power button from waking the screen
5732        // when the keyguard is hidden by another activity.
5733        final boolean keyguardActive = (mKeyguardDelegate == null ? false :
5734                                            (interactive ?
5735                                                isKeyguardShowingAndNotOccluded() :
5736                                                mKeyguardDelegate.isShowing()));
5737
5738        if (DEBUG_INPUT) {
5739            Log.d(TAG, "interceptKeyTq keycode=" + keyCode
5740                    + " interactive=" + interactive + " keyguardActive=" + keyguardActive
5741                    + " policyFlags=" + Integer.toHexString(policyFlags));
5742        }
5743
5744        // Basic policy based on interactive state.
5745        int result;
5746        boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
5747                || event.isWakeKey();
5748        if (interactive || (isInjected && !isWakeKey)) {
5749            // When the device is interactive or the key is injected pass the
5750            // key to the application.
5751            result = ACTION_PASS_TO_USER;
5752            isWakeKey = false;
5753
5754            if (interactive) {
5755                // If the screen is awake, but the button pressed was the one that woke the device
5756                // then don't pass it to the application
5757                if (keyCode == mPendingWakeKey && !down) {
5758                    result = 0;
5759                }
5760                // Reset the pending key
5761                mPendingWakeKey = PENDING_KEY_NULL;
5762            }
5763        } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
5764            // If we're currently dozing with the screen on and the keyguard showing, pass the key
5765            // to the application but preserve its wake key status to make sure we still move
5766            // from dozing to fully interactive if we would normally go from off to fully
5767            // interactive.
5768            result = ACTION_PASS_TO_USER;
5769            // Since we're dispatching the input, reset the pending key
5770            mPendingWakeKey = PENDING_KEY_NULL;
5771        } else {
5772            // When the screen is off and the key is not injected, determine whether
5773            // to wake the device but don't pass the key to the application.
5774            result = 0;
5775            if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
5776                isWakeKey = false;
5777            }
5778            // Cache the wake key on down event so we can also avoid sending the up event to the app
5779            if (isWakeKey && down) {
5780                mPendingWakeKey = keyCode;
5781            }
5782        }
5783
5784        // If the key would be handled globally, just return the result, don't worry about special
5785        // key processing.
5786        if (isValidGlobalKey(keyCode)
5787                && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
5788            if (isWakeKey) {
5789                wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5790            }
5791            return result;
5792        }
5793
5794        boolean useHapticFeedback = down
5795                && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
5796                && event.getRepeatCount() == 0;
5797
5798        // Handle special keys.
5799        switch (keyCode) {
5800            case KeyEvent.KEYCODE_BACK: {
5801                if (down) {
5802                    interceptBackKeyDown();
5803                } else {
5804                    boolean handled = interceptBackKeyUp(event);
5805
5806                    // Don't pass back press to app if we've already handled it via long press
5807                    if (handled) {
5808                        result &= ~ACTION_PASS_TO_USER;
5809                    }
5810                }
5811                break;
5812            }
5813
5814            case KeyEvent.KEYCODE_VOLUME_DOWN:
5815            case KeyEvent.KEYCODE_VOLUME_UP:
5816            case KeyEvent.KEYCODE_VOLUME_MUTE: {
5817                if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
5818                    if (down) {
5819                        if (interactive && !mScreenshotChordVolumeDownKeyTriggered
5820                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5821                            mScreenshotChordVolumeDownKeyTriggered = true;
5822                            mScreenshotChordVolumeDownKeyTime = event.getDownTime();
5823                            mScreenshotChordVolumeDownKeyConsumed = false;
5824                            cancelPendingPowerKeyAction();
5825                            interceptScreenshotChord();
5826                            interceptAccessibilityShortcutChord();
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                            interceptAccessibilityShortcutChord();
5843                        }
5844                    } else {
5845                        mA11yShortcutChordVolumeUpKeyTriggered = false;
5846                        cancelPendingScreenshotChordAction();
5847                        cancelPendingAccessibilityShortcutAction();
5848                    }
5849                }
5850                if (down) {
5851                    TelecomManager telecomManager = getTelecommService();
5852                    if (telecomManager != null) {
5853                        if (telecomManager.isRinging()) {
5854                            // If an incoming call is ringing, either VOLUME key means
5855                            // "silence ringer".  We handle these keys here, rather than
5856                            // in the InCallScreen, to make sure we'll respond to them
5857                            // even if the InCallScreen hasn't come to the foreground yet.
5858                            // Look for the DOWN event here, to agree with the "fallback"
5859                            // behavior in the InCallScreen.
5860                            Log.i(TAG, "interceptKeyBeforeQueueing:"
5861                                  + " VOLUME key-down while ringing: Silence ringer!");
5862
5863                            // Silence the ringer.  (It's safe to call this
5864                            // even if the ringer has already been silenced.)
5865                            telecomManager.silenceRinger();
5866
5867                            // And *don't* pass this key thru to the current activity
5868                            // (which is probably the InCallScreen.)
5869                            result &= ~ACTION_PASS_TO_USER;
5870                            break;
5871                        }
5872                        if (telecomManager.isInCall()
5873                                && (result & ACTION_PASS_TO_USER) == 0) {
5874                            // If we are in call but we decided not to pass the key to
5875                            // the application, just pass it to the session service.
5876                            MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
5877                                    event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
5878                            break;
5879                        }
5880                    }
5881                }
5882                if (mUseTvRouting) {
5883                    // On TVs, defer special key handlings to
5884                    // {@link interceptKeyBeforeDispatching()}.
5885                    result |= ACTION_PASS_TO_USER;
5886                } else if ((result & ACTION_PASS_TO_USER) == 0) {
5887                    // If we aren't passing to the user and no one else
5888                    // handled it send it to the session manager to
5889                    // figure out.
5890                    MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
5891                            event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
5892                }
5893                break;
5894            }
5895
5896            case KeyEvent.KEYCODE_ENDCALL: {
5897                result &= ~ACTION_PASS_TO_USER;
5898                if (down) {
5899                    TelecomManager telecomManager = getTelecommService();
5900                    boolean hungUp = false;
5901                    if (telecomManager != null) {
5902                        hungUp = telecomManager.endCall();
5903                    }
5904                    if (interactive && !hungUp) {
5905                        mEndCallKeyHandled = false;
5906                        mHandler.postDelayed(mEndCallLongPress,
5907                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
5908                    } else {
5909                        mEndCallKeyHandled = true;
5910                    }
5911                } else {
5912                    if (!mEndCallKeyHandled) {
5913                        mHandler.removeCallbacks(mEndCallLongPress);
5914                        if (!canceled) {
5915                            if ((mEndcallBehavior
5916                                    & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
5917                                if (goHome()) {
5918                                    break;
5919                                }
5920                            }
5921                            if ((mEndcallBehavior
5922                                    & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
5923                                mPowerManager.goToSleep(event.getEventTime(),
5924                                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
5925                                isWakeKey = false;
5926                            }
5927                        }
5928                    }
5929                }
5930                break;
5931            }
5932
5933            case KeyEvent.KEYCODE_POWER: {
5934                // Any activity on the power button stops the accessibility shortcut
5935                cancelPendingAccessibilityShortcutAction();
5936                result &= ~ACTION_PASS_TO_USER;
5937                isWakeKey = false; // wake-up will be handled separately
5938                if (down) {
5939                    interceptPowerKeyDown(event, interactive);
5940                } else {
5941                    interceptPowerKeyUp(event, interactive, canceled);
5942                }
5943                break;
5944            }
5945
5946            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
5947                // fall through
5948            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
5949                // fall through
5950            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
5951                // fall through
5952            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
5953                result &= ~ACTION_PASS_TO_USER;
5954                interceptSystemNavigationKey(event);
5955                break;
5956            }
5957
5958            case KeyEvent.KEYCODE_SLEEP: {
5959                result &= ~ACTION_PASS_TO_USER;
5960                isWakeKey = false;
5961                if (!mPowerManager.isInteractive()) {
5962                    useHapticFeedback = false; // suppress feedback if already non-interactive
5963                }
5964                if (down) {
5965                    sleepPress(event.getEventTime());
5966                } else {
5967                    sleepRelease(event.getEventTime());
5968                }
5969                break;
5970            }
5971
5972            case KeyEvent.KEYCODE_SOFT_SLEEP: {
5973                result &= ~ACTION_PASS_TO_USER;
5974                isWakeKey = false;
5975                if (!down) {
5976                    mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
5977                }
5978                break;
5979            }
5980
5981            case KeyEvent.KEYCODE_WAKEUP: {
5982                result &= ~ACTION_PASS_TO_USER;
5983                isWakeKey = true;
5984                break;
5985            }
5986
5987            case KeyEvent.KEYCODE_MEDIA_PLAY:
5988            case KeyEvent.KEYCODE_MEDIA_PAUSE:
5989            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
5990            case KeyEvent.KEYCODE_HEADSETHOOK:
5991            case KeyEvent.KEYCODE_MUTE:
5992            case KeyEvent.KEYCODE_MEDIA_STOP:
5993            case KeyEvent.KEYCODE_MEDIA_NEXT:
5994            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
5995            case KeyEvent.KEYCODE_MEDIA_REWIND:
5996            case KeyEvent.KEYCODE_MEDIA_RECORD:
5997            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
5998            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
5999                if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
6000                    // If the global session is active pass all media keys to it
6001                    // instead of the active window.
6002                    result &= ~ACTION_PASS_TO_USER;
6003                }
6004                if ((result & ACTION_PASS_TO_USER) == 0) {
6005                    // Only do this if we would otherwise not pass it to the user. In that
6006                    // case, the PhoneWindow class will do the same thing, except it will
6007                    // only do it if the showing app doesn't process the key on its own.
6008                    // Note that we need to make a copy of the key event here because the
6009                    // original key event will be recycled when we return.
6010                    mBroadcastWakeLock.acquire();
6011                    Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
6012                            new KeyEvent(event));
6013                    msg.setAsynchronous(true);
6014                    msg.sendToTarget();
6015                }
6016                break;
6017            }
6018
6019            case KeyEvent.KEYCODE_CALL: {
6020                if (down) {
6021                    TelecomManager telecomManager = getTelecommService();
6022                    if (telecomManager != null) {
6023                        if (telecomManager.isRinging()) {
6024                            Log.i(TAG, "interceptKeyBeforeQueueing:"
6025                                  + " CALL key-down while ringing: Answer the call!");
6026                            telecomManager.acceptRingingCall();
6027
6028                            // And *don't* pass this key thru to the current activity
6029                            // (which is presumably the InCallScreen.)
6030                            result &= ~ACTION_PASS_TO_USER;
6031                        }
6032                    }
6033                }
6034                break;
6035            }
6036            case KeyEvent.KEYCODE_VOICE_ASSIST: {
6037                // Only do this if we would otherwise not pass it to the user. In that case,
6038                // interceptKeyBeforeDispatching would apply a similar but different policy in
6039                // order to invoke voice assist actions. Note that we need to make a copy of the
6040                // key event here because the original key event will be recycled when we return.
6041                if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
6042                    mBroadcastWakeLock.acquire();
6043                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
6044                            keyguardActive ? 1 : 0, 0);
6045                    msg.setAsynchronous(true);
6046                    msg.sendToTarget();
6047                }
6048                break;
6049            }
6050            case KeyEvent.KEYCODE_WINDOW: {
6051                if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
6052                    if (mPictureInPictureVisible) {
6053                        // Consumes the key only if picture-in-picture is visible to show
6054                        // picture-in-picture control menu. This gives a chance to the foreground
6055                        // activity to customize PIP key behavior.
6056                        if (!down) {
6057                            showPictureInPictureMenu(event);
6058                        }
6059                        result &= ~ACTION_PASS_TO_USER;
6060                    }
6061                }
6062                break;
6063            }
6064        }
6065
6066        if (useHapticFeedback) {
6067            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
6068        }
6069
6070        if (isWakeKey) {
6071            wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
6072        }
6073
6074        return result;
6075    }
6076
6077    /**
6078     * Handle statusbar expansion events.
6079     * @param event
6080     */
6081    private void interceptSystemNavigationKey(KeyEvent event) {
6082        if (event.getAction() == KeyEvent.ACTION_UP) {
6083            if (!mAccessibilityManager.isEnabled()
6084                    || !mAccessibilityManager.sendFingerprintGesture(event.getKeyCode())) {
6085                if (areSystemNavigationKeysEnabled()) {
6086                    IStatusBarService sbar = getStatusBarService();
6087                    if (sbar != null) {
6088                        try {
6089                            sbar.handleSystemNavigationKey(event.getKeyCode());
6090                        } catch (RemoteException e1) {
6091                            // oops, no statusbar. Ignore event.
6092                        }
6093                    }
6094                }
6095            }
6096        }
6097    }
6098
6099    /**
6100     * Returns true if the key can have global actions attached to it.
6101     * We reserve all power management keys for the system since they require
6102     * very careful handling.
6103     */
6104    private static boolean isValidGlobalKey(int keyCode) {
6105        switch (keyCode) {
6106            case KeyEvent.KEYCODE_POWER:
6107            case KeyEvent.KEYCODE_WAKEUP:
6108            case KeyEvent.KEYCODE_SLEEP:
6109                return false;
6110            default:
6111                return true;
6112        }
6113    }
6114
6115    /**
6116     * When the screen is off we ignore some keys that might otherwise typically
6117     * be considered wake keys.  We filter them out here.
6118     *
6119     * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
6120     * is always considered a wake key.
6121     */
6122    private boolean isWakeKeyWhenScreenOff(int keyCode) {
6123        switch (keyCode) {
6124            // ignore volume keys unless docked
6125            case KeyEvent.KEYCODE_VOLUME_UP:
6126            case KeyEvent.KEYCODE_VOLUME_DOWN:
6127            case KeyEvent.KEYCODE_VOLUME_MUTE:
6128                return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
6129
6130            // ignore media and camera keys
6131            case KeyEvent.KEYCODE_MUTE:
6132            case KeyEvent.KEYCODE_HEADSETHOOK:
6133            case KeyEvent.KEYCODE_MEDIA_PLAY:
6134            case KeyEvent.KEYCODE_MEDIA_PAUSE:
6135            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6136            case KeyEvent.KEYCODE_MEDIA_STOP:
6137            case KeyEvent.KEYCODE_MEDIA_NEXT:
6138            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6139            case KeyEvent.KEYCODE_MEDIA_REWIND:
6140            case KeyEvent.KEYCODE_MEDIA_RECORD:
6141            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6142            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
6143            case KeyEvent.KEYCODE_CAMERA:
6144                return false;
6145        }
6146        return true;
6147    }
6148
6149
6150    /** {@inheritDoc} */
6151    @Override
6152    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
6153        if ((policyFlags & FLAG_WAKE) != 0) {
6154            if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
6155                    "android.policy:MOTION")) {
6156                return 0;
6157            }
6158        }
6159
6160        if (shouldDispatchInputWhenNonInteractive(null)) {
6161            return ACTION_PASS_TO_USER;
6162        }
6163
6164        // If we have not passed the action up and we are in theater mode without dreaming,
6165        // there will be no dream to intercept the touch and wake into ambient.  The device should
6166        // wake up in this case.
6167        if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
6168            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
6169                    "android.policy:MOTION");
6170        }
6171
6172        return 0;
6173    }
6174
6175    private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
6176        final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
6177
6178        if (displayOff && !mHasFeatureWatch) {
6179            return false;
6180        }
6181
6182        // Send events to keyguard while the screen is on and it's showing.
6183        if (isKeyguardShowingAndNotOccluded() && !displayOff) {
6184            return true;
6185        }
6186
6187        // Watches handle BACK specially
6188        if (mHasFeatureWatch
6189                && event != null
6190                && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
6191                        || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
6192            return false;
6193        }
6194
6195        // Send events to a dozing dream even if the screen is off since the dream
6196        // is in control of the state of the screen.
6197        IDreamManager dreamManager = getDreamManager();
6198
6199        try {
6200            if (dreamManager != null && dreamManager.isDreaming()) {
6201                return true;
6202            }
6203        } catch (RemoteException e) {
6204            Slog.e(TAG, "RemoteException when checking if dreaming", e);
6205        }
6206
6207        // Otherwise, consume events since the user can't see what is being
6208        // interacted with.
6209        return false;
6210    }
6211
6212    private void dispatchDirectAudioEvent(KeyEvent event) {
6213        if (event.getAction() != KeyEvent.ACTION_DOWN) {
6214            return;
6215        }
6216        int keyCode = event.getKeyCode();
6217        int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
6218                | AudioManager.FLAG_FROM_KEY;
6219        String pkgName = mContext.getOpPackageName();
6220        switch (keyCode) {
6221            case KeyEvent.KEYCODE_VOLUME_UP:
6222                try {
6223                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
6224                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6225                } catch (RemoteException e) {
6226                    Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
6227                }
6228                break;
6229            case KeyEvent.KEYCODE_VOLUME_DOWN:
6230                try {
6231                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
6232                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6233                } catch (RemoteException e) {
6234                    Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
6235                }
6236                break;
6237            case KeyEvent.KEYCODE_VOLUME_MUTE:
6238                try {
6239                    if (event.getRepeatCount() == 0) {
6240                        getAudioService().adjustSuggestedStreamVolume(
6241                                AudioManager.ADJUST_TOGGLE_MUTE,
6242                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6243                    }
6244                } catch (RemoteException e) {
6245                    Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
6246                }
6247                break;
6248        }
6249    }
6250
6251    void dispatchMediaKeyWithWakeLock(KeyEvent event) {
6252        if (DEBUG_INPUT) {
6253            Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
6254        }
6255
6256        if (mHavePendingMediaKeyRepeatWithWakeLock) {
6257            if (DEBUG_INPUT) {
6258                Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
6259            }
6260
6261            mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
6262            mHavePendingMediaKeyRepeatWithWakeLock = false;
6263            mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
6264        }
6265
6266        dispatchMediaKeyWithWakeLockToAudioService(event);
6267
6268        if (event.getAction() == KeyEvent.ACTION_DOWN
6269                && event.getRepeatCount() == 0) {
6270            mHavePendingMediaKeyRepeatWithWakeLock = true;
6271
6272            Message msg = mHandler.obtainMessage(
6273                    MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
6274            msg.setAsynchronous(true);
6275            mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
6276        } else {
6277            mBroadcastWakeLock.release();
6278        }
6279    }
6280
6281    void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
6282        mHavePendingMediaKeyRepeatWithWakeLock = false;
6283
6284        KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
6285                SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6286        if (DEBUG_INPUT) {
6287            Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
6288        }
6289
6290        dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
6291        mBroadcastWakeLock.release();
6292    }
6293
6294    void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
6295        if (mActivityManagerInternal.isSystemReady()) {
6296            MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
6297        }
6298    }
6299
6300    void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
6301        IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
6302                ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
6303        if (dic != null) {
6304            try {
6305                dic.exitIdle("voice-search");
6306            } catch (RemoteException e) {
6307            }
6308        }
6309        Intent voiceIntent =
6310            new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
6311        voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
6312        startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
6313        mBroadcastWakeLock.release();
6314    }
6315
6316    BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
6317        @Override
6318        public void onReceive(Context context, Intent intent) {
6319            if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
6320                mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6321                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
6322            } else {
6323                try {
6324                    IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
6325                            ServiceManager.getService(Context.UI_MODE_SERVICE));
6326                    mUiMode = uiModeService.getCurrentModeType();
6327                } catch (RemoteException e) {
6328                }
6329            }
6330            updateRotation(true);
6331            synchronized (mLock) {
6332                updateOrientationListenerLp();
6333            }
6334        }
6335    };
6336
6337    BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
6338        @Override
6339        public void onReceive(Context context, Intent intent) {
6340            if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
6341                if (mKeyguardDelegate != null) {
6342                    mKeyguardDelegate.onDreamingStarted();
6343                }
6344            } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
6345                if (mKeyguardDelegate != null) {
6346                    mKeyguardDelegate.onDreamingStopped();
6347                }
6348            }
6349        }
6350    };
6351
6352    BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
6353        @Override
6354        public void onReceive(Context context, Intent intent) {
6355            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
6356                // tickle the settings observer: this first ensures that we're
6357                // observing the relevant settings for the newly-active user,
6358                // and then updates our own bookkeeping based on the now-
6359                // current user.
6360                mSettingsObserver.onChange(false);
6361
6362                // force a re-application of focused window sysui visibility.
6363                // the window may never have been shown for this user
6364                // e.g. the keyguard when going through the new-user setup flow
6365                synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6366                    mLastSystemUiFlags = 0;
6367                    updateSystemUiVisibilityLw();
6368                }
6369            }
6370        }
6371    };
6372
6373    private final Runnable mHiddenNavPanic = new Runnable() {
6374        @Override
6375        public void run() {
6376            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6377                if (!isUserSetupComplete()) {
6378                    // Swipe-up for navigation bar is disabled during setup
6379                    return;
6380                }
6381                mPendingPanicGestureUptime = SystemClock.uptimeMillis();
6382                if (!isNavBarEmpty(mLastSystemUiFlags)) {
6383                    mNavigationBarController.showTransient();
6384                }
6385            }
6386        }
6387    };
6388
6389    private void requestTransientBars(WindowState swipeTarget) {
6390        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6391            if (!isUserSetupComplete()) {
6392                // Swipe-up for navigation bar is disabled during setup
6393                return;
6394            }
6395            boolean sb = mStatusBarController.checkShowTransientBarLw();
6396            boolean nb = mNavigationBarController.checkShowTransientBarLw()
6397                    && !isNavBarEmpty(mLastSystemUiFlags);
6398            if (sb || nb) {
6399                // Don't show status bar when swiping on already visible navigation bar
6400                if (!nb && swipeTarget == mNavigationBar) {
6401                    if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
6402                    return;
6403                }
6404                if (sb) mStatusBarController.showTransient();
6405                if (nb) mNavigationBarController.showTransient();
6406                mImmersiveModeConfirmation.confirmCurrentPrompt();
6407                updateSystemUiVisibilityLw();
6408            }
6409        }
6410    }
6411
6412    // Called on the PowerManager's Notifier thread.
6413    @Override
6414    public void startedGoingToSleep(int why) {
6415        if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
6416        mCameraGestureTriggeredDuringGoingToSleep = false;
6417        mGoingToSleep = true;
6418        if (mKeyguardDelegate != null) {
6419            mKeyguardDelegate.onStartedGoingToSleep(why);
6420        }
6421    }
6422
6423    // Called on the PowerManager's Notifier thread.
6424    @Override
6425    public void finishedGoingToSleep(int why) {
6426        EventLog.writeEvent(70000, 0);
6427        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
6428        MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
6429
6430        mGoingToSleep = false;
6431
6432        // We must get this work done here because the power manager will drop
6433        // the wake lock and let the system suspend once this function returns.
6434        synchronized (mLock) {
6435            mAwake = false;
6436            updateWakeGestureListenerLp();
6437            updateOrientationListenerLp();
6438            updateLockScreenTimeout();
6439        }
6440        if (mKeyguardDelegate != null) {
6441            mKeyguardDelegate.onFinishedGoingToSleep(why,
6442                    mCameraGestureTriggeredDuringGoingToSleep);
6443        }
6444        mCameraGestureTriggeredDuringGoingToSleep = false;
6445    }
6446
6447    // Called on the PowerManager's Notifier thread.
6448    @Override
6449    public void startedWakingUp() {
6450        EventLog.writeEvent(70000, 1);
6451        if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
6452
6453        // Since goToSleep performs these functions synchronously, we must
6454        // do the same here.  We cannot post this work to a handler because
6455        // that might cause it to become reordered with respect to what
6456        // may happen in a future call to goToSleep.
6457        synchronized (mLock) {
6458            mAwake = true;
6459
6460            updateWakeGestureListenerLp();
6461            updateOrientationListenerLp();
6462            updateLockScreenTimeout();
6463        }
6464
6465        if (mKeyguardDelegate != null) {
6466            mKeyguardDelegate.onStartedWakingUp();
6467        }
6468    }
6469
6470    // Called on the PowerManager's Notifier thread.
6471    @Override
6472    public void finishedWakingUp() {
6473        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
6474    }
6475
6476    private void wakeUpFromPowerKey(long eventTime) {
6477        wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
6478    }
6479
6480    private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
6481        final boolean theaterModeEnabled = isTheaterModeEnabled();
6482        if (!wakeInTheaterMode && theaterModeEnabled) {
6483            return false;
6484        }
6485
6486        if (theaterModeEnabled) {
6487            Settings.Global.putInt(mContext.getContentResolver(),
6488                    Settings.Global.THEATER_MODE_ON, 0);
6489        }
6490
6491        mPowerManager.wakeUp(wakeTime, reason);
6492        return true;
6493    }
6494
6495    private void finishKeyguardDrawn() {
6496        synchronized (mLock) {
6497            if (!mScreenOnEarly || mKeyguardDrawComplete) {
6498                return; // We are not awake yet or we have already informed of this event.
6499            }
6500
6501            mKeyguardDrawComplete = true;
6502            if (mKeyguardDelegate != null) {
6503                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6504            }
6505            mWindowManagerDrawComplete = false;
6506        }
6507
6508        // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
6509        // as well as enabling the orientation change logic/sensor.
6510        mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
6511                WAITING_FOR_DRAWN_TIMEOUT);
6512    }
6513
6514    // Called on the DisplayManager's DisplayPowerController thread.
6515    @Override
6516    public void screenTurnedOff() {
6517        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
6518
6519        updateScreenOffSleepToken(true);
6520        synchronized (mLock) {
6521            mScreenOnEarly = false;
6522            mScreenOnFully = false;
6523            mKeyguardDrawComplete = false;
6524            mWindowManagerDrawComplete = false;
6525            mScreenOnListener = null;
6526            updateOrientationListenerLp();
6527
6528            if (mKeyguardDelegate != null) {
6529                mKeyguardDelegate.onScreenTurnedOff();
6530            }
6531        }
6532        reportScreenStateToVrManager(false);
6533    }
6534
6535    // Called on the DisplayManager's DisplayPowerController thread.
6536    @Override
6537    public void screenTurningOn(final ScreenOnListener screenOnListener) {
6538        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
6539
6540        updateScreenOffSleepToken(false);
6541        synchronized (mLock) {
6542            mScreenOnEarly = true;
6543            mScreenOnFully = false;
6544            mKeyguardDrawComplete = false;
6545            mWindowManagerDrawComplete = false;
6546            mScreenOnListener = screenOnListener;
6547
6548            if (mKeyguardDelegate != null) {
6549                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6550                mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
6551                mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
6552            } else {
6553                if (DEBUG_WAKEUP) Slog.d(TAG,
6554                        "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
6555                finishKeyguardDrawn();
6556            }
6557        }
6558    }
6559
6560    // Called on the DisplayManager's DisplayPowerController thread.
6561    @Override
6562    public void screenTurnedOn() {
6563        synchronized (mLock) {
6564            if (mKeyguardDelegate != null) {
6565                mKeyguardDelegate.onScreenTurnedOn();
6566            }
6567        }
6568        reportScreenStateToVrManager(true);
6569    }
6570
6571    private void reportScreenStateToVrManager(boolean isScreenOn) {
6572        if (mVrManagerInternal == null) {
6573            return;
6574        }
6575        mVrManagerInternal.onScreenStateChanged(isScreenOn);
6576    }
6577
6578    private void exitPersistentVrMode() {
6579        if (mVrManagerInternal == null) {
6580            return;
6581        }
6582        mVrManagerInternal.setPersistentVrModeEnabled(false);
6583    }
6584
6585    private void finishWindowsDrawn() {
6586        synchronized (mLock) {
6587            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
6588                return; // Screen is not turned on or we did already handle this case earlier.
6589            }
6590
6591            mWindowManagerDrawComplete = true;
6592        }
6593
6594        finishScreenTurningOn();
6595    }
6596
6597    private void finishScreenTurningOn() {
6598        synchronized (mLock) {
6599            // We have just finished drawing screen content. Since the orientation listener
6600            // gets only installed when all windows are drawn, we try to install it again.
6601            updateOrientationListenerLp();
6602        }
6603        final ScreenOnListener listener;
6604        final boolean enableScreen;
6605        synchronized (mLock) {
6606            if (DEBUG_WAKEUP) Slog.d(TAG,
6607                    "finishScreenTurningOn: mAwake=" + mAwake
6608                            + ", mScreenOnEarly=" + mScreenOnEarly
6609                            + ", mScreenOnFully=" + mScreenOnFully
6610                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
6611                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
6612
6613            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
6614                    || (mAwake && !mKeyguardDrawComplete)) {
6615                return; // spurious or not ready yet
6616            }
6617
6618            if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
6619            listener = mScreenOnListener;
6620            mScreenOnListener = null;
6621            mScreenOnFully = true;
6622
6623            // Remember the first time we draw the keyguard so we know when we're done with
6624            // the main part of booting and can enable the screen and hide boot messages.
6625            if (!mKeyguardDrawnOnce && mAwake) {
6626                mKeyguardDrawnOnce = true;
6627                enableScreen = true;
6628                if (mBootMessageNeedsHiding) {
6629                    mBootMessageNeedsHiding = false;
6630                    hideBootMessages();
6631                }
6632            } else {
6633                enableScreen = false;
6634            }
6635        }
6636
6637        if (listener != null) {
6638            listener.onScreenOn();
6639        }
6640
6641        if (enableScreen) {
6642            try {
6643                mWindowManager.enableScreenIfNeeded();
6644            } catch (RemoteException unhandled) {
6645            }
6646        }
6647    }
6648
6649    private void handleHideBootMessage() {
6650        synchronized (mLock) {
6651            if (!mKeyguardDrawnOnce) {
6652                mBootMessageNeedsHiding = true;
6653                return; // keyguard hasn't drawn the first time yet, not done booting
6654            }
6655        }
6656
6657        if (mBootMsgDialog != null) {
6658            if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
6659            mBootMsgDialog.dismiss();
6660            mBootMsgDialog = null;
6661        }
6662    }
6663
6664    @Override
6665    public boolean isScreenOn() {
6666        return mScreenOnFully;
6667    }
6668
6669    /** {@inheritDoc} */
6670    @Override
6671    public void enableKeyguard(boolean enabled) {
6672        if (mKeyguardDelegate != null) {
6673            mKeyguardDelegate.setKeyguardEnabled(enabled);
6674        }
6675    }
6676
6677    /** {@inheritDoc} */
6678    @Override
6679    public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
6680        if (mKeyguardDelegate != null) {
6681            mKeyguardDelegate.verifyUnlock(callback);
6682        }
6683    }
6684
6685    @Override
6686    public boolean isKeyguardShowingAndNotOccluded() {
6687        if (mKeyguardDelegate == null) return false;
6688        return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
6689    }
6690
6691    @Override
6692    public boolean isKeyguardTrustedLw() {
6693        if (mKeyguardDelegate == null) return false;
6694        return mKeyguardDelegate.isTrusted();
6695    }
6696
6697    /** {@inheritDoc} */
6698    @Override
6699    public boolean isKeyguardLocked() {
6700        return keyguardOn();
6701    }
6702
6703    /** {@inheritDoc} */
6704    @Override
6705    public boolean isKeyguardSecure(int userId) {
6706        if (mKeyguardDelegate == null) return false;
6707        return mKeyguardDelegate.isSecure(userId);
6708    }
6709
6710    /** {@inheritDoc} */
6711    @Override
6712    public boolean isKeyguardOccluded() {
6713        if (mKeyguardDelegate == null) return false;
6714        return mKeyguardOccluded;
6715    }
6716
6717    /** {@inheritDoc} */
6718    @Override
6719    public boolean inKeyguardRestrictedKeyInputMode() {
6720        if (mKeyguardDelegate == null) return false;
6721        return mKeyguardDelegate.isInputRestricted();
6722    }
6723
6724    @Override
6725    public void dismissKeyguardLw(IKeyguardDismissCallback callback) {
6726        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
6727            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
6728
6729            // ask the keyguard to prompt the user to authenticate if necessary
6730            mKeyguardDelegate.dismiss(callback);
6731        } else if (callback != null) {
6732            try {
6733                callback.onDismissError();
6734            } catch (RemoteException e) {
6735                Slog.w(TAG, "Failed to call callback", e);
6736            }
6737        }
6738    }
6739
6740    @Override
6741    public boolean isKeyguardDrawnLw() {
6742        synchronized (mLock) {
6743            return mKeyguardDrawnOnce;
6744        }
6745    }
6746
6747    @Override
6748    public boolean isShowingDreamLw() {
6749        return mShowingDream;
6750    }
6751
6752    @Override
6753    public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
6754        if (mKeyguardDelegate != null) {
6755            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
6756            mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
6757        }
6758    }
6759
6760    @Override
6761    public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6762            Rect outInsets) {
6763        outInsets.setEmpty();
6764
6765        // Navigation bar and status bar.
6766        getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
6767        outInsets.top = mStatusBarHeight;
6768    }
6769
6770    @Override
6771    public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6772            Rect outInsets) {
6773        outInsets.setEmpty();
6774
6775        // Only navigation bar
6776        if (mHasNavigationBar) {
6777            int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
6778            if (position == NAV_BAR_BOTTOM) {
6779                outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
6780            } else if (position == NAV_BAR_RIGHT) {
6781                outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
6782            } else if (position == NAV_BAR_LEFT) {
6783                outInsets.left = getNavigationBarWidth(displayRotation, mUiMode);
6784            }
6785        }
6786    }
6787
6788    @Override
6789    public boolean isNavBarForcedShownLw(WindowState windowState) {
6790        return mForceShowSystemBars;
6791    }
6792
6793    @Override
6794    public boolean isDockSideAllowed(int dockSide) {
6795
6796        // We do not allow all dock sides at which the navigation bar touches the docked stack.
6797        if (!mNavigationBarCanMove) {
6798            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT;
6799        } else {
6800            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT;
6801        }
6802    }
6803
6804    void sendCloseSystemWindows() {
6805        PhoneWindow.sendCloseSystemWindows(mContext, null);
6806    }
6807
6808    void sendCloseSystemWindows(String reason) {
6809        PhoneWindow.sendCloseSystemWindows(mContext, reason);
6810    }
6811
6812    @Override
6813    public int rotationForOrientationLw(int orientation, int lastRotation) {
6814        if (false) {
6815            Slog.v(TAG, "rotationForOrientationLw(orient="
6816                        + orientation + ", last=" + lastRotation
6817                        + "); user=" + mUserRotation + " "
6818                        + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
6819                            ? "USER_ROTATION_LOCKED" : "")
6820                        );
6821        }
6822
6823        if (mForceDefaultOrientation) {
6824            return Surface.ROTATION_0;
6825        }
6826
6827        synchronized (mLock) {
6828            int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
6829            if (sensorRotation < 0) {
6830                sensorRotation = lastRotation;
6831            }
6832
6833            final int preferredRotation;
6834            if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
6835                // Ignore sensor when lid switch is open and rotation is forced.
6836                preferredRotation = mLidOpenRotation;
6837            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
6838                    && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
6839                // Ignore sensor when in car dock unless explicitly enabled.
6840                // This case can override the behavior of NOSENSOR, and can also
6841                // enable 180 degree rotation while docked.
6842                preferredRotation = mCarDockEnablesAccelerometer
6843                        ? sensorRotation : mCarDockRotation;
6844            } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
6845                    || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
6846                    || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
6847                    && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
6848                // Ignore sensor when in desk dock unless explicitly enabled.
6849                // This case can override the behavior of NOSENSOR, and can also
6850                // enable 180 degree rotation while docked.
6851                preferredRotation = mDeskDockEnablesAccelerometer
6852                        ? sensorRotation : mDeskDockRotation;
6853            } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
6854                // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
6855                // Note that the dock orientation overrides the HDMI orientation.
6856                preferredRotation = mDemoHdmiRotation;
6857            } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
6858                    && mUndockedHdmiRotation >= 0) {
6859                // Ignore sensor when plugged into HDMI and an undocked orientation has
6860                // been specified in the configuration (only for legacy devices without
6861                // full multi-display support).
6862                // Note that the dock orientation overrides the HDMI orientation.
6863                preferredRotation = mUndockedHdmiRotation;
6864            } else if (mDemoRotationLock) {
6865                // Ignore sensor when demo rotation lock is enabled.
6866                // Note that the dock orientation and HDMI rotation lock override this.
6867                preferredRotation = mDemoRotation;
6868            } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
6869                // Application just wants to remain locked in the last rotation.
6870                preferredRotation = lastRotation;
6871            } else if (!mSupportAutoRotation) {
6872                // If we don't support auto-rotation then bail out here and ignore
6873                // the sensor and any rotation lock settings.
6874                preferredRotation = -1;
6875            } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
6876                            && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
6877                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
6878                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
6879                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
6880                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
6881                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
6882                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6883                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
6884                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
6885                // Otherwise, use sensor only if requested by the application or enabled
6886                // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
6887                if (mAllowAllRotations < 0) {
6888                    // Can't read this during init() because the context doesn't
6889                    // have display metrics at that time so we cannot determine
6890                    // tablet vs. phone then.
6891                    mAllowAllRotations = mContext.getResources().getBoolean(
6892                            com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
6893                }
6894                if (sensorRotation != Surface.ROTATION_180
6895                        || mAllowAllRotations == 1
6896                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6897                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
6898                    preferredRotation = sensorRotation;
6899                } else {
6900                    preferredRotation = lastRotation;
6901                }
6902            } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
6903                    && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
6904                // Apply rotation lock.  Does not apply to NOSENSOR.
6905                // The idea is that the user rotation expresses a weak preference for the direction
6906                // of gravity and as NOSENSOR is never affected by gravity, then neither should
6907                // NOSENSOR be affected by rotation lock (although it will be affected by docks).
6908                preferredRotation = mUserRotation;
6909            } else {
6910                // No overriding preference.
6911                // We will do exactly what the application asked us to do.
6912                preferredRotation = -1;
6913            }
6914
6915            switch (orientation) {
6916                case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6917                    // Return portrait unless overridden.
6918                    if (isAnyPortrait(preferredRotation)) {
6919                        return preferredRotation;
6920                    }
6921                    return mPortraitRotation;
6922
6923                case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6924                    // Return landscape unless overridden.
6925                    if (isLandscapeOrSeascape(preferredRotation)) {
6926                        return preferredRotation;
6927                    }
6928                    return mLandscapeRotation;
6929
6930                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6931                    // Return reverse portrait unless overridden.
6932                    if (isAnyPortrait(preferredRotation)) {
6933                        return preferredRotation;
6934                    }
6935                    return mUpsideDownRotation;
6936
6937                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6938                    // Return seascape unless overridden.
6939                    if (isLandscapeOrSeascape(preferredRotation)) {
6940                        return preferredRotation;
6941                    }
6942                    return mSeascapeRotation;
6943
6944                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6945                case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
6946                    // Return either landscape rotation.
6947                    if (isLandscapeOrSeascape(preferredRotation)) {
6948                        return preferredRotation;
6949                    }
6950                    if (isLandscapeOrSeascape(lastRotation)) {
6951                        return lastRotation;
6952                    }
6953                    return mLandscapeRotation;
6954
6955                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6956                case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
6957                    // Return either portrait rotation.
6958                    if (isAnyPortrait(preferredRotation)) {
6959                        return preferredRotation;
6960                    }
6961                    if (isAnyPortrait(lastRotation)) {
6962                        return lastRotation;
6963                    }
6964                    return mPortraitRotation;
6965
6966                default:
6967                    // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
6968                    // just return the preferred orientation we already calculated.
6969                    if (preferredRotation >= 0) {
6970                        return preferredRotation;
6971                    }
6972                    return Surface.ROTATION_0;
6973            }
6974        }
6975    }
6976
6977    @Override
6978    public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
6979        switch (orientation) {
6980            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6981            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6982            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6983                return isAnyPortrait(rotation);
6984
6985            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6986            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6987            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6988                return isLandscapeOrSeascape(rotation);
6989
6990            default:
6991                return true;
6992        }
6993    }
6994
6995    @Override
6996    public void setRotationLw(int rotation) {
6997        mOrientationListener.setCurrentRotation(rotation);
6998    }
6999
7000    private boolean isLandscapeOrSeascape(int rotation) {
7001        return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
7002    }
7003
7004    private boolean isAnyPortrait(int rotation) {
7005        return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
7006    }
7007
7008    @Override
7009    public int getUserRotationMode() {
7010        return Settings.System.getIntForUser(mContext.getContentResolver(),
7011                Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
7012                        WindowManagerPolicy.USER_ROTATION_FREE :
7013                                WindowManagerPolicy.USER_ROTATION_LOCKED;
7014    }
7015
7016    // User rotation: to be used when all else fails in assigning an orientation to the device
7017    @Override
7018    public void setUserRotationMode(int mode, int rot) {
7019        ContentResolver res = mContext.getContentResolver();
7020
7021        // mUserRotationMode and mUserRotation will be assigned by the content observer
7022        if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
7023            Settings.System.putIntForUser(res,
7024                    Settings.System.USER_ROTATION,
7025                    rot,
7026                    UserHandle.USER_CURRENT);
7027            Settings.System.putIntForUser(res,
7028                    Settings.System.ACCELEROMETER_ROTATION,
7029                    0,
7030                    UserHandle.USER_CURRENT);
7031        } else {
7032            Settings.System.putIntForUser(res,
7033                    Settings.System.ACCELEROMETER_ROTATION,
7034                    1,
7035                    UserHandle.USER_CURRENT);
7036        }
7037    }
7038
7039    @Override
7040    public void setSafeMode(boolean safeMode) {
7041        mSafeMode = safeMode;
7042        performHapticFeedbackLw(null, safeMode
7043                ? HapticFeedbackConstants.SAFE_MODE_ENABLED
7044                : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
7045    }
7046
7047    static long[] getLongIntArray(Resources r, int resid) {
7048        int[] ar = r.getIntArray(resid);
7049        if (ar == null) {
7050            return null;
7051        }
7052        long[] out = new long[ar.length];
7053        for (int i=0; i<ar.length; i++) {
7054            out[i] = ar[i];
7055        }
7056        return out;
7057    }
7058
7059    /** {@inheritDoc} */
7060    @Override
7061    public void systemReady() {
7062        mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
7063                new StateCallback() {
7064                    @Override
7065                    public void onTrustedChanged() {
7066                        mWindowManagerFuncs.notifyKeyguardTrustedChanged();
7067                    }
7068                });
7069        mKeyguardDelegate.onSystemReady();
7070
7071        mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
7072        if (mVrManagerInternal != null) {
7073            mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
7074        }
7075
7076        readCameraLensCoverState();
7077        updateUiMode();
7078        boolean bindKeyguardNow;
7079        synchronized (mLock) {
7080            updateOrientationListenerLp();
7081            mSystemReady = true;
7082            mHandler.post(new Runnable() {
7083                @Override
7084                public void run() {
7085                    updateSettings();
7086                }
7087            });
7088
7089            bindKeyguardNow = mDeferBindKeyguard;
7090            if (bindKeyguardNow) {
7091                // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now.
7092                mDeferBindKeyguard = false;
7093            }
7094        }
7095
7096        if (bindKeyguardNow) {
7097            mKeyguardDelegate.bindService(mContext);
7098            mKeyguardDelegate.onBootCompleted();
7099        }
7100        mSystemGestures.systemReady();
7101        mImmersiveModeConfirmation.systemReady();
7102    }
7103
7104    /** {@inheritDoc} */
7105    @Override
7106    public void systemBooted() {
7107        boolean bindKeyguardNow = false;
7108        synchronized (mLock) {
7109            // Time to bind Keyguard; take care to only bind it once, either here if ready or
7110            // in systemReady if not.
7111            if (mKeyguardDelegate != null) {
7112                bindKeyguardNow = true;
7113            } else {
7114                // Because mKeyguardDelegate is null, we know that the synchronized block in
7115                // systemReady didn't run yet and setting this will actually have an effect.
7116                mDeferBindKeyguard = true;
7117            }
7118        }
7119        if (bindKeyguardNow) {
7120            mKeyguardDelegate.bindService(mContext);
7121            mKeyguardDelegate.onBootCompleted();
7122        }
7123        synchronized (mLock) {
7124            mSystemBooted = true;
7125        }
7126        startedWakingUp();
7127        screenTurningOn(null);
7128        screenTurnedOn();
7129    }
7130
7131    ProgressDialog mBootMsgDialog = null;
7132
7133    /** {@inheritDoc} */
7134    @Override
7135    public void showBootMessage(final CharSequence msg, final boolean always) {
7136        mHandler.post(new Runnable() {
7137            @Override public void run() {
7138                if (mBootMsgDialog == null) {
7139                    int theme;
7140                    if (mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK)) {
7141                        theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
7142                    } else {
7143                        theme = 0;
7144                    }
7145
7146                    mBootMsgDialog = new ProgressDialog(mContext, theme) {
7147                        // This dialog will consume all events coming in to
7148                        // it, to avoid it trying to do things too early in boot.
7149                        @Override public boolean dispatchKeyEvent(KeyEvent event) {
7150                            return true;
7151                        }
7152                        @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7153                            return true;
7154                        }
7155                        @Override public boolean dispatchTouchEvent(MotionEvent ev) {
7156                            return true;
7157                        }
7158                        @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
7159                            return true;
7160                        }
7161                        @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
7162                            return true;
7163                        }
7164                        @Override public boolean dispatchPopulateAccessibilityEvent(
7165                                AccessibilityEvent event) {
7166                            return true;
7167                        }
7168                    };
7169                    if (mContext.getPackageManager().isUpgrade()) {
7170                        mBootMsgDialog.setTitle(R.string.android_upgrading_title);
7171                    } else {
7172                        mBootMsgDialog.setTitle(R.string.android_start_title);
7173                    }
7174                    mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
7175                    mBootMsgDialog.setIndeterminate(true);
7176                    mBootMsgDialog.getWindow().setType(
7177                            WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
7178                    mBootMsgDialog.getWindow().addFlags(
7179                            WindowManager.LayoutParams.FLAG_DIM_BEHIND
7180                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
7181                    mBootMsgDialog.getWindow().setDimAmount(1);
7182                    WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
7183                    lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
7184                    mBootMsgDialog.getWindow().setAttributes(lp);
7185                    mBootMsgDialog.setCancelable(false);
7186                    mBootMsgDialog.show();
7187                }
7188                mBootMsgDialog.setMessage(msg);
7189            }
7190        });
7191    }
7192
7193    /** {@inheritDoc} */
7194    @Override
7195    public void hideBootMessages() {
7196        mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
7197    }
7198
7199    /** {@inheritDoc} */
7200    @Override
7201    public void userActivity() {
7202        // ***************************************
7203        // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
7204        // ***************************************
7205        // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
7206        // WITH ITS LOCKS HELD.
7207        //
7208        // This code must be VERY careful about the locks
7209        // it acquires.
7210        // In fact, the current code acquires way too many,
7211        // and probably has lurking deadlocks.
7212
7213        synchronized (mScreenLockTimeout) {
7214            if (mLockScreenTimerActive) {
7215                // reset the timer
7216                mHandler.removeCallbacks(mScreenLockTimeout);
7217                mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7218            }
7219        }
7220    }
7221
7222    class ScreenLockTimeout implements Runnable {
7223        Bundle options;
7224
7225        @Override
7226        public void run() {
7227            synchronized (this) {
7228                if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
7229                if (mKeyguardDelegate != null) {
7230                    mKeyguardDelegate.doKeyguardTimeout(options);
7231                }
7232                mLockScreenTimerActive = false;
7233                options = null;
7234            }
7235        }
7236
7237        public void setLockOptions(Bundle options) {
7238            this.options = options;
7239        }
7240    }
7241
7242    ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
7243
7244    @Override
7245    public void lockNow(Bundle options) {
7246        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
7247        mHandler.removeCallbacks(mScreenLockTimeout);
7248        if (options != null) {
7249            // In case multiple calls are made to lockNow, we don't wipe out the options
7250            // until the runnable actually executes.
7251            mScreenLockTimeout.setLockOptions(options);
7252        }
7253        mHandler.post(mScreenLockTimeout);
7254    }
7255
7256    private void updateLockScreenTimeout() {
7257        synchronized (mScreenLockTimeout) {
7258            boolean enable = (mAllowLockscreenWhenOn && mAwake &&
7259                    mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
7260            if (mLockScreenTimerActive != enable) {
7261                if (enable) {
7262                    if (localLOGV) Log.v(TAG, "setting lockscreen timer");
7263                    mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
7264                    mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7265                } else {
7266                    if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
7267                    mHandler.removeCallbacks(mScreenLockTimeout);
7268                }
7269                mLockScreenTimerActive = enable;
7270            }
7271        }
7272    }
7273
7274    private void updateDreamingSleepToken(boolean acquire) {
7275        if (acquire) {
7276            if (mDreamingSleepToken == null) {
7277                mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream");
7278            }
7279        } else {
7280            if (mDreamingSleepToken != null) {
7281                mDreamingSleepToken.release();
7282                mDreamingSleepToken = null;
7283            }
7284        }
7285    }
7286
7287    private void updateScreenOffSleepToken(boolean acquire) {
7288        if (acquire) {
7289            if (mScreenOffSleepToken == null) {
7290                mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff");
7291            }
7292        } else {
7293            if (mScreenOffSleepToken != null) {
7294                mScreenOffSleepToken.release();
7295                mScreenOffSleepToken = null;
7296            }
7297        }
7298    }
7299
7300    /** {@inheritDoc} */
7301    @Override
7302    public void enableScreenAfterBoot() {
7303        readLidState();
7304        applyLidSwitchState();
7305        updateRotation(true);
7306    }
7307
7308    private void applyLidSwitchState() {
7309        if (mLidState == LID_CLOSED && mLidControlsSleep) {
7310            mPowerManager.goToSleep(SystemClock.uptimeMillis(),
7311                    PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
7312                    PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
7313        } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
7314            mWindowManagerFuncs.lockDeviceNow();
7315        }
7316
7317        synchronized (mLock) {
7318            updateWakeGestureListenerLp();
7319        }
7320    }
7321
7322    void updateUiMode() {
7323        if (mUiModeManager == null) {
7324            mUiModeManager = IUiModeManager.Stub.asInterface(
7325                    ServiceManager.getService(Context.UI_MODE_SERVICE));
7326        }
7327        try {
7328            mUiMode = mUiModeManager.getCurrentModeType();
7329        } catch (RemoteException e) {
7330        }
7331    }
7332
7333    void updateRotation(boolean alwaysSendConfiguration) {
7334        try {
7335            //set orientation on WindowManager
7336            mWindowManager.updateRotation(alwaysSendConfiguration, false);
7337        } catch (RemoteException e) {
7338            // Ignore
7339        }
7340    }
7341
7342    void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
7343        try {
7344            //set orientation on WindowManager
7345            mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
7346        } catch (RemoteException e) {
7347            // Ignore
7348        }
7349    }
7350
7351    /**
7352     * Return an Intent to launch the currently active dock app as home.  Returns
7353     * null if the standard home should be launched, which is the case if any of the following is
7354     * true:
7355     * <ul>
7356     *  <li>The device is not in either car mode or desk mode
7357     *  <li>The device is in car mode but mEnableCarDockHomeCapture is false
7358     *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
7359     *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
7360     *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
7361     * </ul>
7362     * @return A dock intent.
7363     */
7364    Intent createHomeDockIntent() {
7365        Intent intent = null;
7366
7367        // What home does is based on the mode, not the dock state.  That
7368        // is, when in car mode you should be taken to car home regardless
7369        // of whether we are actually in a car dock.
7370        if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
7371            if (mEnableCarDockHomeCapture) {
7372                intent = mCarDockIntent;
7373            }
7374        } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
7375            if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
7376                intent = mDeskDockIntent;
7377            }
7378        } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
7379                && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7380                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
7381                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
7382            // Always launch dock home from home when watch is docked, if it exists.
7383            intent = mDeskDockIntent;
7384        } else if (mUiMode == Configuration.UI_MODE_TYPE_VR_HEADSET) {
7385            if (ENABLE_VR_HEADSET_HOME_CAPTURE) {
7386                intent = mVrHeadsetHomeIntent;
7387            }
7388        }
7389
7390        if (intent == null) {
7391            return null;
7392        }
7393
7394        ActivityInfo ai = null;
7395        ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
7396                intent,
7397                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
7398                mCurrentUserId);
7399        if (info != null) {
7400            ai = info.activityInfo;
7401        }
7402        if (ai != null
7403                && ai.metaData != null
7404                && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
7405            intent = new Intent(intent);
7406            intent.setClassName(ai.packageName, ai.name);
7407            return intent;
7408        }
7409
7410        return null;
7411    }
7412
7413    void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
7414        if (awakenFromDreams) {
7415            awakenDreams();
7416        }
7417
7418        Intent dock = createHomeDockIntent();
7419        if (dock != null) {
7420            try {
7421                if (fromHomeKey) {
7422                    dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7423                }
7424                startActivityAsUser(dock, UserHandle.CURRENT);
7425                return;
7426            } catch (ActivityNotFoundException e) {
7427            }
7428        }
7429
7430        Intent intent;
7431
7432        if (fromHomeKey) {
7433            intent = new Intent(mHomeIntent);
7434            intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7435        } else {
7436            intent = mHomeIntent;
7437        }
7438
7439        startActivityAsUser(intent, UserHandle.CURRENT);
7440    }
7441
7442    /**
7443     * goes to the home screen
7444     * @return whether it did anything
7445     */
7446    boolean goHome() {
7447        if (!isUserSetupComplete()) {
7448            Slog.i(TAG, "Not going home because user setup is in progress.");
7449            return false;
7450        }
7451        if (false) {
7452            // This code always brings home to the front.
7453            try {
7454                ActivityManager.getService().stopAppSwitches();
7455            } catch (RemoteException e) {
7456            }
7457            sendCloseSystemWindows();
7458            startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
7459        } else {
7460            // This code brings home to the front or, if it is already
7461            // at the front, puts the device to sleep.
7462            try {
7463                if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
7464                    /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
7465                    Log.d(TAG, "UTS-TEST-MODE");
7466                } else {
7467                    ActivityManager.getService().stopAppSwitches();
7468                    sendCloseSystemWindows();
7469                    Intent dock = createHomeDockIntent();
7470                    if (dock != null) {
7471                        int result = ActivityManager.getService()
7472                                .startActivityAsUser(null, null, dock,
7473                                        dock.resolveTypeIfNeeded(mContext.getContentResolver()),
7474                                        null, null, 0,
7475                                        ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7476                                        null, null, UserHandle.USER_CURRENT);
7477                        if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7478                            return false;
7479                        }
7480                    }
7481                }
7482                int result = ActivityManager.getService()
7483                        .startActivityAsUser(null, null, mHomeIntent,
7484                                mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
7485                                null, null, 0,
7486                                ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7487                                null, null, UserHandle.USER_CURRENT);
7488                if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7489                    return false;
7490                }
7491            } catch (RemoteException ex) {
7492                // bummer, the activity manager, which is in this process, is dead
7493            }
7494        }
7495        return true;
7496    }
7497
7498    @Override
7499    public void setCurrentOrientationLw(int newOrientation) {
7500        synchronized (mLock) {
7501            if (newOrientation != mCurrentAppOrientation) {
7502                mCurrentAppOrientation = newOrientation;
7503                updateOrientationListenerLp();
7504            }
7505        }
7506    }
7507
7508    private boolean isTheaterModeEnabled() {
7509        return Settings.Global.getInt(mContext.getContentResolver(),
7510                Settings.Global.THEATER_MODE_ON, 0) == 1;
7511    }
7512
7513    private boolean areSystemNavigationKeysEnabled() {
7514        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
7515                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
7516    }
7517
7518    @Override
7519    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
7520        if (!mVibrator.hasVibrator()) {
7521            return false;
7522        }
7523        final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
7524                Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
7525        if (hapticsDisabled && !always) {
7526            return false;
7527        }
7528
7529        VibrationEffect effect = getVibrationEffect(effectId);
7530        if (effect == null) {
7531            return false;
7532        }
7533
7534        int owningUid;
7535        String owningPackage;
7536        if (win != null) {
7537            owningUid = win.getOwningUid();
7538            owningPackage = win.getOwningPackage();
7539        } else {
7540            owningUid = android.os.Process.myUid();
7541            owningPackage = mContext.getOpPackageName();
7542        }
7543        mVibrator.vibrate(owningUid, owningPackage, effect, VIBRATION_ATTRIBUTES);
7544        return true;
7545    }
7546
7547    private VibrationEffect getVibrationEffect(int effectId) {
7548        long[] pattern;
7549        switch (effectId) {
7550            case HapticFeedbackConstants.VIRTUAL_KEY:
7551                return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
7552            case HapticFeedbackConstants.LONG_PRESS:
7553                pattern = mLongPressVibePattern;
7554                break;
7555            case HapticFeedbackConstants.KEYBOARD_TAP:
7556                return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
7557            case HapticFeedbackConstants.CLOCK_TICK:
7558                pattern = mClockTickVibePattern;
7559                break;
7560            case HapticFeedbackConstants.CALENDAR_DATE:
7561                pattern = mCalendarDateVibePattern;
7562                break;
7563            case HapticFeedbackConstants.SAFE_MODE_DISABLED:
7564                pattern = mSafeModeDisabledVibePattern;
7565                break;
7566            case HapticFeedbackConstants.SAFE_MODE_ENABLED:
7567                pattern = mSafeModeEnabledVibePattern;
7568                break;
7569            case HapticFeedbackConstants.CONTEXT_CLICK:
7570                pattern = mContextClickVibePattern;
7571                break;
7572            default:
7573                return null;
7574        }
7575        if (pattern.length == 1) {
7576            // One-shot vibration
7577            return VibrationEffect.createOneShot(pattern[0], VibrationEffect.DEFAULT_AMPLITUDE);
7578        } else {
7579            // Pattern vibration
7580            return VibrationEffect.createWaveform(pattern, -1);
7581        }
7582    }
7583
7584    @Override
7585    public void keepScreenOnStartedLw() {
7586    }
7587
7588    @Override
7589    public void keepScreenOnStoppedLw() {
7590        if (isKeyguardShowingAndNotOccluded()) {
7591            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
7592        }
7593    }
7594
7595    private int updateSystemUiVisibilityLw() {
7596        // If there is no window focused, there will be nobody to handle the events
7597        // anyway, so just hang on in whatever state we're in until things settle down.
7598        WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
7599                : mTopFullscreenOpaqueWindowState;
7600        if (winCandidate == null) {
7601            return 0;
7602        }
7603        if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
7604            // The immersive mode confirmation should never affect the system bar visibility,
7605            // otherwise it will unhide the navigation bar and hide itself.
7606            winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState;
7607            if (winCandidate == null) {
7608                return 0;
7609            }
7610        }
7611        final WindowState win = winCandidate;
7612        if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mKeyguardOccluded) {
7613            // We are updating at a point where the keyguard has gotten
7614            // focus, but we were last in a state where the top window is
7615            // hiding it.  This is probably because the keyguard as been
7616            // shown while the top window was displayed, so we want to ignore
7617            // it here because this is just a very transient change and it
7618            // will quickly lose focus once it correctly gets hidden.
7619            return 0;
7620        }
7621
7622        int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
7623                & ~mResettingSystemUiFlags
7624                & ~mForceClearedSystemUiFlags;
7625        if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
7626            tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
7627        }
7628
7629        final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
7630                mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
7631        final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
7632                mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
7633        mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);
7634        mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);
7635        final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
7636        final int diff = visibility ^ mLastSystemUiFlags;
7637        final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
7638        final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
7639        final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
7640        if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
7641                && mFocusedApp == win.getAppToken()
7642                && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
7643                && mLastDockedStackBounds.equals(mDockedStackBounds)) {
7644            return 0;
7645        }
7646        mLastSystemUiFlags = visibility;
7647        mLastFullscreenStackSysUiFlags = fullscreenVisibility;
7648        mLastDockedStackSysUiFlags = dockedVisibility;
7649        mLastFocusNeedsMenu = needsMenu;
7650        mFocusedApp = win.getAppToken();
7651        final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
7652        final Rect dockedStackBounds = new Rect(mDockedStackBounds);
7653        mHandler.post(new Runnable() {
7654                @Override
7655                public void run() {
7656                    StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
7657                    if (statusbar != null) {
7658                        statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
7659                                dockedVisibility, 0xffffffff, fullscreenStackBounds,
7660                                dockedStackBounds, win.toString());
7661                        statusbar.topAppWindowChanged(needsMenu);
7662                    }
7663                }
7664            });
7665        return diff;
7666    }
7667
7668    private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
7669        WindowState statusColorWin = isStatusBarKeyguard() && !mKeyguardOccluded
7670                ? mStatusBar
7671                : opaqueOrDimming;
7672
7673        if (statusColorWin != null) {
7674            if (statusColorWin == opaque) {
7675                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7676                // its light flag.
7677                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7678                vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
7679                        & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7680            } else if (statusColorWin != null && statusColorWin.isDimming()) {
7681                // Otherwise if it's dimming, clear the light flag.
7682                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7683            }
7684        }
7685        return vis;
7686    }
7687
7688    private int updateLightNavigationBarLw(int vis, WindowState opaque,
7689            WindowState opaqueOrDimming) {
7690        final WindowState imeWin = mWindowManagerFuncs.getInputMethodWindowLw();
7691
7692        final WindowState navColorWin;
7693        if (imeWin != null && imeWin.isVisibleLw()) {
7694            navColorWin = imeWin;
7695        } else {
7696            navColorWin = opaqueOrDimming;
7697        }
7698
7699        if (navColorWin != null) {
7700            if (navColorWin == opaque) {
7701                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7702                // its light flag.
7703                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7704                vis |= PolicyControl.getSystemUiVisibility(navColorWin, null)
7705                        & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7706            } else if (navColorWin.isDimming() || navColorWin == imeWin) {
7707                // Otherwise if it's dimming or it's the IME window, clear the light flag.
7708                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7709            }
7710        }
7711        return vis;
7712    }
7713
7714    private boolean drawsSystemBarBackground(WindowState win) {
7715        return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
7716    }
7717
7718    private boolean forcesDrawStatusBarBackground(WindowState win) {
7719        return win == null || (win.getAttrs().privateFlags
7720                & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
7721    }
7722
7723    private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
7724        final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
7725        final boolean freeformStackVisible =
7726                mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
7727        final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
7728
7729        // We need to force system bars when the docked stack is visible, when the freeform stack
7730        // is visible but also when we are resizing for the transitions when docked stack
7731        // visibility changes.
7732        mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
7733        final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
7734
7735        // apply translucent bar vis flags
7736        WindowState fullscreenTransWin = isStatusBarKeyguard() && !mKeyguardOccluded
7737                ? mStatusBar
7738                : mTopFullscreenOpaqueWindowState;
7739        vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7740        vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7741        final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
7742                mTopDockedOpaqueWindowState, 0, 0);
7743
7744        final boolean fullscreenDrawsStatusBarBackground =
7745                (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
7746                        && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
7747                || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
7748        final boolean dockedDrawsStatusBarBackground =
7749                (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
7750                        && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
7751                || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
7752
7753        // prevent status bar interaction from clearing certain flags
7754        int type = win.getAttrs().type;
7755        boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
7756        if (statusBarHasFocus && !isStatusBarKeyguard()) {
7757            int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
7758                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
7759                    | View.SYSTEM_UI_FLAG_IMMERSIVE
7760                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
7761                    | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7762            if (mKeyguardOccluded) {
7763                flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
7764            }
7765            vis = (vis & ~flags) | (oldVis & flags);
7766        }
7767
7768        if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
7769            vis |= View.STATUS_BAR_TRANSPARENT;
7770            vis &= ~View.STATUS_BAR_TRANSLUCENT;
7771        } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
7772                || forceOpaqueStatusBar) {
7773            vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
7774        }
7775
7776        vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
7777
7778        // update status bar
7779        boolean immersiveSticky =
7780                (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7781        final boolean hideStatusBarWM =
7782                mTopFullscreenOpaqueWindowState != null
7783                && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
7784                        & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
7785        final boolean hideStatusBarSysui =
7786                (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
7787        final boolean hideNavBarSysui =
7788                (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
7789
7790        final boolean transientStatusBarAllowed = mStatusBar != null
7791                && (statusBarHasFocus || (!mForceShowSystemBars
7792                        && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
7793
7794        final boolean transientNavBarAllowed = mNavigationBar != null
7795                && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
7796
7797        final long now = SystemClock.uptimeMillis();
7798        final boolean pendingPanic = mPendingPanicGestureUptime != 0
7799                && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
7800        if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
7801            // The user performed the panic gesture recently, we're about to hide the bars,
7802            // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
7803            mPendingPanicGestureUptime = 0;
7804            mStatusBarController.showTransient();
7805            if (!isNavBarEmpty(vis)) {
7806                mNavigationBarController.showTransient();
7807            }
7808        }
7809
7810        final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
7811                && !transientStatusBarAllowed && hideStatusBarSysui;
7812        final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
7813                && !transientNavBarAllowed;
7814        if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
7815            // clear the clearable flags instead
7816            clearClearableFlagsLw();
7817            vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
7818        }
7819
7820        final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
7821        immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7822        final boolean navAllowedHidden = immersive || immersiveSticky;
7823
7824        if (hideNavBarSysui && !navAllowedHidden
7825                && getWindowLayerLw(win) > getWindowLayerFromTypeLw(TYPE_INPUT_CONSUMER)) {
7826            // We can't hide the navbar from this window otherwise the input consumer would not get
7827            // the input events.
7828            vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
7829        }
7830
7831        vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
7832
7833        // update navigation bar
7834        boolean oldImmersiveMode = isImmersiveMode(oldVis);
7835        boolean newImmersiveMode = isImmersiveMode(vis);
7836        if (win != null && oldImmersiveMode != newImmersiveMode) {
7837            final String pkg = win.getOwningPackage();
7838            mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
7839                    isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility()));
7840        }
7841
7842        vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
7843
7844        vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState,
7845                mTopFullscreenOpaqueOrDimmingWindowState);
7846
7847        return vis;
7848    }
7849
7850    /**
7851     * @return the current visibility flags with the nav-bar opacity related flags toggled based
7852     *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
7853     */
7854    private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
7855            boolean freeformStackVisible, boolean isDockedDividerResizing) {
7856        if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
7857            if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
7858                visibility = setNavBarOpaqueFlag(visibility);
7859            }
7860        } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
7861            if (isDockedDividerResizing) {
7862                visibility = setNavBarOpaqueFlag(visibility);
7863            } else if (freeformStackVisible) {
7864                visibility = setNavBarTranslucentFlag(visibility);
7865            } else {
7866                visibility = setNavBarOpaqueFlag(visibility);
7867            }
7868        }
7869
7870        if (!areTranslucentBarsAllowed()) {
7871            visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
7872        }
7873        return visibility;
7874    }
7875
7876    private int setNavBarOpaqueFlag(int visibility) {
7877        return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
7878    }
7879
7880    private int setNavBarTranslucentFlag(int visibility) {
7881        visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
7882        return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
7883    }
7884
7885    private void clearClearableFlagsLw() {
7886        int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
7887        if (newVal != mResettingSystemUiFlags) {
7888            mResettingSystemUiFlags = newVal;
7889            mWindowManagerFuncs.reevaluateStatusBarVisibility();
7890        }
7891    }
7892
7893    private boolean isImmersiveMode(int vis) {
7894        final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
7895        return mNavigationBar != null
7896                && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
7897                && (vis & flags) != 0
7898                && canHideNavigationBar();
7899    }
7900
7901    private static boolean isNavBarEmpty(int systemUiFlags) {
7902        final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
7903                | View.STATUS_BAR_DISABLE_BACK
7904                | View.STATUS_BAR_DISABLE_RECENT);
7905
7906        return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
7907    }
7908
7909    /**
7910     * @return whether the navigation or status bar can be made translucent
7911     *
7912     * This should return true unless touch exploration is not enabled or
7913     * R.boolean.config_enableTranslucentDecor is false.
7914     */
7915    private boolean areTranslucentBarsAllowed() {
7916        return mTranslucentDecorEnabled;
7917    }
7918
7919    // Use this instead of checking config_showNavigationBar so that it can be consistently
7920    // overridden by qemu.hw.mainkeys in the emulator.
7921    @Override
7922    public boolean hasNavigationBar() {
7923        return mHasNavigationBar;
7924    }
7925
7926    @Override
7927    public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
7928        mLastInputMethodWindow = ime;
7929        mLastInputMethodTargetWindow = target;
7930    }
7931
7932    @Override
7933    public int getInputMethodWindowVisibleHeightLw() {
7934        return mDockBottom - mCurBottom;
7935    }
7936
7937    @Override
7938    public void setCurrentUserLw(int newUserId) {
7939        mCurrentUserId = newUserId;
7940        if (mKeyguardDelegate != null) {
7941            mKeyguardDelegate.setCurrentUser(newUserId);
7942        }
7943        if (mAccessibilityShortcutController != null) {
7944            mAccessibilityShortcutController.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