PhoneWindowManager.java revision 7121697a5e2d4458f6f63e9eb3b5deec62ee6202
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.speech.RecognizerIntent;
187import android.telecom.TelecomManager;
188import android.util.DisplayMetrics;
189import android.util.EventLog;
190import android.util.Log;
191import android.util.LongSparseArray;
192import android.util.MutableBoolean;
193import android.util.Slog;
194import android.util.SparseArray;
195import android.view.Display;
196import android.view.Gravity;
197import android.view.HapticFeedbackConstants;
198import android.view.IApplicationToken;
199import android.view.IWindowManager;
200import android.view.InputChannel;
201import android.view.InputDevice;
202import android.view.InputEvent;
203import android.view.InputEventReceiver;
204import android.view.KeyCharacterMap;
205import android.view.KeyCharacterMap.FallbackAction;
206import android.view.KeyEvent;
207import android.view.MotionEvent;
208import android.view.PointerIcon;
209import android.view.Surface;
210import android.view.View;
211import android.view.ViewConfiguration;
212import android.view.WindowManager;
213import android.view.WindowManager.LayoutParams;
214import android.view.WindowManagerGlobal;
215import android.view.WindowManagerInternal;
216import android.view.WindowManagerInternal.AppTransitionListener;
217import android.view.WindowManagerPolicy;
218import android.view.accessibility.AccessibilityEvent;
219import android.view.accessibility.AccessibilityManager;
220import android.view.animation.Animation;
221import android.view.animation.AnimationSet;
222import android.view.animation.AnimationUtils;
223
224import com.android.internal.R;
225import com.android.internal.logging.MetricsLogger;
226import com.android.internal.policy.IKeyguardDismissCallback;
227import com.android.internal.policy.IShortcutService;
228import com.android.internal.policy.PhoneWindow;
229import com.android.internal.statusbar.IStatusBarService;
230import com.android.internal.util.ScreenShapeHelper;
231import com.android.internal.widget.PointerLocationView;
232import com.android.server.GestureLauncherService;
233import com.android.server.LocalServices;
234import com.android.server.policy.keyguard.KeyguardServiceDelegate;
235import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener;
236import com.android.server.policy.keyguard.KeyguardStateMonitor.StateCallback;
237import com.android.server.statusbar.StatusBarManagerInternal;
238import com.android.server.wm.AppTransition;
239import com.android.server.vr.VrManagerInternal;
240import com.android.server.vr.PersistentVrStateListener;
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_RECENT_SYSTEM_UI = 1;
302    static final int LONG_PRESS_HOME_ASSIST = 2;
303    static final int LAST_LONG_PRESS_HOME_BEHAVIOR = LONG_PRESS_HOME_ASSIST;
304
305    static final int DOUBLE_TAP_HOME_NOTHING = 0;
306    static final int DOUBLE_TAP_HOME_RECENT_SYSTEM_UI = 1;
307
308    static final int SHORT_PRESS_WINDOW_NOTHING = 0;
309    static final int SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE = 1;
310
311    static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP = 0;
312    static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME = 1;
313
314    static final int PENDING_KEY_NULL = -1;
315
316    // Controls navigation bar opacity depending on which workspace stacks are currently
317    // visible.
318    // Nav bar is always opaque when either the freeform stack or docked stack is visible.
319    static final int NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED = 0;
320    // Nav bar is always translucent when the freeform stack is visible, otherwise always opaque.
321    static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1;
322
323    static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
324    static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
325    static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
326    static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
327    static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";
328
329    /**
330     * These are the system UI flags that, when changing, can cause the layout
331     * of the screen to change.
332     */
333    static final int SYSTEM_UI_CHANGING_LAYOUT =
334              View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
335            | View.SYSTEM_UI_FLAG_FULLSCREEN
336            | View.STATUS_BAR_TRANSLUCENT
337            | View.NAVIGATION_BAR_TRANSLUCENT
338            | View.STATUS_BAR_TRANSPARENT
339            | View.NAVIGATION_BAR_TRANSPARENT;
340
341    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
342            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
343            .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
344            .build();
345
346    // The panic gesture may become active only after the keyguard is dismissed and the immersive
347    // app shows again. If that doesn't happen for 30s we drop the gesture.
348    private static final long PANIC_GESTURE_EXPIRATION = 30000;
349
350    private static final String SYSUI_PACKAGE = "com.android.systemui";
351    private static final String SYSUI_SCREENSHOT_SERVICE =
352            "com.android.systemui.screenshot.TakeScreenshotService";
353    private static final String SYSUI_SCREENSHOT_ERROR_RECEIVER =
354            "com.android.systemui.screenshot.ScreenshotServiceErrorReceiver";
355
356    private static final int NAV_BAR_BOTTOM = 0;
357    private static final int NAV_BAR_RIGHT = 1;
358    private static final int NAV_BAR_LEFT = 2;
359
360    /**
361     * Keyguard stuff
362     */
363    private boolean mKeyguardDrawnOnce;
364
365    /* Table of Application Launch keys.  Maps from key codes to intent categories.
366     *
367     * These are special keys that are used to launch particular kinds of applications,
368     * such as a web browser.  HID defines nearly a hundred of them in the Consumer (0x0C)
369     * usage page.  We don't support quite that many yet...
370     */
371    static SparseArray<String> sApplicationLaunchKeyCategories;
372    static {
373        sApplicationLaunchKeyCategories = new SparseArray<String>();
374        sApplicationLaunchKeyCategories.append(
375                KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER);
376        sApplicationLaunchKeyCategories.append(
377                KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL);
378        sApplicationLaunchKeyCategories.append(
379                KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS);
380        sApplicationLaunchKeyCategories.append(
381                KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR);
382        sApplicationLaunchKeyCategories.append(
383                KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC);
384        sApplicationLaunchKeyCategories.append(
385                KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
386    }
387
388    /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
389    static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;
390
391    /** Amount of time (in milliseconds) a toast window can be shown. */
392    public static final int TOAST_WINDOW_TIMEOUT = 3500; // 3.5 seconds
393
394    /**
395     * Lock protecting internal state.  Must not call out into window
396     * manager with lock held.  (This lock will be acquired in places
397     * where the window manager is calling in with its own lock held.)
398     */
399    private final Object mLock = new Object();
400
401    Context mContext;
402    IWindowManager mWindowManager;
403    WindowManagerFuncs mWindowManagerFuncs;
404    WindowManagerInternal mWindowManagerInternal;
405    PowerManager mPowerManager;
406    ActivityManagerInternal mActivityManagerInternal;
407    InputManagerInternal mInputManagerInternal;
408    DreamManagerInternal mDreamManagerInternal;
409    PowerManagerInternal mPowerManagerInternal;
410    IStatusBarService mStatusBarService;
411    StatusBarManagerInternal mStatusBarManagerInternal;
412    boolean mPreloadedRecentApps;
413    final Object mServiceAquireLock = new Object();
414    Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
415    SearchManager mSearchManager;
416    AccessibilityManager mAccessibilityManager;
417    BurnInProtectionHelper mBurnInProtectionHelper;
418    AppOpsManager mAppOpsManager;
419    private boolean mHasFeatureWatch;
420    private boolean mHasFeatureLeanback;
421
422    // Assigned on main thread, accessed on UI thread
423    volatile VrManagerInternal mVrManagerInternal;
424
425    // Vibrator pattern for haptic feedback of a long press.
426    long[] mLongPressVibePattern;
427
428    // Vibrator pattern for haptic feedback of virtual key press.
429    long[] mVirtualKeyVibePattern;
430
431    // Vibrator pattern for a short vibration.
432    long[] mKeyboardTapVibePattern;
433
434    // Vibrator pattern for a short vibration when tapping on an hour/minute tick of a Clock.
435    long[] mClockTickVibePattern;
436
437    // Vibrator pattern for a short vibration when tapping on a day/month/year date of a Calendar.
438    long[] mCalendarDateVibePattern;
439
440    // Vibrator pattern for haptic feedback during boot when safe mode is disabled.
441    long[] mSafeModeDisabledVibePattern;
442
443    // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
444    long[] mSafeModeEnabledVibePattern;
445
446    // Vibrator pattern for haptic feedback of a context click.
447    long[] mContextClickVibePattern;
448
449    /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
450    boolean mEnableShiftMenuBugReports = false;
451
452    /** Controller that supports enabling an AccessibilityService by holding down the volume keys */
453    private AccessibilityShortcutController mAccessibilityShortcutController;
454
455    boolean mSafeMode;
456    WindowState mStatusBar = null;
457    int mStatusBarHeight;
458    WindowState mNavigationBar = null;
459    boolean mHasNavigationBar = false;
460    boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?
461    int mNavigationBarPosition = NAV_BAR_BOTTOM;
462    int[] mNavigationBarHeightForRotationDefault = new int[4];
463    int[] mNavigationBarWidthForRotationDefault = new int[4];
464    int[] mNavigationBarHeightForRotationInCarMode = new int[4];
465    int[] mNavigationBarWidthForRotationInCarMode = new int[4];
466
467    private LongSparseArray<IShortcutService> mShortcutKeyServices = new LongSparseArray<>();
468
469    // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
470    // This is for car dock and this is updated from resource.
471    private boolean mEnableCarDockHomeCapture = true;
472
473    boolean mBootMessageNeedsHiding;
474    KeyguardServiceDelegate mKeyguardDelegate;
475    final Runnable mWindowManagerDrawCallback = new Runnable() {
476        @Override
477        public void run() {
478            if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!");
479            mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);
480        }
481    };
482    final DrawnListener mKeyguardDrawnCallback = new DrawnListener() {
483        @Override
484        public void onDrawn() {
485            if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn.");
486            mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
487        }
488    };
489
490    GlobalActions mGlobalActions;
491    Handler mHandler;
492    WindowState mLastInputMethodWindow = null;
493    WindowState mLastInputMethodTargetWindow = null;
494
495    // FIXME This state is shared between the input reader and handler thread.
496    // Technically it's broken and buggy but it has been like this for many years
497    // and we have not yet seen any problems.  Someday we'll rewrite this logic
498    // so that only one thread is involved in handling input policy.  Unfortunately
499    // it's on a critical path for power management so we can't just post the work to the
500    // handler thread.  We'll need to resolve this someday by teaching the input dispatcher
501    // to hold wakelocks during dispatch and eliminating the critical path.
502    volatile boolean mPowerKeyHandled;
503    volatile boolean mBackKeyHandled;
504    volatile boolean mBeganFromNonInteractive;
505    volatile int mPowerKeyPressCounter;
506    volatile int mBackKeyPressCounter;
507    volatile boolean mEndCallKeyHandled;
508    volatile boolean mCameraGestureTriggeredDuringGoingToSleep;
509    volatile boolean mGoingToSleep;
510    volatile boolean mRecentsVisible;
511    volatile boolean mTvPictureInPictureVisible;
512    // Written by vr manager thread, only read in this class
513    volatile boolean mPersistentVrModeEnabled;
514
515    // Used to hold the last user key used to wake the device.  This helps us prevent up events
516    // from being passed to the foregrounded app without a corresponding down event
517    volatile int mPendingWakeKey = PENDING_KEY_NULL;
518
519    int mRecentAppsHeldModifiers;
520    boolean mLanguageSwitchKeyPressed;
521
522    int mLidState = LID_ABSENT;
523    int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT;
524    boolean mHaveBuiltInKeyboard;
525
526    boolean mSystemReady;
527    boolean mSystemBooted;
528    private boolean mDeferBindKeyguard;
529    boolean mHdmiPlugged;
530    HdmiControl mHdmiControl;
531    IUiModeManager mUiModeManager;
532    int mUiMode;
533    int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
534    int mLidOpenRotation;
535    int mCarDockRotation;
536    int mDeskDockRotation;
537    int mUndockedHdmiRotation;
538    int mDemoHdmiRotation;
539    boolean mDemoHdmiRotationLock;
540    int mDemoRotation;
541    boolean mDemoRotationLock;
542
543    boolean mWakeGestureEnabledSetting;
544    MyWakeGestureListener mWakeGestureListener;
545
546    // Default display does not rotate, apps that require non-default orientation will have to
547    // have the orientation emulated.
548    private boolean mForceDefaultOrientation = false;
549
550    int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
551    int mUserRotation = Surface.ROTATION_0;
552    boolean mAccelerometerDefault;
553
554    boolean mSupportAutoRotation;
555    int mAllowAllRotations = -1;
556    boolean mCarDockEnablesAccelerometer;
557    boolean mDeskDockEnablesAccelerometer;
558    int mLidKeyboardAccessibility;
559    int mLidNavigationAccessibility;
560    boolean mLidControlsScreenLock;
561    boolean mLidControlsSleep;
562    int mShortPressOnPowerBehavior;
563    int mLongPressOnPowerBehavior;
564    int mDoublePressOnPowerBehavior;
565    int mTriplePressOnPowerBehavior;
566    int mLongPressOnBackBehavior;
567    int mPanicPressOnBackBehavior;
568    int mShortPressOnSleepBehavior;
569    int mShortPressWindowBehavior;
570    boolean mAwake;
571    boolean mScreenOnEarly;
572    boolean mScreenOnFully;
573    ScreenOnListener mScreenOnListener;
574    boolean mKeyguardDrawComplete;
575    boolean mWindowManagerDrawComplete;
576    boolean mOrientationSensorEnabled = false;
577    int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
578    boolean mHasSoftInput = false;
579    boolean mTranslucentDecorEnabled = true;
580    boolean mUseTvRouting;
581
582    int mPointerLocationMode = 0; // guarded by mLock
583
584    // The last window we were told about in focusChanged.
585    WindowState mFocusedWindow;
586    IApplicationToken mFocusedApp;
587
588    PointerLocationView mPointerLocationView;
589
590    // The current size of the screen; really; extends into the overscan area of
591    // the screen and doesn't account for any system elements like the status bar.
592    int mOverscanScreenLeft, mOverscanScreenTop;
593    int mOverscanScreenWidth, mOverscanScreenHeight;
594    // The current visible size of the screen; really; (ir)regardless of whether the status
595    // bar can be hidden but not extending into the overscan area.
596    int mUnrestrictedScreenLeft, mUnrestrictedScreenTop;
597    int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight;
598    // Like mOverscanScreen*, but allowed to move into the overscan region where appropriate.
599    int mRestrictedOverscanScreenLeft, mRestrictedOverscanScreenTop;
600    int mRestrictedOverscanScreenWidth, mRestrictedOverscanScreenHeight;
601    // The current size of the screen; these may be different than (0,0)-(dw,dh)
602    // if the status bar can't be hidden; in that case it effectively carves out
603    // that area of the display from all other windows.
604    int mRestrictedScreenLeft, mRestrictedScreenTop;
605    int mRestrictedScreenWidth, mRestrictedScreenHeight;
606    // During layout, the current screen borders accounting for any currently
607    // visible system UI elements.
608    int mSystemLeft, mSystemTop, mSystemRight, mSystemBottom;
609    // For applications requesting stable content insets, these are them.
610    int mStableLeft, mStableTop, mStableRight, mStableBottom;
611    // For applications requesting stable content insets but have also set the
612    // fullscreen window flag, these are the stable dimensions without the status bar.
613    int mStableFullscreenLeft, mStableFullscreenTop;
614    int mStableFullscreenRight, mStableFullscreenBottom;
615    // During layout, the current screen borders with all outer decoration
616    // (status bar, input method dock) accounted for.
617    int mCurLeft, mCurTop, mCurRight, mCurBottom;
618    // During layout, the frame in which content should be displayed
619    // to the user, accounting for all screen decoration except for any
620    // space they deem as available for other content.  This is usually
621    // the same as mCur*, but may be larger if the screen decor has supplied
622    // content insets.
623    int mContentLeft, mContentTop, mContentRight, mContentBottom;
624    // During layout, the frame in which voice content should be displayed
625    // to the user, accounting for all screen decoration except for any
626    // space they deem as available for other content.
627    int mVoiceContentLeft, mVoiceContentTop, mVoiceContentRight, mVoiceContentBottom;
628    // During layout, the current screen borders along which input method
629    // windows are placed.
630    int mDockLeft, mDockTop, mDockRight, mDockBottom;
631    // During layout, the layer at which the doc window is placed.
632    int mDockLayer;
633    // During layout, this is the layer of the status bar.
634    int mStatusBarLayer;
635    int mLastSystemUiFlags;
636    // Bits that we are in the process of clearing, so we want to prevent
637    // them from being set by applications until everything has been updated
638    // to have them clear.
639    int mResettingSystemUiFlags = 0;
640    // Bits that we are currently always keeping cleared.
641    int mForceClearedSystemUiFlags = 0;
642    int mLastFullscreenStackSysUiFlags;
643    int mLastDockedStackSysUiFlags;
644    final Rect mNonDockedStackBounds = new Rect();
645    final Rect mDockedStackBounds = new Rect();
646    final Rect mLastNonDockedStackBounds = new Rect();
647    final Rect mLastDockedStackBounds = new Rect();
648
649    // What we last reported to system UI about whether the compatibility
650    // menu needs to be displayed.
651    boolean mLastFocusNeedsMenu = false;
652    // If nonzero, a panic gesture was performed at that time in uptime millis and is still pending.
653    private long mPendingPanicGestureUptime;
654
655    InputConsumer mInputConsumer = null;
656
657    static final Rect mTmpParentFrame = new Rect();
658    static final Rect mTmpDisplayFrame = new Rect();
659    static final Rect mTmpOverscanFrame = new Rect();
660    static final Rect mTmpContentFrame = new Rect();
661    static final Rect mTmpVisibleFrame = new Rect();
662    static final Rect mTmpDecorFrame = new Rect();
663    static final Rect mTmpStableFrame = new Rect();
664    static final Rect mTmpNavigationFrame = new Rect();
665    static final Rect mTmpOutsetFrame = new Rect();
666    private static final Rect mTmpRect = new Rect();
667
668    WindowState mTopFullscreenOpaqueWindowState;
669    WindowState mTopFullscreenOpaqueOrDimmingWindowState;
670    WindowState mTopDockedOpaqueWindowState;
671    WindowState mTopDockedOpaqueOrDimmingWindowState;
672    boolean mTopIsFullscreen;
673    boolean mForceStatusBar;
674    boolean mForceStatusBarFromKeyguard;
675    private boolean mForceStatusBarTransparent;
676    int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
677    boolean mForcingShowNavBar;
678    int mForcingShowNavBarLayer;
679
680    private boolean mPendingKeyguardOccluded;
681    private boolean mKeyguardOccludedChanged;
682
683    boolean mShowingDream;
684    private boolean mLastShowingDream;
685    boolean mDreamingLockscreen;
686    boolean mDreamingSleepTokenNeeded;
687    SleepToken mDreamingSleepToken;
688    SleepToken mScreenOffSleepToken;
689    volatile boolean mKeyguardOccluded;
690    boolean mHomePressed;
691    boolean mHomeConsumed;
692    boolean mHomeDoubleTapPending;
693    Intent mHomeIntent;
694    Intent mCarDockIntent;
695    Intent mDeskDockIntent;
696    Intent mVrHeadsetHomeIntent;
697    boolean mSearchKeyShortcutPending;
698    boolean mConsumeSearchKeyUp;
699    boolean mAssistKeyLongPressed;
700    boolean mPendingMetaAction;
701    boolean mPendingCapsLockToggle;
702    int mMetaState;
703    int mInitialMetaState;
704    boolean mForceShowSystemBars;
705
706    // support for activating the lock screen while the screen is on
707    boolean mAllowLockscreenWhenOn;
708    int mLockScreenTimeout;
709    boolean mLockScreenTimerActive;
710
711    // Behavior of ENDCALL Button.  (See Settings.System.END_BUTTON_BEHAVIOR.)
712    int mEndcallBehavior;
713
714    // Behavior of POWER button while in-call and screen on.
715    // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
716    int mIncallPowerBehavior;
717
718    // Behavior of Back button while in-call and screen on
719    int mIncallBackBehavior;
720
721    Display mDisplay;
722
723    private int mDisplayRotation;
724
725    int mLandscapeRotation = 0;  // default landscape rotation
726    int mSeascapeRotation = 0;   // "other" landscape rotation, 180 degrees from mLandscapeRotation
727    int mPortraitRotation = 0;   // default portrait rotation
728    int mUpsideDownRotation = 0; // "other" portrait rotation
729
730    int mOverscanLeft = 0;
731    int mOverscanTop = 0;
732    int mOverscanRight = 0;
733    int mOverscanBottom = 0;
734
735    // What we do when the user long presses on home
736    private int mLongPressOnHomeBehavior;
737
738    // What we do when the user double-taps on home
739    private int mDoubleTapOnHomeBehavior;
740
741    // Allowed theater mode wake actions
742    private boolean mAllowTheaterModeWakeFromKey;
743    private boolean mAllowTheaterModeWakeFromPowerKey;
744    private boolean mAllowTheaterModeWakeFromMotion;
745    private boolean mAllowTheaterModeWakeFromMotionWhenNotDreaming;
746    private boolean mAllowTheaterModeWakeFromCameraLens;
747    private boolean mAllowTheaterModeWakeFromLidSwitch;
748    private boolean mAllowTheaterModeWakeFromWakeGesture;
749
750    // Whether to support long press from power button in non-interactive mode
751    private boolean mSupportLongPressPowerWhenNonInteractive;
752
753    // Whether to go to sleep entering theater mode from power button
754    private boolean mGoToSleepOnButtonPressTheaterMode;
755
756    // Screenshot trigger states
757    // Time to volume and power must be pressed within this interval of each other.
758    private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
759    // Increase the chord delay when taking a screenshot from the keyguard
760    private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f;
761    private boolean mScreenshotChordEnabled;
762    private boolean mScreenshotChordVolumeDownKeyTriggered;
763    private long mScreenshotChordVolumeDownKeyTime;
764    private boolean mScreenshotChordVolumeDownKeyConsumed;
765    private boolean mA11yShortcutChordVolumeUpKeyTriggered;
766    private long mA11yShortcutChordVolumeUpKeyTime;
767    private boolean mA11yShortcutChordVolumeUpKeyConsumed;
768
769    private boolean mScreenshotChordPowerKeyTriggered;
770    private long mScreenshotChordPowerKeyTime;
771
772    private static final long BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS = 1000;
773
774    private boolean mBugreportTvKey1Pressed;
775    private boolean mBugreportTvKey2Pressed;
776    private boolean mBugreportTvScheduled;
777
778    /* The number of steps between min and max brightness */
779    private static final int BRIGHTNESS_STEPS = 10;
780
781    SettingsObserver mSettingsObserver;
782    ShortcutManager mShortcutManager;
783    PowerManager.WakeLock mBroadcastWakeLock;
784    PowerManager.WakeLock mPowerKeyWakeLock;
785    boolean mHavePendingMediaKeyRepeatWithWakeLock;
786
787    private int mCurrentUserId;
788
789    // Maps global key codes to the components that will handle them.
790    private GlobalKeyManager mGlobalKeyManager;
791
792    // Fallback actions by key code.
793    private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions =
794            new SparseArray<KeyCharacterMap.FallbackAction>();
795
796    private final LogDecelerateInterpolator mLogDecelerateInterpolator
797            = new LogDecelerateInterpolator(100, 0);
798
799    private final MutableBoolean mTmpBoolean = new MutableBoolean(false);
800
801    private static final int MSG_ENABLE_POINTER_LOCATION = 1;
802    private static final int MSG_DISABLE_POINTER_LOCATION = 2;
803    private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
804    private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
805    private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
806    private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6;
807    private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7;
808    private static final int MSG_DISPATCH_SHOW_RECENTS = 9;
809    private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10;
810    private static final int MSG_HIDE_BOOT_MESSAGE = 11;
811    private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12;
812    private static final int MSG_POWER_DELAYED_PRESS = 13;
813    private static final int MSG_POWER_LONG_PRESS = 14;
814    private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 15;
815    private static final int MSG_REQUEST_TRANSIENT_BARS = 16;
816    private static final int MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU = 17;
817    private static final int MSG_BACK_LONG_PRESS = 18;
818    private static final int MSG_DISPOSE_INPUT_CONSUMER = 19;
819    private static final int MSG_BACK_DELAYED_PRESS = 20;
820    private static final int MSG_ACCESSIBILITY_SHORTCUT = 21;
821    private static final int MSG_BUGREPORT_TV = 22;
822
823    private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
824    private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
825
826    private class PolicyHandler extends Handler {
827        @Override
828        public void handleMessage(Message msg) {
829            switch (msg.what) {
830                case MSG_ENABLE_POINTER_LOCATION:
831                    enablePointerLocation();
832                    break;
833                case MSG_DISABLE_POINTER_LOCATION:
834                    disablePointerLocation();
835                    break;
836                case MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK:
837                    dispatchMediaKeyWithWakeLock((KeyEvent)msg.obj);
838                    break;
839                case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK:
840                    dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj);
841                    break;
842                case MSG_DISPATCH_SHOW_RECENTS:
843                    showRecentApps(false, msg.arg1 != 0);
844                    break;
845                case MSG_DISPATCH_SHOW_GLOBAL_ACTIONS:
846                    showGlobalActionsInternal();
847                    break;
848                case MSG_KEYGUARD_DRAWN_COMPLETE:
849                    if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete");
850                    finishKeyguardDrawn();
851                    break;
852                case MSG_KEYGUARD_DRAWN_TIMEOUT:
853                    Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete");
854                    finishKeyguardDrawn();
855                    break;
856                case MSG_WINDOW_MANAGER_DRAWN_COMPLETE:
857                    if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete");
858                    finishWindowsDrawn();
859                    break;
860                case MSG_HIDE_BOOT_MESSAGE:
861                    handleHideBootMessage();
862                    break;
863                case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK:
864                    launchVoiceAssistWithWakeLock(msg.arg1 != 0);
865                    break;
866                case MSG_POWER_DELAYED_PRESS:
867                    powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2);
868                    finishPowerKeyPress();
869                    break;
870                case MSG_POWER_LONG_PRESS:
871                    powerLongPress();
872                    break;
873                case MSG_UPDATE_DREAMING_SLEEP_TOKEN:
874                    updateDreamingSleepToken(msg.arg1 != 0);
875                    break;
876                case MSG_REQUEST_TRANSIENT_BARS:
877                    WindowState targetBar = (msg.arg1 == MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS) ?
878                            mStatusBar : mNavigationBar;
879                    if (targetBar != null) {
880                        requestTransientBars(targetBar);
881                    }
882                    break;
883                case MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU:
884                    showTvPictureInPictureMenuInternal();
885                    break;
886                case MSG_BACK_LONG_PRESS:
887                    backLongPress();
888                    finishBackKeyPress();
889                    break;
890                case MSG_DISPOSE_INPUT_CONSUMER:
891                    disposeInputConsumer((InputConsumer) msg.obj);
892                    break;
893                case MSG_BACK_DELAYED_PRESS:
894                    backMultiPressAction((Long) msg.obj, msg.arg1);
895                    finishBackKeyPress();
896                    break;
897                case MSG_ACCESSIBILITY_SHORTCUT:
898                    accessibilityShortcutActivated();
899                    break;
900                case MSG_BUGREPORT_TV:
901                    takeBugreport();
902                    break;
903            }
904        }
905    }
906
907    private UEventObserver mHDMIObserver = new UEventObserver() {
908        @Override
909        public void onUEvent(UEventObserver.UEvent event) {
910            setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
911        }
912    };
913
914    class SettingsObserver extends ContentObserver {
915        SettingsObserver(Handler handler) {
916            super(handler);
917        }
918
919        void observe() {
920            // Observe all users' changes
921            ContentResolver resolver = mContext.getContentResolver();
922            resolver.registerContentObserver(Settings.System.getUriFor(
923                    Settings.System.END_BUTTON_BEHAVIOR), false, this,
924                    UserHandle.USER_ALL);
925            resolver.registerContentObserver(Settings.Secure.getUriFor(
926                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this,
927                    UserHandle.USER_ALL);
928            resolver.registerContentObserver(Settings.Secure.getUriFor(
929                    Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR), false, this,
930                    UserHandle.USER_ALL);
931            resolver.registerContentObserver(Settings.Secure.getUriFor(
932                    Settings.Secure.WAKE_GESTURE_ENABLED), false, this,
933                    UserHandle.USER_ALL);
934            resolver.registerContentObserver(Settings.System.getUriFor(
935                    Settings.System.ACCELEROMETER_ROTATION), false, this,
936                    UserHandle.USER_ALL);
937            resolver.registerContentObserver(Settings.System.getUriFor(
938                    Settings.System.USER_ROTATION), false, this,
939                    UserHandle.USER_ALL);
940            resolver.registerContentObserver(Settings.System.getUriFor(
941                    Settings.System.SCREEN_OFF_TIMEOUT), false, this,
942                    UserHandle.USER_ALL);
943            resolver.registerContentObserver(Settings.System.getUriFor(
944                    Settings.System.POINTER_LOCATION), false, this,
945                    UserHandle.USER_ALL);
946            resolver.registerContentObserver(Settings.Secure.getUriFor(
947                    Settings.Secure.DEFAULT_INPUT_METHOD), false, this,
948                    UserHandle.USER_ALL);
949            resolver.registerContentObserver(Settings.Secure.getUriFor(
950                    Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this,
951                    UserHandle.USER_ALL);
952            resolver.registerContentObserver(Settings.Global.getUriFor(
953                    Settings.Global.POLICY_CONTROL), false, this,
954                    UserHandle.USER_ALL);
955            updateSettings();
956        }
957
958        @Override public void onChange(boolean selfChange) {
959            updateSettings();
960            updateRotation(false);
961        }
962    }
963
964    class MyWakeGestureListener extends WakeGestureListener {
965        MyWakeGestureListener(Context context, Handler handler) {
966            super(context, handler);
967        }
968
969        @Override
970        public void onWakeUp() {
971            synchronized (mLock) {
972                if (shouldEnableWakeGestureLp()) {
973                    performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
974                    wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture,
975                            "android.policy:GESTURE");
976                }
977            }
978        }
979    }
980
981    class MyOrientationListener extends WindowOrientationListener {
982        private final Runnable mUpdateRotationRunnable = new Runnable() {
983            @Override
984            public void run() {
985                // send interaction hint to improve redraw performance
986                mPowerManagerInternal.powerHint(PowerHint.INTERACTION, 0);
987                updateRotation(false);
988            }
989        };
990
991        MyOrientationListener(Context context, Handler handler) {
992            super(context, handler);
993        }
994
995        @Override
996        public void onProposedRotationChanged(int rotation) {
997            if (localLOGV) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
998            mHandler.post(mUpdateRotationRunnable);
999        }
1000    }
1001    MyOrientationListener mOrientationListener;
1002
1003    final PersistentVrStateListener mPersistentVrModeListener =
1004            new PersistentVrStateListener() {
1005        @Override
1006        public void onPersistentVrStateChanged(boolean enabled) {
1007            mPersistentVrModeEnabled = enabled;
1008        }
1009    };
1010
1011    private final StatusBarController mStatusBarController = new StatusBarController();
1012
1013    private final BarController mNavigationBarController = new BarController("NavigationBar",
1014            View.NAVIGATION_BAR_TRANSIENT,
1015            View.NAVIGATION_BAR_UNHIDE,
1016            View.NAVIGATION_BAR_TRANSLUCENT,
1017            StatusBarManager.WINDOW_NAVIGATION_BAR,
1018            WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
1019            View.NAVIGATION_BAR_TRANSPARENT);
1020
1021    private final BarController.OnBarVisibilityChangedListener mNavBarVisibilityListener =
1022            new BarController.OnBarVisibilityChangedListener() {
1023        @Override
1024        public void onBarVisibilityChanged(boolean visible) {
1025            mAccessibilityManager.notifyAccessibilityButtonAvailabilityChanged(visible);
1026        }
1027    };
1028
1029    private ImmersiveModeConfirmation mImmersiveModeConfirmation;
1030
1031    private SystemGesturesPointerEventListener mSystemGestures;
1032
1033    IStatusBarService getStatusBarService() {
1034        synchronized (mServiceAquireLock) {
1035            if (mStatusBarService == null) {
1036                mStatusBarService = IStatusBarService.Stub.asInterface(
1037                        ServiceManager.getService("statusbar"));
1038            }
1039            return mStatusBarService;
1040        }
1041    }
1042
1043    StatusBarManagerInternal getStatusBarManagerInternal() {
1044        synchronized (mServiceAquireLock) {
1045            if (mStatusBarManagerInternal == null) {
1046                mStatusBarManagerInternal =
1047                        LocalServices.getService(StatusBarManagerInternal.class);
1048            }
1049            return mStatusBarManagerInternal;
1050        }
1051    }
1052
1053    /*
1054     * We always let the sensor be switched on by default except when
1055     * the user has explicitly disabled sensor based rotation or when the
1056     * screen is switched off.
1057     */
1058    boolean needSensorRunningLp() {
1059        if (mSupportAutoRotation) {
1060            if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
1061                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
1062                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
1063                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
1064                // If the application has explicitly requested to follow the
1065                // orientation, then we need to turn the sensor on.
1066                return true;
1067            }
1068        }
1069        if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
1070                (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
1071                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
1072                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
1073            // enable accelerometer if we are docked in a dock that enables accelerometer
1074            // orientation management,
1075            return true;
1076        }
1077        if (mUserRotationMode == USER_ROTATION_LOCKED) {
1078            // If the setting for using the sensor by default is enabled, then
1079            // we will always leave it on.  Note that the user could go to
1080            // a window that forces an orientation that does not use the
1081            // sensor and in theory we could turn it off... however, when next
1082            // turning it on we won't have a good value for the current
1083            // orientation for a little bit, which can cause orientation
1084            // changes to lag, so we'd like to keep it always on.  (It will
1085            // still be turned off when the screen is off.)
1086            return false;
1087        }
1088        return mSupportAutoRotation;
1089    }
1090
1091    /*
1092     * Various use cases for invoking this function
1093     * screen turning off, should always disable listeners if already enabled
1094     * screen turned on and current app has sensor based orientation, enable listeners
1095     * if not already enabled
1096     * screen turned on and current app does not have sensor orientation, disable listeners if
1097     * already enabled
1098     * screen turning on and current app has sensor based orientation, enable listeners if needed
1099     * screen turning on and current app has nosensor based orientation, do nothing
1100     */
1101    void updateOrientationListenerLp() {
1102        if (!mOrientationListener.canDetectOrientation()) {
1103            // If sensor is turned off or nonexistent for some reason
1104            return;
1105        }
1106        // Could have been invoked due to screen turning on or off or
1107        // change of the currently visible window's orientation.
1108        if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly
1109                + ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation
1110                + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled
1111                + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
1112                + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
1113        boolean disable = true;
1114        // Note: We postpone the rotating of the screen until the keyguard as well as the
1115        // window manager have reported a draw complete.
1116        if (mScreenOnEarly && mAwake &&
1117                mKeyguardDrawComplete && mWindowManagerDrawComplete) {
1118            if (needSensorRunningLp()) {
1119                disable = false;
1120                //enable listener if not already enabled
1121                if (!mOrientationSensorEnabled) {
1122                    mOrientationListener.enable();
1123                    if(localLOGV) Slog.v(TAG, "Enabling listeners");
1124                    mOrientationSensorEnabled = true;
1125                }
1126            }
1127        }
1128        //check if sensors need to be disabled
1129        if (disable && mOrientationSensorEnabled) {
1130            mOrientationListener.disable();
1131            if(localLOGV) Slog.v(TAG, "Disabling listeners");
1132            mOrientationSensorEnabled = false;
1133        }
1134    }
1135
1136    private void interceptBackKeyDown() {
1137        MetricsLogger.count(mContext, "key_back_down", 1);
1138        // Reset back key state for long press
1139        mBackKeyHandled = false;
1140
1141        // Cancel multi-press detection timeout.
1142        if (hasPanicPressOnBackBehavior()) {
1143            if (mBackKeyPressCounter != 0
1144                    && mBackKeyPressCounter < PANIC_PRESS_BACK_COUNT) {
1145                mHandler.removeMessages(MSG_BACK_DELAYED_PRESS);
1146            }
1147        }
1148
1149        if (hasLongPressOnBackBehavior()) {
1150            Message msg = mHandler.obtainMessage(MSG_BACK_LONG_PRESS);
1151            msg.setAsynchronous(true);
1152            mHandler.sendMessageDelayed(msg,
1153                    ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1154        }
1155    }
1156
1157    // returns true if the key was handled and should not be passed to the user
1158    private boolean interceptBackKeyUp(KeyEvent event) {
1159        // Cache handled state
1160        boolean handled = mBackKeyHandled;
1161
1162        if (hasPanicPressOnBackBehavior()) {
1163            // Check for back key panic press
1164            ++mBackKeyPressCounter;
1165
1166            final long eventTime = event.getDownTime();
1167
1168            if (mBackKeyPressCounter <= PANIC_PRESS_BACK_COUNT) {
1169                // This could be a multi-press.  Wait a little bit longer to confirm.
1170                Message msg = mHandler.obtainMessage(MSG_BACK_DELAYED_PRESS,
1171                    mBackKeyPressCounter, 0, eventTime);
1172                msg.setAsynchronous(true);
1173                mHandler.sendMessageDelayed(msg, ViewConfiguration.getMultiPressTimeout());
1174            }
1175        }
1176
1177        // Reset back long press state
1178        cancelPendingBackKeyAction();
1179
1180        if (mHasFeatureWatch) {
1181            TelecomManager telecomManager = getTelecommService();
1182
1183            if (telecomManager != null) {
1184                if (telecomManager.isRinging()) {
1185                    // Pressing back while there's a ringing incoming
1186                    // call should silence the ringer.
1187                    telecomManager.silenceRinger();
1188
1189                    // It should not prevent navigating away
1190                    return false;
1191                } else if (
1192                    (mIncallBackBehavior & Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_HANGUP) != 0
1193                        && telecomManager.isInCall()) {
1194                    // Otherwise, if "Back button ends call" is enabled,
1195                    // the Back button will hang up any current active call.
1196                    return telecomManager.endCall();
1197                }
1198            }
1199        }
1200
1201        return handled;
1202    }
1203
1204    private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
1205        // Hold a wake lock until the power key is released.
1206        if (!mPowerKeyWakeLock.isHeld()) {
1207            mPowerKeyWakeLock.acquire();
1208        }
1209
1210        // Cancel multi-press detection timeout.
1211        if (mPowerKeyPressCounter != 0) {
1212            mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);
1213        }
1214
1215        // Detect user pressing the power button in panic when an application has
1216        // taken over the whole screen.
1217        boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
1218                SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags),
1219                isNavBarEmpty(mLastSystemUiFlags));
1220        if (panic) {
1221            mHandler.post(mHiddenNavPanic);
1222        }
1223
1224        // Latch power key state to detect screenshot chord.
1225        if (interactive && !mScreenshotChordPowerKeyTriggered
1226                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
1227            mScreenshotChordPowerKeyTriggered = true;
1228            mScreenshotChordPowerKeyTime = event.getDownTime();
1229            interceptScreenshotChord();
1230        }
1231
1232        // Stop ringing or end call if configured to do so when power is pressed.
1233        TelecomManager telecomManager = getTelecommService();
1234        boolean hungUp = false;
1235        if (telecomManager != null) {
1236            if (telecomManager.isRinging()) {
1237                // Pressing Power while there's a ringing incoming
1238                // call should silence the ringer.
1239                telecomManager.silenceRinger();
1240            } else if ((mIncallPowerBehavior
1241                    & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
1242                    && telecomManager.isInCall() && interactive) {
1243                // Otherwise, if "Power button ends call" is enabled,
1244                // the Power button will hang up any current active call.
1245                hungUp = telecomManager.endCall();
1246            }
1247        }
1248
1249        GestureLauncherService gestureService = LocalServices.getService(
1250                GestureLauncherService.class);
1251        boolean gesturedServiceIntercepted = false;
1252        if (gestureService != null) {
1253            gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive,
1254                    mTmpBoolean);
1255            if (mTmpBoolean.value && mGoingToSleep) {
1256                mCameraGestureTriggeredDuringGoingToSleep = true;
1257            }
1258        }
1259
1260        // If the power key has still not yet been handled, then detect short
1261        // press, long press, or multi press and decide what to do.
1262        mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
1263                || mA11yShortcutChordVolumeUpKeyTriggered || gesturedServiceIntercepted;
1264        if (!mPowerKeyHandled) {
1265            if (interactive) {
1266                // When interactive, we're already awake.
1267                // Wait for a long press or for the button to be released to decide what to do.
1268                if (hasLongPressOnPowerBehavior()) {
1269                    Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
1270                    msg.setAsynchronous(true);
1271                    mHandler.sendMessageDelayed(msg,
1272                            ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1273                }
1274            } else {
1275                wakeUpFromPowerKey(event.getDownTime());
1276
1277                if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
1278                    Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
1279                    msg.setAsynchronous(true);
1280                    mHandler.sendMessageDelayed(msg,
1281                            ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1282                    mBeganFromNonInteractive = true;
1283                } else {
1284                    final int maxCount = getMaxMultiPressPowerCount();
1285
1286                    if (maxCount <= 1) {
1287                        mPowerKeyHandled = true;
1288                    } else {
1289                        mBeganFromNonInteractive = true;
1290                    }
1291                }
1292            }
1293        }
1294    }
1295
1296    private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
1297        final boolean handled = canceled || mPowerKeyHandled;
1298        mScreenshotChordPowerKeyTriggered = false;
1299        cancelPendingScreenshotChordAction();
1300        cancelPendingPowerKeyAction();
1301
1302        if (!handled) {
1303            // Figure out how to handle the key now that it has been released.
1304            mPowerKeyPressCounter += 1;
1305
1306            final int maxCount = getMaxMultiPressPowerCount();
1307            final long eventTime = event.getDownTime();
1308            if (mPowerKeyPressCounter < maxCount) {
1309                // This could be a multi-press.  Wait a little bit longer to confirm.
1310                // Continue holding the wake lock.
1311                Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
1312                        interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
1313                msg.setAsynchronous(true);
1314                mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
1315                return;
1316            }
1317
1318            // No other actions.  Handle it immediately.
1319            powerPress(eventTime, interactive, mPowerKeyPressCounter);
1320        }
1321
1322        // Done.  Reset our state.
1323        finishPowerKeyPress();
1324    }
1325
1326    private void finishPowerKeyPress() {
1327        mBeganFromNonInteractive = false;
1328        mPowerKeyPressCounter = 0;
1329        if (mPowerKeyWakeLock.isHeld()) {
1330            mPowerKeyWakeLock.release();
1331        }
1332    }
1333
1334    private void finishBackKeyPress() {
1335        mBackKeyPressCounter = 0;
1336    }
1337
1338    private void cancelPendingPowerKeyAction() {
1339        if (!mPowerKeyHandled) {
1340            mPowerKeyHandled = true;
1341            mHandler.removeMessages(MSG_POWER_LONG_PRESS);
1342        }
1343    }
1344
1345    private void cancelPendingBackKeyAction() {
1346        if (!mBackKeyHandled) {
1347            mBackKeyHandled = true;
1348            mHandler.removeMessages(MSG_BACK_LONG_PRESS);
1349        }
1350    }
1351
1352    private void backMultiPressAction(long eventTime, int count) {
1353        if (count >= PANIC_PRESS_BACK_COUNT) {
1354            switch (mPanicPressOnBackBehavior) {
1355                case PANIC_PRESS_BACK_NOTHING:
1356                    break;
1357                case PANIC_PRESS_BACK_HOME:
1358                    launchHomeFromHotKey();
1359                    break;
1360            }
1361        }
1362    }
1363
1364    private void powerPress(long eventTime, boolean interactive, int count) {
1365        if (mScreenOnEarly && !mScreenOnFully) {
1366            Slog.i(TAG, "Suppressed redundant power key press while "
1367                    + "already in the process of turning the screen on.");
1368            return;
1369        }
1370
1371        if (count == 2) {
1372            powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
1373        } else if (count == 3) {
1374            powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
1375        } else if (interactive && !mBeganFromNonInteractive) {
1376            switch (mShortPressOnPowerBehavior) {
1377                case SHORT_PRESS_POWER_NOTHING:
1378                    break;
1379                case SHORT_PRESS_POWER_GO_TO_SLEEP:
1380                    mPowerManager.goToSleep(eventTime,
1381                            PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
1382                    break;
1383                case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
1384                    mPowerManager.goToSleep(eventTime,
1385                            PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
1386                            PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
1387                    break;
1388                case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
1389                    mPowerManager.goToSleep(eventTime,
1390                            PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
1391                            PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
1392                    launchHomeFromHotKey();
1393                    break;
1394                case SHORT_PRESS_POWER_GO_HOME:
1395                    launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
1396                    break;
1397            }
1398        }
1399    }
1400
1401    private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) {
1402        switch (behavior) {
1403            case MULTI_PRESS_POWER_NOTHING:
1404                break;
1405            case MULTI_PRESS_POWER_THEATER_MODE:
1406                if (!isUserSetupComplete()) {
1407                    Slog.i(TAG, "Ignoring toggling theater mode - device not setup.");
1408                    break;
1409                }
1410
1411                if (isTheaterModeEnabled()) {
1412                    Slog.i(TAG, "Toggling theater mode off.");
1413                    Settings.Global.putInt(mContext.getContentResolver(),
1414                            Settings.Global.THEATER_MODE_ON, 0);
1415                    if (!interactive) {
1416                        wakeUpFromPowerKey(eventTime);
1417                    }
1418                } else {
1419                    Slog.i(TAG, "Toggling theater mode on.");
1420                    Settings.Global.putInt(mContext.getContentResolver(),
1421                            Settings.Global.THEATER_MODE_ON, 1);
1422
1423                    if (mGoToSleepOnButtonPressTheaterMode && interactive) {
1424                        mPowerManager.goToSleep(eventTime,
1425                                PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
1426                    }
1427                }
1428                break;
1429            case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
1430                Slog.i(TAG, "Starting brightness boost.");
1431                if (!interactive) {
1432                    wakeUpFromPowerKey(eventTime);
1433                }
1434                mPowerManager.boostScreenBrightness(eventTime);
1435                break;
1436        }
1437    }
1438
1439    private int getMaxMultiPressPowerCount() {
1440        if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
1441            return 3;
1442        }
1443        if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
1444            return 2;
1445        }
1446        return 1;
1447    }
1448
1449    private void powerLongPress() {
1450        final int behavior = getResolvedLongPressOnPowerBehavior();
1451        switch (behavior) {
1452        case LONG_PRESS_POWER_NOTHING:
1453            break;
1454        case LONG_PRESS_POWER_GLOBAL_ACTIONS:
1455            mPowerKeyHandled = true;
1456            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1457            showGlobalActionsInternal();
1458            break;
1459        case LONG_PRESS_POWER_SHUT_OFF:
1460        case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
1461            mPowerKeyHandled = true;
1462            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1463            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
1464            mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
1465            break;
1466        }
1467    }
1468
1469    private void backLongPress() {
1470        mBackKeyHandled = true;
1471
1472        switch (mLongPressOnBackBehavior) {
1473            case LONG_PRESS_BACK_NOTHING:
1474                break;
1475            case LONG_PRESS_BACK_GO_TO_VOICE_ASSIST:
1476                final boolean keyguardActive = mKeyguardDelegate == null
1477                        ? false
1478                        : mKeyguardDelegate.isShowing();
1479                if (!keyguardActive) {
1480                    Intent intent = new Intent(Intent.ACTION_VOICE_ASSIST);
1481                    startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
1482                }
1483                break;
1484        }
1485    }
1486
1487    private void accessibilityShortcutActivated() {
1488        mAccessibilityShortcutController.performAccessibilityShortcut();
1489    }
1490
1491    private void disposeInputConsumer(InputConsumer inputConsumer) {
1492        if (inputConsumer != null) {
1493            inputConsumer.dismiss();
1494        }
1495    }
1496
1497    private void sleepPress(long eventTime) {
1498        if (mShortPressOnSleepBehavior == SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME) {
1499            launchHomeFromHotKey(false /* awakenDreams */, true /*respectKeyguard*/);
1500        }
1501    }
1502
1503    private void sleepRelease(long eventTime) {
1504        switch (mShortPressOnSleepBehavior) {
1505            case SHORT_PRESS_SLEEP_GO_TO_SLEEP:
1506            case SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME:
1507                Slog.i(TAG, "sleepRelease() calling goToSleep(GO_TO_SLEEP_REASON_SLEEP_BUTTON)");
1508                mPowerManager.goToSleep(eventTime,
1509                       PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON, 0);
1510                break;
1511        }
1512    }
1513
1514    private int getResolvedLongPressOnPowerBehavior() {
1515        if (FactoryTest.isLongPressOnPowerOffEnabled()) {
1516            return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
1517        }
1518        return mLongPressOnPowerBehavior;
1519    }
1520
1521    private boolean hasLongPressOnPowerBehavior() {
1522        return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;
1523    }
1524
1525    private boolean hasLongPressOnBackBehavior() {
1526        return mLongPressOnBackBehavior != LONG_PRESS_BACK_NOTHING;
1527    }
1528
1529    private boolean hasPanicPressOnBackBehavior() {
1530        return mPanicPressOnBackBehavior != PANIC_PRESS_BACK_NOTHING;
1531    }
1532
1533    private void interceptScreenshotChord() {
1534        if (mScreenshotChordEnabled
1535                && mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered
1536                && !mA11yShortcutChordVolumeUpKeyTriggered) {
1537            final long now = SystemClock.uptimeMillis();
1538            if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
1539                    && now <= mScreenshotChordPowerKeyTime
1540                            + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
1541                mScreenshotChordVolumeDownKeyConsumed = true;
1542                cancelPendingPowerKeyAction();
1543                mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
1544                mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
1545            }
1546        }
1547    }
1548
1549    private void interceptAccessibilityShortcutChord() {
1550        if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable()
1551                && mScreenshotChordVolumeDownKeyTriggered && mA11yShortcutChordVolumeUpKeyTriggered
1552                && !mScreenshotChordPowerKeyTriggered) {
1553            final long now = SystemClock.uptimeMillis();
1554            if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
1555                    && now <= mA11yShortcutChordVolumeUpKeyTime
1556                    + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
1557                mScreenshotChordVolumeDownKeyConsumed = true;
1558                mA11yShortcutChordVolumeUpKeyConsumed = true;
1559                mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_ACCESSIBILITY_SHORTCUT),
1560                        ViewConfiguration.get(mContext).getAccessibilityShortcutKeyTimeout());
1561            }
1562        }
1563    }
1564
1565    private long getScreenshotChordLongPressDelay() {
1566        if (mKeyguardDelegate.isShowing()) {
1567            // Double the time it takes to take a screenshot from the keyguard
1568            return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER *
1569                    ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1570        }
1571        return ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout();
1572    }
1573
1574    private void cancelPendingScreenshotChordAction() {
1575        mHandler.removeCallbacks(mScreenshotRunnable);
1576    }
1577
1578    private void cancelPendingAccessibilityShortcutAction() {
1579        mHandler.removeMessages(MSG_ACCESSIBILITY_SHORTCUT);
1580    }
1581
1582    private final Runnable mEndCallLongPress = new Runnable() {
1583        @Override
1584        public void run() {
1585            mEndCallKeyHandled = true;
1586            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1587            showGlobalActionsInternal();
1588        }
1589    };
1590
1591    private class ScreenshotRunnable implements Runnable {
1592        private int mScreenshotType = TAKE_SCREENSHOT_FULLSCREEN;
1593
1594        public void setScreenshotType(int screenshotType) {
1595            mScreenshotType = screenshotType;
1596        }
1597
1598        @Override
1599        public void run() {
1600            takeScreenshot(mScreenshotType);
1601        }
1602    }
1603
1604    private final ScreenshotRunnable mScreenshotRunnable = new ScreenshotRunnable();
1605
1606    @Override
1607    public void showGlobalActions() {
1608        mHandler.removeMessages(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
1609        mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
1610    }
1611
1612    void showGlobalActionsInternal() {
1613        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
1614        if (mGlobalActions == null) {
1615            mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
1616        }
1617        final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();
1618        mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
1619        if (keyguardShowing) {
1620            // since it took two seconds of long press to bring this up,
1621            // poke the wake lock so they have some time to see the dialog.
1622            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
1623        }
1624    }
1625
1626    boolean isDeviceProvisioned() {
1627        return Settings.Global.getInt(
1628                mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
1629    }
1630
1631    boolean isUserSetupComplete() {
1632        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
1633                Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
1634    }
1635
1636    private void handleShortPressOnHome() {
1637        // Turn on the connected TV and switch HDMI input if we're a HDMI playback device.
1638        final HdmiControl hdmiControl = getHdmiControl();
1639        if (hdmiControl != null) {
1640            hdmiControl.turnOnTv();
1641        }
1642
1643        // If there's a dream running then use home to escape the dream
1644        // but don't actually go home.
1645        if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) {
1646            mDreamManagerInternal.stopDream(false /*immediate*/);
1647            return;
1648        }
1649
1650        // Go home!
1651        launchHomeFromHotKey();
1652    }
1653
1654    /**
1655     * Creates an accessor to HDMI control service that performs the operation of
1656     * turning on TV (optional) and switching input to us. If HDMI control service
1657     * is not available or we're not a HDMI playback device, the operation is no-op.
1658     * @return {@link HdmiControl} instance if available, null otherwise.
1659     */
1660    private HdmiControl getHdmiControl() {
1661        if (null == mHdmiControl) {
1662            if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
1663                return null;
1664            }
1665            HdmiControlManager manager = (HdmiControlManager) mContext.getSystemService(
1666                        Context.HDMI_CONTROL_SERVICE);
1667            HdmiPlaybackClient client = null;
1668            if (manager != null) {
1669                client = manager.getPlaybackClient();
1670            }
1671            mHdmiControl = new HdmiControl(client);
1672        }
1673        return mHdmiControl;
1674    }
1675
1676    private static class HdmiControl {
1677        private final HdmiPlaybackClient mClient;
1678
1679        private HdmiControl(HdmiPlaybackClient client) {
1680            mClient = client;
1681        }
1682
1683        public void turnOnTv() {
1684            if (mClient == null) {
1685                return;
1686            }
1687            mClient.oneTouchPlay(new OneTouchPlayCallback() {
1688                @Override
1689                public void onComplete(int result) {
1690                    if (result != HdmiControlManager.RESULT_SUCCESS) {
1691                        Log.w(TAG, "One touch play failed: " + result);
1692                    }
1693                }
1694            });
1695        }
1696    }
1697
1698    private void handleLongPressOnHome(int deviceId) {
1699        if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_NOTHING) {
1700            return;
1701        }
1702        mHomeConsumed = true;
1703        performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1704
1705        switch (mLongPressOnHomeBehavior) {
1706            case LONG_PRESS_HOME_RECENT_SYSTEM_UI:
1707                toggleRecentApps();
1708                break;
1709            case LONG_PRESS_HOME_ASSIST:
1710                launchAssistAction(null, deviceId);
1711                break;
1712            default:
1713                Log.w(TAG, "Undefined home long press behavior: " + mLongPressOnHomeBehavior);
1714                break;
1715        }
1716    }
1717
1718    private void handleDoubleTapOnHome() {
1719        if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
1720            mHomeConsumed = true;
1721            toggleRecentApps();
1722        }
1723    }
1724
1725    private void showTvPictureInPictureMenu(KeyEvent event) {
1726        if (DEBUG_INPUT) Log.d(TAG, "showTvPictureInPictureMenu event=" + event);
1727        mHandler.removeMessages(MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU);
1728        Message msg = mHandler.obtainMessage(MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU);
1729        msg.setAsynchronous(true);
1730        msg.sendToTarget();
1731    }
1732
1733    private void showTvPictureInPictureMenuInternal() {
1734        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
1735        if (statusbar != null) {
1736            statusbar.showTvPictureInPictureMenu();
1737        }
1738    }
1739
1740    private final Runnable mHomeDoubleTapTimeoutRunnable = new Runnable() {
1741        @Override
1742        public void run() {
1743            if (mHomeDoubleTapPending) {
1744                mHomeDoubleTapPending = false;
1745                handleShortPressOnHome();
1746            }
1747        }
1748    };
1749
1750    private boolean isRoundWindow() {
1751        return mContext.getResources().getConfiguration().isScreenRound();
1752    }
1753
1754    /** {@inheritDoc} */
1755    @Override
1756    public void init(Context context, IWindowManager windowManager,
1757            WindowManagerFuncs windowManagerFuncs) {
1758        mContext = context;
1759        mWindowManager = windowManager;
1760        mWindowManagerFuncs = windowManagerFuncs;
1761        mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
1762        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
1763        mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
1764        mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
1765        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
1766        mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
1767        mHasFeatureWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH);
1768        mHasFeatureLeanback = mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK);
1769        mAccessibilityShortcutController =
1770                new AccessibilityShortcutController(mContext, new Handler());
1771        // Init display burn-in protection
1772        boolean burnInProtectionEnabled = context.getResources().getBoolean(
1773                com.android.internal.R.bool.config_enableBurnInProtection);
1774        // Allow a system property to override this. Used by developer settings.
1775        boolean burnInProtectionDevMode =
1776                SystemProperties.getBoolean("persist.debug.force_burn_in", false);
1777        if (burnInProtectionEnabled || burnInProtectionDevMode) {
1778            final int minHorizontal;
1779            final int maxHorizontal;
1780            final int minVertical;
1781            final int maxVertical;
1782            final int maxRadius;
1783            if (burnInProtectionDevMode) {
1784                minHorizontal = -8;
1785                maxHorizontal = 8;
1786                minVertical = -8;
1787                maxVertical = -4;
1788                maxRadius = (isRoundWindow()) ? 6 : -1;
1789            } else {
1790                Resources resources = context.getResources();
1791                minHorizontal = resources.getInteger(
1792                        com.android.internal.R.integer.config_burnInProtectionMinHorizontalOffset);
1793                maxHorizontal = resources.getInteger(
1794                        com.android.internal.R.integer.config_burnInProtectionMaxHorizontalOffset);
1795                minVertical = resources.getInteger(
1796                        com.android.internal.R.integer.config_burnInProtectionMinVerticalOffset);
1797                maxVertical = resources.getInteger(
1798                        com.android.internal.R.integer.config_burnInProtectionMaxVerticalOffset);
1799                maxRadius = resources.getInteger(
1800                        com.android.internal.R.integer.config_burnInProtectionMaxRadius);
1801            }
1802            mBurnInProtectionHelper = new BurnInProtectionHelper(
1803                    context, minHorizontal, maxHorizontal, minVertical, maxVertical, maxRadius);
1804        }
1805
1806        mHandler = new PolicyHandler();
1807        mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
1808        mOrientationListener = new MyOrientationListener(mContext, mHandler);
1809        try {
1810            mOrientationListener.setCurrentRotation(windowManager.getDefaultDisplayRotation());
1811        } catch (RemoteException ex) { }
1812        mSettingsObserver = new SettingsObserver(mHandler);
1813        mSettingsObserver.observe();
1814        mShortcutManager = new ShortcutManager(context);
1815        mUiMode = context.getResources().getInteger(
1816                com.android.internal.R.integer.config_defaultUiModeType);
1817        mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
1818        mHomeIntent.addCategory(Intent.CATEGORY_HOME);
1819        mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1820                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1821        mEnableCarDockHomeCapture = context.getResources().getBoolean(
1822                com.android.internal.R.bool.config_enableCarDockHomeLaunch);
1823        mCarDockIntent =  new Intent(Intent.ACTION_MAIN, null);
1824        mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
1825        mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1826                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1827        mDeskDockIntent =  new Intent(Intent.ACTION_MAIN, null);
1828        mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
1829        mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1830                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1831        mVrHeadsetHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
1832        mVrHeadsetHomeIntent.addCategory(Intent.CATEGORY_VR_HOME);
1833        mVrHeadsetHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1834                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1835
1836        mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1837        mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1838                "PhoneWindowManager.mBroadcastWakeLock");
1839        mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1840                "PhoneWindowManager.mPowerKeyWakeLock");
1841        mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
1842        mSupportAutoRotation = mContext.getResources().getBoolean(
1843                com.android.internal.R.bool.config_supportAutoRotation);
1844        mLidOpenRotation = readRotation(
1845                com.android.internal.R.integer.config_lidOpenRotation);
1846        mCarDockRotation = readRotation(
1847                com.android.internal.R.integer.config_carDockRotation);
1848        mDeskDockRotation = readRotation(
1849                com.android.internal.R.integer.config_deskDockRotation);
1850        mUndockedHdmiRotation = readRotation(
1851                com.android.internal.R.integer.config_undockedHdmiRotation);
1852        mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
1853                com.android.internal.R.bool.config_carDockEnablesAccelerometer);
1854        mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
1855                com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
1856        mLidKeyboardAccessibility = mContext.getResources().getInteger(
1857                com.android.internal.R.integer.config_lidKeyboardAccessibility);
1858        mLidNavigationAccessibility = mContext.getResources().getInteger(
1859                com.android.internal.R.integer.config_lidNavigationAccessibility);
1860        mLidControlsScreenLock = mContext.getResources().getBoolean(
1861                com.android.internal.R.bool.config_lidControlsScreenLock);
1862        mLidControlsSleep = mContext.getResources().getBoolean(
1863                com.android.internal.R.bool.config_lidControlsSleep);
1864        mTranslucentDecorEnabled = mContext.getResources().getBoolean(
1865                com.android.internal.R.bool.config_enableTranslucentDecor);
1866
1867        mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
1868                com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
1869        mAllowTheaterModeWakeFromPowerKey = mAllowTheaterModeWakeFromKey
1870                || mContext.getResources().getBoolean(
1871                    com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey);
1872        mAllowTheaterModeWakeFromMotion = mContext.getResources().getBoolean(
1873                com.android.internal.R.bool.config_allowTheaterModeWakeFromMotion);
1874        mAllowTheaterModeWakeFromMotionWhenNotDreaming = mContext.getResources().getBoolean(
1875                com.android.internal.R.bool.config_allowTheaterModeWakeFromMotionWhenNotDreaming);
1876        mAllowTheaterModeWakeFromCameraLens = mContext.getResources().getBoolean(
1877                com.android.internal.R.bool.config_allowTheaterModeWakeFromCameraLens);
1878        mAllowTheaterModeWakeFromLidSwitch = mContext.getResources().getBoolean(
1879                com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch);
1880        mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean(
1881                com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture);
1882
1883        mGoToSleepOnButtonPressTheaterMode = mContext.getResources().getBoolean(
1884                com.android.internal.R.bool.config_goToSleepOnButtonPressTheaterMode);
1885
1886        mSupportLongPressPowerWhenNonInteractive = mContext.getResources().getBoolean(
1887                com.android.internal.R.bool.config_supportLongPressPowerWhenNonInteractive);
1888
1889        mLongPressOnBackBehavior = mContext.getResources().getInteger(
1890                com.android.internal.R.integer.config_longPressOnBackBehavior);
1891        mPanicPressOnBackBehavior = mContext.getResources().getInteger(
1892                com.android.internal.R.integer.config_backPanicBehavior);
1893
1894        mShortPressOnPowerBehavior = mContext.getResources().getInteger(
1895                com.android.internal.R.integer.config_shortPressOnPowerBehavior);
1896        mLongPressOnPowerBehavior = mContext.getResources().getInteger(
1897                com.android.internal.R.integer.config_longPressOnPowerBehavior);
1898        mDoublePressOnPowerBehavior = mContext.getResources().getInteger(
1899                com.android.internal.R.integer.config_doublePressOnPowerBehavior);
1900        mTriplePressOnPowerBehavior = mContext.getResources().getInteger(
1901                com.android.internal.R.integer.config_triplePressOnPowerBehavior);
1902        mShortPressOnSleepBehavior = mContext.getResources().getInteger(
1903                com.android.internal.R.integer.config_shortPressOnSleepBehavior);
1904
1905        mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION;
1906
1907        readConfigurationDependentBehaviors();
1908
1909        mAccessibilityManager = (AccessibilityManager) context.getSystemService(
1910                Context.ACCESSIBILITY_SERVICE);
1911
1912        // register for dock events
1913        IntentFilter filter = new IntentFilter();
1914        filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
1915        filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
1916        filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
1917        filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
1918        filter.addAction(Intent.ACTION_DOCK_EVENT);
1919        Intent intent = context.registerReceiver(mDockReceiver, filter);
1920        if (intent != null) {
1921            // Retrieve current sticky dock event broadcast.
1922            mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
1923                    Intent.EXTRA_DOCK_STATE_UNDOCKED);
1924        }
1925
1926        // register for dream-related broadcasts
1927        filter = new IntentFilter();
1928        filter.addAction(Intent.ACTION_DREAMING_STARTED);
1929        filter.addAction(Intent.ACTION_DREAMING_STOPPED);
1930        context.registerReceiver(mDreamReceiver, filter);
1931
1932        // register for multiuser-relevant broadcasts
1933        filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
1934        context.registerReceiver(mMultiuserReceiver, filter);
1935
1936        // monitor for system gestures
1937        mSystemGestures = new SystemGesturesPointerEventListener(context,
1938                new SystemGesturesPointerEventListener.Callbacks() {
1939                    @Override
1940                    public void onSwipeFromTop() {
1941                        if (mStatusBar != null) {
1942                            requestTransientBars(mStatusBar);
1943                        }
1944                        if (mPersistentVrModeEnabled) {
1945                            exitPersistentVrMode();
1946                        }
1947                    }
1948                    @Override
1949                    public void onSwipeFromBottom() {
1950                        if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_BOTTOM) {
1951                            requestTransientBars(mNavigationBar);
1952                        }
1953                        if (mPersistentVrModeEnabled) {
1954                            exitPersistentVrMode();
1955                        }
1956                    }
1957                    @Override
1958                    public void onSwipeFromRight() {
1959                        if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_RIGHT) {
1960                            requestTransientBars(mNavigationBar);
1961                        }
1962                        if (mPersistentVrModeEnabled) {
1963                            exitPersistentVrMode();
1964                        }
1965                    }
1966                    @Override
1967                    public void onSwipeFromLeft() {
1968                        if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_LEFT) {
1969                            requestTransientBars(mNavigationBar);
1970                        }
1971                        if (mPersistentVrModeEnabled) {
1972                            exitPersistentVrMode();
1973                        }
1974                    }
1975                    @Override
1976                    public void onFling(int duration) {
1977                        if (mPowerManagerInternal != null) {
1978                            mPowerManagerInternal.powerHint(
1979                                    PowerHint.INTERACTION, duration);
1980                        }
1981                    }
1982                    @Override
1983                    public void onDebug() {
1984                        // no-op
1985                    }
1986                    @Override
1987                    public void onDown() {
1988                        mOrientationListener.onTouchStart();
1989                    }
1990                    @Override
1991                    public void onUpOrCancel() {
1992                        mOrientationListener.onTouchEnd();
1993                    }
1994                    @Override
1995                    public void onMouseHoverAtTop() {
1996                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
1997                        Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
1998                        msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
1999                        mHandler.sendMessageDelayed(msg, 500);
2000                    }
2001                    @Override
2002                    public void onMouseHoverAtBottom() {
2003                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
2004                        Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
2005                        msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
2006                        mHandler.sendMessageDelayed(msg, 500);
2007                    }
2008                    @Override
2009                    public void onMouseLeaveFromEdge() {
2010                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
2011                    }
2012                });
2013        mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext);
2014        mWindowManagerFuncs.registerPointerEventListener(mSystemGestures);
2015
2016        mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
2017        mLongPressVibePattern = getLongIntArray(mContext.getResources(),
2018                com.android.internal.R.array.config_longPressVibePattern);
2019        mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(),
2020                com.android.internal.R.array.config_virtualKeyVibePattern);
2021        mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(),
2022                com.android.internal.R.array.config_keyboardTapVibePattern);
2023        mClockTickVibePattern = getLongIntArray(mContext.getResources(),
2024                com.android.internal.R.array.config_clockTickVibePattern);
2025        mCalendarDateVibePattern = getLongIntArray(mContext.getResources(),
2026                com.android.internal.R.array.config_calendarDateVibePattern);
2027        mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
2028                com.android.internal.R.array.config_safeModeDisabledVibePattern);
2029        mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
2030                com.android.internal.R.array.config_safeModeEnabledVibePattern);
2031        mContextClickVibePattern = getLongIntArray(mContext.getResources(),
2032                com.android.internal.R.array.config_contextClickVibePattern);
2033
2034        mScreenshotChordEnabled = mContext.getResources().getBoolean(
2035                com.android.internal.R.bool.config_enableScreenshotChord);
2036
2037        mGlobalKeyManager = new GlobalKeyManager(mContext);
2038
2039        // Controls rotation and the like.
2040        initializeHdmiState();
2041
2042        // Match current screen state.
2043        if (!mPowerManager.isInteractive()) {
2044            startedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
2045            finishedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
2046        }
2047
2048        mWindowManagerInternal.registerAppTransitionListener(
2049                mStatusBarController.getAppTransitionListener());
2050        mWindowManagerInternal.registerAppTransitionListener(new AppTransitionListener() {
2051            @Override
2052            public int onAppTransitionStartingLocked(int transit, IBinder openToken,
2053                    IBinder closeToken,
2054                    Animation openAnimation, Animation closeAnimation) {
2055                return handleStartTransitionForKeyguardLw(transit, openAnimation);
2056            }
2057
2058            @Override
2059            public void onAppTransitionCancelledLocked(int transit) {
2060                handleStartTransitionForKeyguardLw(transit, null /* transit */);
2061            }
2062        });
2063    }
2064
2065    /**
2066     * Read values from config.xml that may be overridden depending on
2067     * the configuration of the device.
2068     * eg. Disable long press on home goes to recents on sw600dp.
2069     */
2070    private void readConfigurationDependentBehaviors() {
2071        final Resources res = mContext.getResources();
2072
2073        mLongPressOnHomeBehavior = res.getInteger(
2074                com.android.internal.R.integer.config_longPressOnHomeBehavior);
2075        if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||
2076                mLongPressOnHomeBehavior > LAST_LONG_PRESS_HOME_BEHAVIOR) {
2077            mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
2078        }
2079
2080        mDoubleTapOnHomeBehavior = res.getInteger(
2081                com.android.internal.R.integer.config_doubleTapOnHomeBehavior);
2082        if (mDoubleTapOnHomeBehavior < DOUBLE_TAP_HOME_NOTHING ||
2083                mDoubleTapOnHomeBehavior > DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
2084            mDoubleTapOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
2085        }
2086
2087        mShortPressWindowBehavior = SHORT_PRESS_WINDOW_NOTHING;
2088        if (mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
2089            mShortPressWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE;
2090        }
2091
2092        mNavBarOpacityMode = res.getInteger(
2093                com.android.internal.R.integer.config_navBarOpacityMode);
2094    }
2095
2096    @Override
2097    public void setInitialDisplaySize(Display display, int width, int height, int density) {
2098        // This method might be called before the policy has been fully initialized
2099        // or for other displays we don't care about.
2100        // TODO(multi-display): Define policy for secondary displays.
2101        if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) {
2102            return;
2103        }
2104        mDisplay = display;
2105
2106        final Resources res = mContext.getResources();
2107        int shortSize, longSize;
2108        if (width > height) {
2109            shortSize = height;
2110            longSize = width;
2111            mLandscapeRotation = Surface.ROTATION_0;
2112            mSeascapeRotation = Surface.ROTATION_180;
2113            if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
2114                mPortraitRotation = Surface.ROTATION_90;
2115                mUpsideDownRotation = Surface.ROTATION_270;
2116            } else {
2117                mPortraitRotation = Surface.ROTATION_270;
2118                mUpsideDownRotation = Surface.ROTATION_90;
2119            }
2120        } else {
2121            shortSize = width;
2122            longSize = height;
2123            mPortraitRotation = Surface.ROTATION_0;
2124            mUpsideDownRotation = Surface.ROTATION_180;
2125            if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
2126                mLandscapeRotation = Surface.ROTATION_270;
2127                mSeascapeRotation = Surface.ROTATION_90;
2128            } else {
2129                mLandscapeRotation = Surface.ROTATION_90;
2130                mSeascapeRotation = Surface.ROTATION_270;
2131            }
2132        }
2133
2134        // SystemUI (status bar) layout policy
2135        int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
2136        int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
2137
2138        // Allow the navigation bar to move on non-square small devices (phones).
2139        mNavigationBarCanMove = width != height && shortSizeDp < 600;
2140
2141        mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
2142
2143        // Allow a system property to override this. Used by the emulator.
2144        // See also hasNavigationBar().
2145        String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
2146        if ("1".equals(navBarOverride)) {
2147            mHasNavigationBar = false;
2148        } else if ("0".equals(navBarOverride)) {
2149            mHasNavigationBar = true;
2150        }
2151
2152        // For demo purposes, allow the rotation of the HDMI display to be controlled.
2153        // By default, HDMI locks rotation to landscape.
2154        if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
2155            mDemoHdmiRotation = mPortraitRotation;
2156        } else {
2157            mDemoHdmiRotation = mLandscapeRotation;
2158        }
2159        mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
2160
2161        // For demo purposes, allow the rotation of the remote display to be controlled.
2162        // By default, remote display locks rotation to landscape.
2163        if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
2164            mDemoRotation = mPortraitRotation;
2165        } else {
2166            mDemoRotation = mLandscapeRotation;
2167        }
2168        mDemoRotationLock = SystemProperties.getBoolean(
2169                "persist.demo.rotationlock", false);
2170
2171        // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
2172        // http://developer.android.com/guide/practices/screens_support.html#range
2173        mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 &&
2174                res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
2175                // For debug purposes the next line turns this feature off with:
2176                // $ adb shell setprop config.override_forced_orient true
2177                // $ adb shell wm size reset
2178                !"true".equals(SystemProperties.get("config.override_forced_orient"));
2179    }
2180
2181    /**
2182     * @return whether the navigation bar can be hidden, e.g. the device has a
2183     *         navigation bar and touch exploration is not enabled
2184     */
2185    private boolean canHideNavigationBar() {
2186        return mHasNavigationBar;
2187    }
2188
2189    @Override
2190    public boolean isDefaultOrientationForced() {
2191        return mForceDefaultOrientation;
2192    }
2193
2194    @Override
2195    public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) {
2196        // TODO(multi-display): Define policy for secondary displays.
2197        if (display.getDisplayId() == Display.DEFAULT_DISPLAY) {
2198            mOverscanLeft = left;
2199            mOverscanTop = top;
2200            mOverscanRight = right;
2201            mOverscanBottom = bottom;
2202        }
2203    }
2204
2205    public void updateSettings() {
2206        ContentResolver resolver = mContext.getContentResolver();
2207        boolean updateRotation = false;
2208        synchronized (mLock) {
2209            mEndcallBehavior = Settings.System.getIntForUser(resolver,
2210                    Settings.System.END_BUTTON_BEHAVIOR,
2211                    Settings.System.END_BUTTON_BEHAVIOR_DEFAULT,
2212                    UserHandle.USER_CURRENT);
2213            mIncallPowerBehavior = Settings.Secure.getIntForUser(resolver,
2214                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
2215                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT,
2216                    UserHandle.USER_CURRENT);
2217            mIncallBackBehavior = Settings.Secure.getIntForUser(resolver,
2218                    Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR,
2219                    Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_DEFAULT,
2220                    UserHandle.USER_CURRENT);
2221
2222            // Configure wake gesture.
2223            boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver,
2224                    Settings.Secure.WAKE_GESTURE_ENABLED, 0,
2225                    UserHandle.USER_CURRENT) != 0;
2226            if (mWakeGestureEnabledSetting != wakeGestureEnabledSetting) {
2227                mWakeGestureEnabledSetting = wakeGestureEnabledSetting;
2228                updateWakeGestureListenerLp();
2229            }
2230
2231            // Configure rotation lock.
2232            int userRotation = Settings.System.getIntForUser(resolver,
2233                    Settings.System.USER_ROTATION, Surface.ROTATION_0,
2234                    UserHandle.USER_CURRENT);
2235            if (mUserRotation != userRotation) {
2236                mUserRotation = userRotation;
2237                updateRotation = true;
2238            }
2239            int userRotationMode = Settings.System.getIntForUser(resolver,
2240                    Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
2241                            WindowManagerPolicy.USER_ROTATION_FREE :
2242                                    WindowManagerPolicy.USER_ROTATION_LOCKED;
2243            if (mUserRotationMode != userRotationMode) {
2244                mUserRotationMode = userRotationMode;
2245                updateRotation = true;
2246                updateOrientationListenerLp();
2247            }
2248
2249            if (mSystemReady) {
2250                int pointerLocation = Settings.System.getIntForUser(resolver,
2251                        Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT);
2252                if (mPointerLocationMode != pointerLocation) {
2253                    mPointerLocationMode = pointerLocation;
2254                    mHandler.sendEmptyMessage(pointerLocation != 0 ?
2255                            MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
2256                }
2257            }
2258            // use screen off timeout setting as the timeout for the lockscreen
2259            mLockScreenTimeout = Settings.System.getIntForUser(resolver,
2260                    Settings.System.SCREEN_OFF_TIMEOUT, 0, UserHandle.USER_CURRENT);
2261            String imId = Settings.Secure.getStringForUser(resolver,
2262                    Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.USER_CURRENT);
2263            boolean hasSoftInput = imId != null && imId.length() > 0;
2264            if (mHasSoftInput != hasSoftInput) {
2265                mHasSoftInput = hasSoftInput;
2266                updateRotation = true;
2267            }
2268            if (mImmersiveModeConfirmation != null) {
2269                mImmersiveModeConfirmation.loadSetting(mCurrentUserId);
2270            }
2271        }
2272        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
2273            PolicyControl.reloadFromSetting(mContext);
2274        }
2275        if (updateRotation) {
2276            updateRotation(true);
2277        }
2278    }
2279
2280    private void updateWakeGestureListenerLp() {
2281        if (shouldEnableWakeGestureLp()) {
2282            mWakeGestureListener.requestWakeUpTrigger();
2283        } else {
2284            mWakeGestureListener.cancelWakeUpTrigger();
2285        }
2286    }
2287
2288    private boolean shouldEnableWakeGestureLp() {
2289        return mWakeGestureEnabledSetting && !mAwake
2290                && (!mLidControlsSleep || mLidState != LID_CLOSED)
2291                && mWakeGestureListener.isSupported();
2292    }
2293
2294    private void enablePointerLocation() {
2295        if (mPointerLocationView == null) {
2296            mPointerLocationView = new PointerLocationView(mContext);
2297            mPointerLocationView.setPrintCoords(false);
2298            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
2299                    WindowManager.LayoutParams.MATCH_PARENT,
2300                    WindowManager.LayoutParams.MATCH_PARENT);
2301            lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
2302            lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
2303                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
2304                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2305                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
2306            if (ActivityManager.isHighEndGfx()) {
2307                lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
2308                lp.privateFlags |=
2309                        WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
2310            }
2311            lp.format = PixelFormat.TRANSLUCENT;
2312            lp.setTitle("PointerLocation");
2313            WindowManager wm = (WindowManager) mContext.getSystemService(WINDOW_SERVICE);
2314            lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
2315            wm.addView(mPointerLocationView, lp);
2316            mWindowManagerFuncs.registerPointerEventListener(mPointerLocationView);
2317        }
2318    }
2319
2320    private void disablePointerLocation() {
2321        if (mPointerLocationView != null) {
2322            mWindowManagerFuncs.unregisterPointerEventListener(mPointerLocationView);
2323            WindowManager wm = (WindowManager) mContext.getSystemService(WINDOW_SERVICE);
2324            wm.removeView(mPointerLocationView);
2325            mPointerLocationView = null;
2326        }
2327    }
2328
2329    private int readRotation(int resID) {
2330        try {
2331            int rotation = mContext.getResources().getInteger(resID);
2332            switch (rotation) {
2333                case 0:
2334                    return Surface.ROTATION_0;
2335                case 90:
2336                    return Surface.ROTATION_90;
2337                case 180:
2338                    return Surface.ROTATION_180;
2339                case 270:
2340                    return Surface.ROTATION_270;
2341            }
2342        } catch (Resources.NotFoundException e) {
2343            // fall through
2344        }
2345        return -1;
2346    }
2347
2348    /** {@inheritDoc} */
2349    @Override
2350    public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) {
2351        int type = attrs.type;
2352
2353        outAppOp[0] = AppOpsManager.OP_NONE;
2354
2355        if (!((type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW)
2356                || (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW)
2357                || (type >= FIRST_SYSTEM_WINDOW && type <= LAST_SYSTEM_WINDOW))) {
2358            return WindowManagerGlobal.ADD_INVALID_TYPE;
2359        }
2360
2361        if (type < FIRST_SYSTEM_WINDOW || type > LAST_SYSTEM_WINDOW) {
2362            // Window manager will make sure these are okay.
2363            return ADD_OKAY;
2364        }
2365
2366        if (!isSystemAlertWindowType(type)) {
2367            switch (type) {
2368                case TYPE_TOAST:
2369                    // Only apps that target older than O SDK can add window without a token, after
2370                    // that we require a token so apps cannot add toasts directly as the token is
2371                    // added by the notification system.
2372                    // Window manager does the checking for this.
2373                    outAppOp[0] = OP_TOAST_WINDOW;
2374                    return ADD_OKAY;
2375                case TYPE_DREAM:
2376                case TYPE_INPUT_METHOD:
2377                case TYPE_WALLPAPER:
2378                case TYPE_PRESENTATION:
2379                case TYPE_PRIVATE_PRESENTATION:
2380                case TYPE_VOICE_INTERACTION:
2381                case TYPE_ACCESSIBILITY_OVERLAY:
2382                case TYPE_QS_DIALOG:
2383                    // The window manager will check these.
2384                    return ADD_OKAY;
2385            }
2386            return mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
2387                    == PERMISSION_GRANTED ? ADD_OKAY : ADD_PERMISSION_DENIED;
2388        }
2389
2390        // Things get a little more interesting for alert windows...
2391        outAppOp[0] = OP_SYSTEM_ALERT_WINDOW;
2392
2393        final int callingUid = Binder.getCallingUid();
2394        // system processes will be automatically granted privilege to draw
2395        if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
2396            return ADD_OKAY;
2397        }
2398
2399        ApplicationInfo appInfo;
2400        try {
2401            appInfo = mContext.getPackageManager().getApplicationInfo(attrs.packageName,
2402                            UserHandle.getUserId(callingUid));
2403        } catch (PackageManager.NameNotFoundException e) {
2404            appInfo = null;
2405        }
2406
2407        if (appInfo == null || (type != TYPE_APPLICATION_OVERLAY && appInfo.targetSdkVersion >= O)) {
2408            /**
2409             * Apps targeting >= {@link Build.VERSION_CODES#O} are required to hold
2410             * {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW} (system signature apps)
2411             * permission to add alert windows that aren't
2412             * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY}.
2413             */
2414            return (mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
2415                    == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
2416        }
2417
2418        // check if user has enabled this operation. SecurityException will be thrown if this app
2419        // has not been allowed by the user
2420        final int mode = mAppOpsManager.checkOpNoThrow(outAppOp[0], callingUid, attrs.packageName);
2421        switch (mode) {
2422            case AppOpsManager.MODE_ALLOWED:
2423            case AppOpsManager.MODE_IGNORED:
2424                // although we return ADD_OKAY for MODE_IGNORED, the added window will
2425                // actually be hidden in WindowManagerService
2426                return ADD_OKAY;
2427            case AppOpsManager.MODE_ERRORED:
2428                // Don't crash legacy apps
2429                if (appInfo.targetSdkVersion < M) {
2430                    return ADD_OKAY;
2431                }
2432                return ADD_PERMISSION_DENIED;
2433            default:
2434                // in the default mode, we will make a decision here based on
2435                // checkCallingPermission()
2436                return (mContext.checkCallingOrSelfPermission(SYSTEM_ALERT_WINDOW)
2437                        == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
2438        }
2439    }
2440
2441    @Override
2442    public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) {
2443
2444        // If this switch statement is modified, modify the comment in the declarations of
2445        // the type in {@link WindowManager.LayoutParams} as well.
2446        switch (attrs.type) {
2447            default:
2448                // These are the windows that by default are shown only to the user that created
2449                // them. If this needs to be overridden, set
2450                // {@link WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS} in
2451                // {@link WindowManager.LayoutParams}. Note that permission
2452                // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well.
2453                if ((attrs.privateFlags & PRIVATE_FLAG_SHOW_FOR_ALL_USERS) == 0) {
2454                    return true;
2455                }
2456                break;
2457
2458            // These are the windows that by default are shown to all users. However, to
2459            // protect against spoofing, check permissions below.
2460            case TYPE_APPLICATION_STARTING:
2461            case TYPE_BOOT_PROGRESS:
2462            case TYPE_DISPLAY_OVERLAY:
2463            case TYPE_INPUT_CONSUMER:
2464            case TYPE_KEYGUARD_DIALOG:
2465            case TYPE_MAGNIFICATION_OVERLAY:
2466            case TYPE_NAVIGATION_BAR:
2467            case TYPE_NAVIGATION_BAR_PANEL:
2468            case TYPE_PHONE:
2469            case TYPE_POINTER:
2470            case TYPE_PRIORITY_PHONE:
2471            case TYPE_SEARCH_BAR:
2472            case TYPE_STATUS_BAR:
2473            case TYPE_STATUS_BAR_PANEL:
2474            case TYPE_STATUS_BAR_SUB_PANEL:
2475            case TYPE_SYSTEM_DIALOG:
2476            case TYPE_VOLUME_OVERLAY:
2477            case TYPE_PRESENTATION:
2478            case TYPE_PRIVATE_PRESENTATION:
2479            case TYPE_DOCK_DIVIDER:
2480                break;
2481        }
2482
2483        // Check if third party app has set window to system window type.
2484        return mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW) != PERMISSION_GRANTED;
2485    }
2486
2487    @Override
2488    public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
2489        switch (attrs.type) {
2490            case TYPE_SYSTEM_OVERLAY:
2491            case TYPE_SECURE_SYSTEM_OVERLAY:
2492                // These types of windows can't receive input events.
2493                attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2494                        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
2495                attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
2496                break;
2497            case TYPE_STATUS_BAR:
2498
2499                // If the Keyguard is in a hidden state (occluded by another window), we force to
2500                // remove the wallpaper and keyguard flag so that any change in-flight after setting
2501                // the keyguard as occluded wouldn't set these flags again.
2502                // See {@link #processKeyguardSetHiddenResultLw}.
2503                if (mKeyguardOccluded) {
2504                    attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
2505                    attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2506                }
2507                break;
2508
2509            case TYPE_SCREENSHOT:
2510                attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
2511                break;
2512
2513            case TYPE_TOAST:
2514                // While apps should use the dedicated toast APIs to add such windows
2515                // it possible legacy apps to add the window directly. Therefore, we
2516                // make windows added directly by the app behave as a toast as much
2517                // as possible in terms of timeout and animation.
2518                if (attrs.hideTimeoutMilliseconds < 0
2519                        || attrs.hideTimeoutMilliseconds > TOAST_WINDOW_TIMEOUT) {
2520                    attrs.hideTimeoutMilliseconds = TOAST_WINDOW_TIMEOUT;
2521                }
2522                attrs.windowAnimations = com.android.internal.R.style.Animation_Toast;
2523                break;
2524        }
2525
2526        if (attrs.type != TYPE_STATUS_BAR) {
2527            // The status bar is the only window allowed to exhibit keyguard behavior.
2528            attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2529        }
2530
2531        if (ActivityManager.isHighEndGfx()) {
2532            if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
2533                attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
2534            }
2535            final boolean forceWindowDrawsStatusBarBackground =
2536                    (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND)
2537                            != 0;
2538            if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
2539                    || forceWindowDrawsStatusBarBackground
2540                            && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) {
2541                attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2542            }
2543        }
2544    }
2545
2546    void readLidState() {
2547        mLidState = mWindowManagerFuncs.getLidState();
2548    }
2549
2550    private void readCameraLensCoverState() {
2551        mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState();
2552    }
2553
2554    private boolean isHidden(int accessibilityMode) {
2555        switch (accessibilityMode) {
2556            case 1:
2557                return mLidState == LID_CLOSED;
2558            case 2:
2559                return mLidState == LID_OPEN;
2560            default:
2561                return false;
2562        }
2563    }
2564
2565    /** {@inheritDoc} */
2566    @Override
2567    public void adjustConfigurationLw(Configuration config, int keyboardPresence,
2568            int navigationPresence) {
2569        mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0;
2570
2571        readConfigurationDependentBehaviors();
2572        readLidState();
2573
2574        if (config.keyboard == Configuration.KEYBOARD_NOKEYS
2575                || (keyboardPresence == PRESENCE_INTERNAL
2576                        && isHidden(mLidKeyboardAccessibility))) {
2577            config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
2578            if (!mHasSoftInput) {
2579                config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
2580            }
2581        }
2582
2583        if (config.navigation == Configuration.NAVIGATION_NONAV
2584                || (navigationPresence == PRESENCE_INTERNAL
2585                        && isHidden(mLidNavigationAccessibility))) {
2586            config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
2587        }
2588    }
2589
2590    @Override
2591    public void onConfigurationChanged() {
2592        // TODO(multi-display): Define policy for secondary displays.
2593        final Resources res = mContext.getResources();
2594
2595        mStatusBarHeight =
2596                res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
2597
2598        // Height of the navigation bar when presented horizontally at bottom
2599        mNavigationBarHeightForRotationDefault[mPortraitRotation] =
2600        mNavigationBarHeightForRotationDefault[mUpsideDownRotation] =
2601                res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
2602        mNavigationBarHeightForRotationDefault[mLandscapeRotation] =
2603        mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize(
2604                com.android.internal.R.dimen.navigation_bar_height_landscape);
2605
2606        // Width of the navigation bar when presented vertically along one side
2607        mNavigationBarWidthForRotationDefault[mPortraitRotation] =
2608        mNavigationBarWidthForRotationDefault[mUpsideDownRotation] =
2609        mNavigationBarWidthForRotationDefault[mLandscapeRotation] =
2610        mNavigationBarWidthForRotationDefault[mSeascapeRotation] =
2611                res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
2612
2613        if (ALTERNATE_CAR_MODE_NAV_SIZE) {
2614            // Height of the navigation bar when presented horizontally at bottom
2615            mNavigationBarHeightForRotationInCarMode[mPortraitRotation] =
2616            mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] =
2617                    res.getDimensionPixelSize(
2618                            com.android.internal.R.dimen.navigation_bar_height_car_mode);
2619            mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] =
2620            mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize(
2621                    com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode);
2622
2623            // Width of the navigation bar when presented vertically along one side
2624            mNavigationBarWidthForRotationInCarMode[mPortraitRotation] =
2625            mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] =
2626            mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] =
2627            mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] =
2628                    res.getDimensionPixelSize(
2629                            com.android.internal.R.dimen.navigation_bar_width_car_mode);
2630        }
2631    }
2632
2633    @Override
2634    public int getMaxWallpaperLayer() {
2635        return getWindowLayerFromTypeLw(TYPE_STATUS_BAR);
2636    }
2637
2638    private int getNavigationBarWidth(int rotation, int uiMode) {
2639        if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2640            return mNavigationBarWidthForRotationInCarMode[rotation];
2641        } else {
2642            return mNavigationBarWidthForRotationDefault[rotation];
2643        }
2644    }
2645
2646    @Override
2647    public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
2648            int displayId) {
2649        // TODO(multi-display): Support navigation bar on secondary displays.
2650        if (displayId == Display.DEFAULT_DISPLAY && mHasNavigationBar) {
2651            // For a basic navigation bar, when we are in landscape mode we place
2652            // the navigation bar to the side.
2653            if (mNavigationBarCanMove && fullWidth > fullHeight) {
2654                return fullWidth - getNavigationBarWidth(rotation, uiMode);
2655            }
2656        }
2657        return fullWidth;
2658    }
2659
2660    private int getNavigationBarHeight(int rotation, int uiMode) {
2661        if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2662            return mNavigationBarHeightForRotationInCarMode[rotation];
2663        } else {
2664            return mNavigationBarHeightForRotationDefault[rotation];
2665        }
2666    }
2667
2668    @Override
2669    public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
2670            int displayId) {
2671        // TODO(multi-display): Support navigation bar on secondary displays.
2672        if (displayId == Display.DEFAULT_DISPLAY && mHasNavigationBar) {
2673            // For a basic navigation bar, when we are in portrait mode we place
2674            // the navigation bar to the bottom.
2675            if (!mNavigationBarCanMove || fullWidth < fullHeight) {
2676                return fullHeight - getNavigationBarHeight(rotation, uiMode);
2677            }
2678        }
2679        return fullHeight;
2680    }
2681
2682    @Override
2683    public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
2684            int displayId) {
2685        return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode, displayId);
2686    }
2687
2688    @Override
2689    public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
2690            int displayId) {
2691        // There is a separate status bar at the top of the display.  We don't count that as part
2692        // of the fixed decor, since it can hide; however, for purposes of configurations,
2693        // we do want to exclude it since applications can't generally use that part
2694        // of the screen.
2695        // TODO(multi-display): Support status bars on secondary displays.
2696        if (displayId == Display.DEFAULT_DISPLAY) {
2697            return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayId)
2698                    - mStatusBarHeight;
2699        }
2700        return fullHeight;
2701    }
2702
2703    @Override
2704    public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) {
2705        return attrs.type == TYPE_STATUS_BAR;
2706    }
2707
2708    @Override
2709    public boolean canBeHiddenByKeyguardLw(WindowState win) {
2710        switch (win.getAttrs().type) {
2711            case TYPE_STATUS_BAR:
2712            case TYPE_NAVIGATION_BAR:
2713            case TYPE_WALLPAPER:
2714            case TYPE_DREAM:
2715                return false;
2716            default:
2717                // Hide only windows below the keyguard host window.
2718                return getWindowLayerLw(win) < getWindowLayerFromTypeLw(TYPE_STATUS_BAR);
2719        }
2720    }
2721
2722    private boolean shouldBeHiddenByKeyguard(WindowState win, WindowState imeTarget) {
2723
2724        // Keyguard visibility of window from activities are determined over activity visibility.
2725        if (win.getAppToken() != null) {
2726            return false;
2727        }
2728
2729        final LayoutParams attrs = win.getAttrs();
2730        final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleLw() &&
2731                ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0
2732                        || !canBeHiddenByKeyguardLw(imeTarget));
2733
2734        // Show IME over the keyguard if the target allows it
2735        boolean allowWhenLocked = (win.isInputMethodWindow() || imeTarget == this)
2736                && showImeOverKeyguard;;
2737
2738        if (isKeyguardLocked() && isKeyguardOccluded()) {
2739            // Show SHOW_WHEN_LOCKED windows if Keyguard is occluded.
2740            allowWhenLocked |= (attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
2741                    // Show error dialogs over apps that are shown on lockscreen
2742                    || (attrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
2743        }
2744
2745        boolean keyguardLocked = isKeyguardLocked();
2746        boolean hideDockDivider = attrs.type == TYPE_DOCK_DIVIDER
2747                && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
2748        return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == Display.DEFAULT_DISPLAY)
2749                || hideDockDivider;
2750    }
2751
2752    /** {@inheritDoc} */
2753    @Override
2754    public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme,
2755            CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon,
2756            int logo, int windowFlags, Configuration overrideConfig, int displayId) {
2757        if (!SHOW_SPLASH_SCREENS) {
2758            return null;
2759        }
2760        if (packageName == null) {
2761            return null;
2762        }
2763
2764        WindowManager wm = null;
2765        View view = null;
2766
2767        try {
2768            Context context = mContext;
2769            if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen " + packageName
2770                    + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
2771                    + Integer.toHexString(theme));
2772
2773            // Obtain proper context to launch on the right display.
2774            final Context displayContext = getDisplayContext(context, displayId);
2775            if (displayContext == null) {
2776                // Can't show splash screen on requested display, so skip showing at all.
2777                return null;
2778            }
2779            context = displayContext;
2780
2781            if (theme != context.getThemeResId() || labelRes != 0) {
2782                try {
2783                    context = context.createPackageContext(packageName, 0);
2784                    context.setTheme(theme);
2785                } catch (PackageManager.NameNotFoundException e) {
2786                    // Ignore
2787                }
2788            }
2789
2790            if (overrideConfig != null && !overrideConfig.equals(EMPTY)) {
2791                if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: creating context based"
2792                        + " on overrideConfig" + overrideConfig + " for splash screen");
2793                final Context overrideContext = context.createConfigurationContext(overrideConfig);
2794                overrideContext.setTheme(theme);
2795                final TypedArray typedArray = overrideContext.obtainStyledAttributes(
2796                        com.android.internal.R.styleable.Window);
2797                final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
2798                if (resId != 0 && overrideContext.getDrawable(resId) != null) {
2799                    // We want to use the windowBackground for the override context if it is
2800                    // available, otherwise we use the default one to make sure a themed starting
2801                    // window is displayed for the app.
2802                    if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: apply overrideConfig"
2803                            + overrideConfig + " to starting window resId=" + resId);
2804                    context = overrideContext;
2805                }
2806            }
2807
2808            final PhoneWindow win = new PhoneWindow(context);
2809            win.setIsStartingWindow(true);
2810
2811            CharSequence label = context.getResources().getText(labelRes, null);
2812            // Only change the accessibility title if the label is localized
2813            if (label != null) {
2814                win.setTitle(label, true);
2815            } else {
2816                win.setTitle(nonLocalizedLabel, false);
2817            }
2818
2819            win.setType(
2820                WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
2821
2822            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
2823                // Assumes it's safe to show starting windows of launched apps while
2824                // the keyguard is being hidden. This is okay because starting windows never show
2825                // secret information.
2826                if (mKeyguardOccluded) {
2827                    windowFlags |= FLAG_SHOW_WHEN_LOCKED;
2828                }
2829            }
2830
2831            // Force the window flags: this is a fake window, so it is not really
2832            // touchable or focusable by the user.  We also add in the ALT_FOCUSABLE_IM
2833            // flag because we do know that the next window will take input
2834            // focus, so we want to get the IME window up on top of us right away.
2835            win.setFlags(
2836                windowFlags|
2837                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2838                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2839                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
2840                windowFlags|
2841                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2842                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2843                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
2844
2845            win.setDefaultIcon(icon);
2846            win.setDefaultLogo(logo);
2847
2848            win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
2849                    WindowManager.LayoutParams.MATCH_PARENT);
2850
2851            final WindowManager.LayoutParams params = win.getAttributes();
2852            params.token = appToken;
2853            params.packageName = packageName;
2854            params.windowAnimations = win.getWindowStyle().getResourceId(
2855                    com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
2856            params.privateFlags |=
2857                    WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
2858            params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
2859
2860            if (!compatInfo.supportsScreen()) {
2861                params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
2862            }
2863
2864            params.setTitle("Splash Screen " + packageName);
2865            wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
2866            view = win.getDecorView();
2867
2868            if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "Adding splash screen window for "
2869                + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null));
2870
2871            wm.addView(view, params);
2872
2873            // Only return the view if it was successfully added to the
2874            // window manager... which we can tell by it having a parent.
2875            return view.getParent() != null ? new SplashScreenSurface(view, appToken) : null;
2876        } catch (WindowManager.BadTokenException e) {
2877            // ignore
2878            Log.w(TAG, appToken + " already running, starting window not displayed. " +
2879                    e.getMessage());
2880        } catch (RuntimeException e) {
2881            // don't crash if something else bad happens, for example a
2882            // failure loading resources because we are loading from an app
2883            // on external storage that has been unmounted.
2884            Log.w(TAG, appToken + " failed creating starting window", e);
2885        } finally {
2886            if (view != null && view.getParent() == null) {
2887                Log.w(TAG, "view not successfully added to wm, removing view");
2888                wm.removeViewImmediate(view);
2889            }
2890        }
2891
2892        return null;
2893    }
2894
2895    /** Obtain proper context for showing splash screen on the provided display. */
2896    private Context getDisplayContext(Context context, int displayId) {
2897        if (displayId == Display.DEFAULT_DISPLAY) {
2898            // The default context fits.
2899            return context;
2900        }
2901
2902        final DisplayManager dm = (DisplayManager) context.getSystemService(DISPLAY_SERVICE);
2903        final Display targetDisplay = dm.getDisplay(displayId);
2904        if (targetDisplay == null) {
2905            // Failed to obtain the non-default display where splash screen should be shown,
2906            // lets not show at all.
2907            return null;
2908        }
2909
2910        return context.createDisplayContext(targetDisplay);
2911    }
2912
2913    /**
2914     * Preflight adding a window to the system.
2915     *
2916     * Currently enforces that three window types are singletons:
2917     * <ul>
2918     * <li>STATUS_BAR_TYPE</li>
2919     * <li>KEYGUARD_TYPE</li>
2920     * </ul>
2921     *
2922     * @param win The window to be added
2923     * @param attrs Information about the window to be added
2924     *
2925     * @return If ok, WindowManagerImpl.ADD_OKAY.  If too many singletons,
2926     * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
2927     */
2928    @Override
2929    public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
2930        switch (attrs.type) {
2931            case TYPE_STATUS_BAR:
2932                mContext.enforceCallingOrSelfPermission(
2933                        android.Manifest.permission.STATUS_BAR_SERVICE,
2934                        "PhoneWindowManager");
2935                if (mStatusBar != null) {
2936                    if (mStatusBar.isAlive()) {
2937                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2938                    }
2939                }
2940                mStatusBar = win;
2941                mStatusBarController.setWindow(win);
2942                break;
2943            case TYPE_NAVIGATION_BAR:
2944                mContext.enforceCallingOrSelfPermission(
2945                        android.Manifest.permission.STATUS_BAR_SERVICE,
2946                        "PhoneWindowManager");
2947                if (mNavigationBar != null) {
2948                    if (mNavigationBar.isAlive()) {
2949                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2950                    }
2951                }
2952                mNavigationBar = win;
2953                mNavigationBarController.setWindow(win);
2954                mNavigationBarController.setOnBarVisibilityChangedListener(
2955                        mNavBarVisibilityListener);
2956                if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
2957                break;
2958            case TYPE_NAVIGATION_BAR_PANEL:
2959            case TYPE_STATUS_BAR_PANEL:
2960            case TYPE_STATUS_BAR_SUB_PANEL:
2961            case TYPE_VOICE_INTERACTION_STARTING:
2962                mContext.enforceCallingOrSelfPermission(
2963                        android.Manifest.permission.STATUS_BAR_SERVICE,
2964                        "PhoneWindowManager");
2965                break;
2966        }
2967        return ADD_OKAY;
2968    }
2969
2970    /** {@inheritDoc} */
2971    @Override
2972    public void removeWindowLw(WindowState win) {
2973        if (mStatusBar == win) {
2974            mStatusBar = null;
2975            mStatusBarController.setWindow(null);
2976        } else if (mNavigationBar == win) {
2977            mNavigationBar = null;
2978            mNavigationBarController.setWindow(null);
2979        }
2980    }
2981
2982    static final boolean PRINT_ANIM = false;
2983
2984    /** {@inheritDoc} */
2985    @Override
2986    public int selectAnimationLw(WindowState win, int transit) {
2987        if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
2988              + ": transit=" + transit);
2989        if (win == mStatusBar) {
2990            boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
2991            if (transit == TRANSIT_EXIT
2992                    || transit == TRANSIT_HIDE) {
2993                return isKeyguard ? -1 : R.anim.dock_top_exit;
2994            } else if (transit == TRANSIT_ENTER
2995                    || transit == TRANSIT_SHOW) {
2996                return isKeyguard ? -1 : R.anim.dock_top_enter;
2997            }
2998        } else if (win == mNavigationBar) {
2999            if (win.getAttrs().windowAnimations != 0) {
3000                return 0;
3001            }
3002            // This can be on either the bottom or the right or the left.
3003            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
3004                if (transit == TRANSIT_EXIT
3005                        || transit == TRANSIT_HIDE) {
3006                    if (isKeyguardShowingAndNotOccluded()) {
3007                        return R.anim.dock_bottom_exit_keyguard;
3008                    } else {
3009                        return R.anim.dock_bottom_exit;
3010                    }
3011                } else if (transit == TRANSIT_ENTER
3012                        || transit == TRANSIT_SHOW) {
3013                    return R.anim.dock_bottom_enter;
3014                }
3015            } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
3016                if (transit == TRANSIT_EXIT
3017                        || transit == TRANSIT_HIDE) {
3018                    return R.anim.dock_right_exit;
3019                } else if (transit == TRANSIT_ENTER
3020                        || transit == TRANSIT_SHOW) {
3021                    return R.anim.dock_right_enter;
3022                }
3023            } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
3024                if (transit == TRANSIT_EXIT
3025                        || transit == TRANSIT_HIDE) {
3026                    return R.anim.dock_left_exit;
3027                } else if (transit == TRANSIT_ENTER
3028                        || transit == TRANSIT_SHOW) {
3029                    return R.anim.dock_left_enter;
3030                }
3031            }
3032        } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) {
3033            return selectDockedDividerAnimationLw(win, transit);
3034        }
3035
3036        if (transit == TRANSIT_PREVIEW_DONE) {
3037            if (win.hasAppShownWindows()) {
3038                if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
3039                return com.android.internal.R.anim.app_starting_exit;
3040            }
3041        } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
3042                && transit == TRANSIT_ENTER) {
3043            // Special case: we are animating in a dream, while the keyguard
3044            // is shown.  We don't want an animation on the dream, because
3045            // we need it shown immediately with the keyguard animating away
3046            // to reveal it.
3047            return -1;
3048        }
3049
3050        return 0;
3051    }
3052
3053    private int selectDockedDividerAnimationLw(WindowState win, int transit) {
3054        int insets = mWindowManagerFuncs.getDockedDividerInsetsLw();
3055
3056        // If the divider is behind the navigation bar, don't animate.
3057        final Rect frame = win.getFrameLw();
3058        final boolean behindNavBar = mNavigationBar != null
3059                && ((mNavigationBarPosition == NAV_BAR_BOTTOM
3060                        && frame.top + insets >= mNavigationBar.getFrameLw().top)
3061                || (mNavigationBarPosition == NAV_BAR_RIGHT
3062                        && frame.left + insets >= mNavigationBar.getFrameLw().left)
3063                || (mNavigationBarPosition == NAV_BAR_LEFT
3064                        && frame.right - insets <= mNavigationBar.getFrameLw().right));
3065        final boolean landscape = frame.height() > frame.width();
3066        final boolean offscreenLandscape = landscape && (frame.right - insets <= 0
3067                || frame.left + insets >= win.getDisplayFrameLw().right);
3068        final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0
3069                || frame.bottom + insets >= win.getDisplayFrameLw().bottom);
3070        final boolean offscreen = offscreenLandscape || offscreenPortrait;
3071        if (behindNavBar || offscreen) {
3072            return 0;
3073        }
3074        if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
3075            return R.anim.fade_in;
3076        } else if (transit == TRANSIT_EXIT) {
3077            return R.anim.fade_out;
3078        } else {
3079            return 0;
3080        }
3081    }
3082
3083    @Override
3084    public void selectRotationAnimationLw(int anim[]) {
3085        if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
3086                + mTopFullscreenOpaqueWindowState + " rotationAnimation="
3087                + (mTopFullscreenOpaqueWindowState == null ?
3088                        "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation));
3089        if (mTopFullscreenOpaqueWindowState != null) {
3090            int animationHint = mTopFullscreenOpaqueWindowState.getRotationAnimationHint();
3091            if (animationHint < 0 && mTopIsFullscreen) {
3092                animationHint = mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation;
3093            }
3094            switch (animationHint) {
3095                case ROTATION_ANIMATION_CROSSFADE:
3096                case ROTATION_ANIMATION_SEAMLESS: // Crossfade is fallback for seamless.
3097                    anim[0] = R.anim.rotation_animation_xfade_exit;
3098                    anim[1] = R.anim.rotation_animation_enter;
3099                    break;
3100                case ROTATION_ANIMATION_JUMPCUT:
3101                    anim[0] = R.anim.rotation_animation_jump_exit;
3102                    anim[1] = R.anim.rotation_animation_enter;
3103                    break;
3104                case ROTATION_ANIMATION_ROTATE:
3105                default:
3106                    anim[0] = anim[1] = 0;
3107                    break;
3108            }
3109        } else {
3110            anim[0] = anim[1] = 0;
3111        }
3112    }
3113
3114    @Override
3115    public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId,
3116            boolean forceDefault) {
3117        switch (exitAnimId) {
3118            case R.anim.rotation_animation_xfade_exit:
3119            case R.anim.rotation_animation_jump_exit:
3120                // These are the only cases that matter.
3121                if (forceDefault) {
3122                    return false;
3123                }
3124                int anim[] = new int[2];
3125                selectRotationAnimationLw(anim);
3126                return (exitAnimId == anim[0] && enterAnimId == anim[1]);
3127            default:
3128                return true;
3129        }
3130    }
3131
3132    @Override
3133    public Animation createHiddenByKeyguardExit(boolean onWallpaper,
3134            boolean goingToNotificationShade) {
3135        if (goingToNotificationShade) {
3136            return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
3137        }
3138
3139        AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ?
3140                    R.anim.lock_screen_behind_enter_wallpaper :
3141                    R.anim.lock_screen_behind_enter);
3142
3143        // TODO: Use XML interpolators when we have log interpolators available in XML.
3144        final List<Animation> animations = set.getAnimations();
3145        for (int i = animations.size() - 1; i >= 0; --i) {
3146            animations.get(i).setInterpolator(mLogDecelerateInterpolator);
3147        }
3148
3149        return set;
3150    }
3151
3152
3153    @Override
3154    public Animation createKeyguardWallpaperExit(boolean goingToNotificationShade) {
3155        if (goingToNotificationShade) {
3156            return null;
3157        } else {
3158            return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
3159        }
3160    }
3161
3162    private static void awakenDreams() {
3163        IDreamManager dreamManager = getDreamManager();
3164        if (dreamManager != null) {
3165            try {
3166                dreamManager.awaken();
3167            } catch (RemoteException e) {
3168                // fine, stay asleep then
3169            }
3170        }
3171    }
3172
3173    static IDreamManager getDreamManager() {
3174        return IDreamManager.Stub.asInterface(
3175                ServiceManager.checkService(DreamService.DREAM_SERVICE));
3176    }
3177
3178    TelecomManager getTelecommService() {
3179        return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
3180    }
3181
3182    static IAudioService getAudioService() {
3183        IAudioService audioService = IAudioService.Stub.asInterface(
3184                ServiceManager.checkService(Context.AUDIO_SERVICE));
3185        if (audioService == null) {
3186            Log.w(TAG, "Unable to find IAudioService interface.");
3187        }
3188        return audioService;
3189    }
3190
3191    boolean keyguardOn() {
3192        return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode();
3193    }
3194
3195    private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
3196            WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
3197            WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
3198        };
3199
3200    /** {@inheritDoc} */
3201    @Override
3202    public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
3203        final boolean keyguardOn = keyguardOn();
3204        final int keyCode = event.getKeyCode();
3205        final int repeatCount = event.getRepeatCount();
3206        final int metaState = event.getMetaState();
3207        final int flags = event.getFlags();
3208        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
3209        final boolean canceled = event.isCanceled();
3210
3211        if (DEBUG_INPUT) {
3212            Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
3213                    + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
3214                    + " canceled=" + canceled);
3215        }
3216
3217        // If we think we might have a volume down & power key chord on the way
3218        // but we're not sure, then tell the dispatcher to wait a little while and
3219        // try again later before dispatching.
3220        if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
3221            if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
3222                final long now = SystemClock.uptimeMillis();
3223                final long timeoutTime = mScreenshotChordVolumeDownKeyTime
3224                        + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
3225                if (now < timeoutTime) {
3226                    return timeoutTime - now;
3227                }
3228            }
3229            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3230                    && mScreenshotChordVolumeDownKeyConsumed) {
3231                if (!down) {
3232                    mScreenshotChordVolumeDownKeyConsumed = false;
3233                }
3234                return -1;
3235            }
3236        }
3237
3238        // If an accessibility shortcut might be partially complete, hold off dispatching until we
3239        // know if it is complete or not
3240        if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable()
3241                && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
3242            if (mScreenshotChordVolumeDownKeyTriggered ^ mA11yShortcutChordVolumeUpKeyTriggered) {
3243                final long now = SystemClock.uptimeMillis();
3244                final long timeoutTime = (mScreenshotChordVolumeDownKeyTriggered
3245                        ? mScreenshotChordVolumeDownKeyTime : mA11yShortcutChordVolumeUpKeyTime)
3246                        + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
3247                if (now < timeoutTime) {
3248                    return timeoutTime - now;
3249                }
3250            }
3251            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && mScreenshotChordVolumeDownKeyConsumed) {
3252                if (!down) {
3253                    mScreenshotChordVolumeDownKeyConsumed = false;
3254                }
3255                return -1;
3256            }
3257            if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mA11yShortcutChordVolumeUpKeyConsumed) {
3258                if (!down) {
3259                    mA11yShortcutChordVolumeUpKeyConsumed = false;
3260                }
3261                return -1;
3262            }
3263        }
3264
3265        // Cancel any pending meta actions if we see any other keys being pressed between the down
3266        // of the meta key and its corresponding up.
3267        if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
3268            mPendingMetaAction = false;
3269        }
3270        // Any key that is not Alt or Meta cancels Caps Lock combo tracking.
3271        if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) {
3272            mPendingCapsLockToggle = false;
3273        }
3274
3275        // First we always handle the home key here, so applications
3276        // can never break it, although if keyguard is on, we do let
3277        // it handle it, because that gives us the correct 5 second
3278        // timeout.
3279        if (keyCode == KeyEvent.KEYCODE_HOME) {
3280
3281            // If we have released the home key, and didn't do anything else
3282            // while it was pressed, then it is time to go home!
3283            if (!down) {
3284                cancelPreloadRecentApps();
3285
3286                mHomePressed = false;
3287                if (mHomeConsumed) {
3288                    mHomeConsumed = false;
3289                    return -1;
3290                }
3291
3292                if (canceled) {
3293                    Log.i(TAG, "Ignoring HOME; event canceled.");
3294                    return -1;
3295                }
3296
3297                // Delay handling home if a double-tap is possible.
3298                if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
3299                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
3300                    mHomeDoubleTapPending = true;
3301                    mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
3302                            ViewConfiguration.getDoubleTapTimeout());
3303                    return -1;
3304                }
3305
3306                handleShortPressOnHome();
3307                return -1;
3308            }
3309
3310            // If a system window has focus, then it doesn't make sense
3311            // right now to interact with applications.
3312            WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
3313            if (attrs != null) {
3314                final int type = attrs.type;
3315                if (type == TYPE_KEYGUARD_DIALOG
3316                        || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
3317                    // the "app" is keyguard, so give it the key
3318                    return 0;
3319                }
3320                final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
3321                for (int i=0; i<typeCount; i++) {
3322                    if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
3323                        // don't do anything, but also don't pass it to the app
3324                        return -1;
3325                    }
3326                }
3327            }
3328
3329            // Remember that home is pressed and handle special actions.
3330            if (repeatCount == 0) {
3331                mHomePressed = true;
3332                if (mHomeDoubleTapPending) {
3333                    mHomeDoubleTapPending = false;
3334                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
3335                    handleDoubleTapOnHome();
3336                } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI
3337                        || mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
3338                    preloadRecentApps();
3339                }
3340            } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
3341                if (!keyguardOn) {
3342                    handleLongPressOnHome(event.getDeviceId());
3343                }
3344            }
3345            return -1;
3346        } else if (keyCode == KeyEvent.KEYCODE_MENU) {
3347            // Hijack modified menu keys for debugging features
3348            final int chordBug = KeyEvent.META_SHIFT_ON;
3349
3350            if (down && repeatCount == 0) {
3351                if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
3352                    Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
3353                    mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
3354                            null, null, null, 0, null, null);
3355                    return -1;
3356                }
3357            }
3358        } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
3359            if (down) {
3360                if (repeatCount == 0) {
3361                    mSearchKeyShortcutPending = true;
3362                    mConsumeSearchKeyUp = false;
3363                }
3364            } else {
3365                mSearchKeyShortcutPending = false;
3366                if (mConsumeSearchKeyUp) {
3367                    mConsumeSearchKeyUp = false;
3368                    return -1;
3369                }
3370            }
3371            return 0;
3372        } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
3373            if (!keyguardOn) {
3374                if (down && repeatCount == 0) {
3375                    preloadRecentApps();
3376                } else if (!down) {
3377                    toggleRecentApps();
3378                }
3379            }
3380            return -1;
3381        } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) {
3382            if (down) {
3383                IStatusBarService service = getStatusBarService();
3384                if (service != null) {
3385                    try {
3386                        service.expandNotificationsPanel();
3387                    } catch (RemoteException e) {
3388                        // do nothing.
3389                    }
3390                }
3391            }
3392        } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed()
3393                && event.isCtrlPressed()) {
3394            if (down && repeatCount == 0) {
3395                int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION
3396                        : TAKE_SCREENSHOT_FULLSCREEN;
3397                mScreenshotRunnable.setScreenshotType(type);
3398                mHandler.post(mScreenshotRunnable);
3399                return -1;
3400            }
3401        } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
3402            if (down && repeatCount == 0 && !isKeyguardLocked()) {
3403                toggleKeyboardShortcutsMenu(event.getDeviceId());
3404            }
3405        } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
3406            if (down) {
3407                if (repeatCount == 0) {
3408                    mAssistKeyLongPressed = false;
3409                } else if (repeatCount == 1) {
3410                    mAssistKeyLongPressed = true;
3411                    if (!keyguardOn) {
3412                         launchAssistLongPressAction();
3413                    }
3414                }
3415            } else {
3416                if (mAssistKeyLongPressed) {
3417                    mAssistKeyLongPressed = false;
3418                } else {
3419                    if (!keyguardOn) {
3420                        launchAssistAction(null, event.getDeviceId());
3421                    }
3422                }
3423            }
3424            return -1;
3425        } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
3426            if (!down) {
3427                Intent voiceIntent;
3428                if (!keyguardOn) {
3429                    voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
3430                } else {
3431                    IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
3432                            ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
3433                    if (dic != null) {
3434                        try {
3435                            dic.exitIdle("voice-search");
3436                        } catch (RemoteException e) {
3437                        }
3438                    }
3439                    voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
3440                    voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
3441                }
3442                startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
3443            }
3444        } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
3445            if (down && repeatCount == 0) {
3446                mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
3447                mHandler.post(mScreenshotRunnable);
3448            }
3449            return -1;
3450        } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP
3451                || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) {
3452            if (down) {
3453                int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
3454
3455                // Disable autobrightness if it's on
3456                int auto = Settings.System.getIntForUser(
3457                        mContext.getContentResolver(),
3458                        Settings.System.SCREEN_BRIGHTNESS_MODE,
3459                        Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3460                        UserHandle.USER_CURRENT_OR_SELF);
3461                if (auto != 0) {
3462                    Settings.System.putIntForUser(mContext.getContentResolver(),
3463                            Settings.System.SCREEN_BRIGHTNESS_MODE,
3464                            Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3465                            UserHandle.USER_CURRENT_OR_SELF);
3466                }
3467
3468                int min = mPowerManager.getMinimumScreenBrightnessSetting();
3469                int max = mPowerManager.getMaximumScreenBrightnessSetting();
3470                int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction;
3471                int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
3472                        Settings.System.SCREEN_BRIGHTNESS,
3473                        mPowerManager.getDefaultScreenBrightnessSetting(),
3474                        UserHandle.USER_CURRENT_OR_SELF);
3475                brightness += step;
3476                // Make sure we don't go beyond the limits.
3477                brightness = Math.min(max, brightness);
3478                brightness = Math.max(min, brightness);
3479
3480                Settings.System.putIntForUser(mContext.getContentResolver(),
3481                        Settings.System.SCREEN_BRIGHTNESS, brightness,
3482                        UserHandle.USER_CURRENT_OR_SELF);
3483                startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
3484                        UserHandle.CURRENT_OR_SELF);
3485            }
3486            return -1;
3487        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
3488                || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3489                || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
3490            if (mUseTvRouting) {
3491                // On TVs volume keys never go to the foreground app.
3492                dispatchDirectAudioEvent(event);
3493                return -1;
3494            }
3495        } else if (keyCode == KeyEvent.KEYCODE_TAB && event.isMetaPressed()) {
3496            // Pass through keyboard navigation keys.
3497            return 0;
3498        } else if (mHasFeatureLeanback && interceptBugreportGestureTv(keyCode, down)) {
3499            return -1;
3500        }
3501
3502        // Toggle Caps Lock on META-ALT.
3503        boolean actionTriggered = false;
3504        if (KeyEvent.isModifierKey(keyCode)) {
3505            if (!mPendingCapsLockToggle) {
3506                // Start tracking meta state for combo.
3507                mInitialMetaState = mMetaState;
3508                mPendingCapsLockToggle = true;
3509            } else if (event.getAction() == KeyEvent.ACTION_UP) {
3510                int altOnMask = mMetaState & KeyEvent.META_ALT_MASK;
3511                int metaOnMask = mMetaState & KeyEvent.META_META_MASK;
3512
3513                // Check for Caps Lock toggle
3514                if ((metaOnMask != 0) && (altOnMask != 0)) {
3515                    // Check if nothing else is pressed
3516                    if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) {
3517                        // Handle Caps Lock Toggle
3518                        mInputManagerInternal.toggleCapsLock(event.getDeviceId());
3519                        actionTriggered = true;
3520                    }
3521                }
3522
3523                // Always stop tracking when key goes up.
3524                mPendingCapsLockToggle = false;
3525            }
3526        }
3527        // Store current meta state to be able to evaluate it later.
3528        mMetaState = metaState;
3529
3530        if (actionTriggered) {
3531            return -1;
3532        }
3533
3534        if (KeyEvent.isMetaKey(keyCode)) {
3535            if (down) {
3536                mPendingMetaAction = true;
3537            } else if (mPendingMetaAction) {
3538                launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId());
3539            }
3540            return -1;
3541        }
3542
3543        // Shortcuts are invoked through Search+key, so intercept those here
3544        // Any printing key that is chorded with Search should be consumed
3545        // even if no shortcut was invoked.  This prevents text from being
3546        // inadvertently inserted when using a keyboard that has built-in macro
3547        // shortcut keys (that emit Search+x) and some of them are not registered.
3548        if (mSearchKeyShortcutPending) {
3549            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3550            if (kcm.isPrintingKey(keyCode)) {
3551                mConsumeSearchKeyUp = true;
3552                mSearchKeyShortcutPending = false;
3553                if (down && repeatCount == 0 && !keyguardOn) {
3554                    Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
3555                    if (shortcutIntent != null) {
3556                        shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3557                        try {
3558                            startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3559                            dismissKeyboardShortcutsMenu();
3560                        } catch (ActivityNotFoundException ex) {
3561                            Slog.w(TAG, "Dropping shortcut key combination because "
3562                                    + "the activity to which it is registered was not found: "
3563                                    + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);
3564                        }
3565                    } else {
3566                        Slog.i(TAG, "Dropping unregistered shortcut key combination: "
3567                                + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));
3568                    }
3569                }
3570                return -1;
3571            }
3572        }
3573
3574        // Invoke shortcuts using Meta.
3575        if (down && repeatCount == 0 && !keyguardOn
3576                && (metaState & KeyEvent.META_META_ON) != 0) {
3577            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3578            if (kcm.isPrintingKey(keyCode)) {
3579                Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
3580                        metaState & ~(KeyEvent.META_META_ON
3581                                | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
3582                if (shortcutIntent != null) {
3583                    shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3584                    try {
3585                        startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3586                        dismissKeyboardShortcutsMenu();
3587                    } catch (ActivityNotFoundException ex) {
3588                        Slog.w(TAG, "Dropping shortcut key combination because "
3589                                + "the activity to which it is registered was not found: "
3590                                + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
3591                    }
3592                    return -1;
3593                }
3594            }
3595        }
3596
3597        // Handle application launch keys.
3598        if (down && repeatCount == 0 && !keyguardOn) {
3599            String category = sApplicationLaunchKeyCategories.get(keyCode);
3600            if (category != null) {
3601                Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
3602                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3603                try {
3604                    startActivityAsUser(intent, UserHandle.CURRENT);
3605                    dismissKeyboardShortcutsMenu();
3606                } catch (ActivityNotFoundException ex) {
3607                    Slog.w(TAG, "Dropping application launch key because "
3608                            + "the activity to which it is registered was not found: "
3609                            + "keyCode=" + keyCode + ", category=" + category, ex);
3610                }
3611                return -1;
3612            }
3613        }
3614
3615        // Display task switcher for ALT-TAB.
3616        if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
3617            if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
3618                final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
3619                if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
3620                    mRecentAppsHeldModifiers = shiftlessModifiers;
3621                    showRecentApps(true, false);
3622                    return -1;
3623                }
3624            }
3625        } else if (!down && mRecentAppsHeldModifiers != 0
3626                && (metaState & mRecentAppsHeldModifiers) == 0) {
3627            mRecentAppsHeldModifiers = 0;
3628            hideRecentApps(true, false);
3629        }
3630
3631        // Handle input method switching.
3632        if (down && repeatCount == 0
3633                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3634                        || (keyCode == KeyEvent.KEYCODE_SPACE
3635                                && (metaState & KeyEvent.META_META_MASK) != 0))) {
3636            final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0;
3637            mWindowManagerFuncs.switchInputMethod(forwardDirection);
3638            return -1;
3639        }
3640        if (mLanguageSwitchKeyPressed && !down
3641                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3642                        || keyCode == KeyEvent.KEYCODE_SPACE)) {
3643            mLanguageSwitchKeyPressed = false;
3644            return -1;
3645        }
3646
3647        if (isValidGlobalKey(keyCode)
3648                && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
3649            return -1;
3650        }
3651
3652        if (down) {
3653            long shortcutCode = keyCode;
3654            if (event.isCtrlPressed()) {
3655                shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
3656            }
3657
3658            if (event.isAltPressed()) {
3659                shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
3660            }
3661
3662            if (event.isShiftPressed()) {
3663                shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
3664            }
3665
3666            if (event.isMetaPressed()) {
3667                shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE;
3668            }
3669
3670            IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode);
3671            if (shortcutService != null) {
3672                try {
3673                    if (isUserSetupComplete()) {
3674                        shortcutService.notifyShortcutKeyPressed(shortcutCode);
3675                    }
3676                } catch (RemoteException e) {
3677                    mShortcutKeyServices.delete(shortcutCode);
3678                }
3679                return -1;
3680            }
3681        }
3682
3683        // Reserve all the META modifier combos for system behavior
3684        if ((metaState & KeyEvent.META_META_ON) != 0) {
3685            return -1;
3686        }
3687
3688        // Let the application handle the key.
3689        return 0;
3690    }
3691
3692    /**
3693     * TV only: recognizes a remote control gesture for capturing a bug report.
3694     */
3695    private boolean interceptBugreportGestureTv(int keyCode, boolean down) {
3696        // The bugreport capture chord is a long press on DPAD CENTER and BACK simultaneously.
3697        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
3698            mBugreportTvKey1Pressed = down;
3699        } else if (keyCode == KeyEvent.KEYCODE_BACK) {
3700            mBugreportTvKey2Pressed = down;
3701        }
3702
3703        if (mBugreportTvKey1Pressed && mBugreportTvKey2Pressed) {
3704            if (!mBugreportTvScheduled) {
3705                mBugreportTvScheduled = true;
3706                Message msg = Message.obtain(mHandler, MSG_BUGREPORT_TV);
3707                msg.setAsynchronous(true);
3708                mHandler.sendMessageDelayed(msg, BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS);
3709            }
3710        } else if (mBugreportTvScheduled) {
3711            mHandler.removeMessages(MSG_BUGREPORT_TV);
3712            mBugreportTvScheduled = false;
3713        }
3714
3715        return mBugreportTvScheduled;
3716    }
3717
3718    private void takeBugreport() {
3719        if ("1".equals(SystemProperties.get("ro.debuggable"))
3720                || Settings.Global.getInt(mContext.getContentResolver(),
3721                        Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) == 1) {
3722            try {
3723                ActivityManager.getService()
3724                        .requestBugReport(ActivityManager.BUGREPORT_OPTION_INTERACTIVE);
3725            } catch (RemoteException e) {
3726                Slog.e(TAG, "Error taking bugreport", e);
3727            }
3728        }
3729    }
3730
3731    /** {@inheritDoc} */
3732    @Override
3733    public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
3734        // Note: This method is only called if the initial down was unhandled.
3735        if (DEBUG_INPUT) {
3736            Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
3737                    + ", flags=" + event.getFlags()
3738                    + ", keyCode=" + event.getKeyCode()
3739                    + ", scanCode=" + event.getScanCode()
3740                    + ", metaState=" + event.getMetaState()
3741                    + ", repeatCount=" + event.getRepeatCount()
3742                    + ", policyFlags=" + policyFlags);
3743        }
3744
3745        KeyEvent fallbackEvent = null;
3746        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3747            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3748            final int keyCode = event.getKeyCode();
3749            final int metaState = event.getMetaState();
3750            final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
3751                    && event.getRepeatCount() == 0;
3752
3753            // Check for fallback actions specified by the key character map.
3754            final FallbackAction fallbackAction;
3755            if (initialDown) {
3756                fallbackAction = kcm.getFallbackAction(keyCode, metaState);
3757            } else {
3758                fallbackAction = mFallbackActions.get(keyCode);
3759            }
3760
3761            if (fallbackAction != null) {
3762                if (DEBUG_INPUT) {
3763                    Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode
3764                            + " metaState=" + Integer.toHexString(fallbackAction.metaState));
3765                }
3766
3767                final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
3768                fallbackEvent = KeyEvent.obtain(
3769                        event.getDownTime(), event.getEventTime(),
3770                        event.getAction(), fallbackAction.keyCode,
3771                        event.getRepeatCount(), fallbackAction.metaState,
3772                        event.getDeviceId(), event.getScanCode(),
3773                        flags, event.getSource(), null);
3774
3775                if (!interceptFallback(win, fallbackEvent, policyFlags)) {
3776                    fallbackEvent.recycle();
3777                    fallbackEvent = null;
3778                }
3779
3780                if (initialDown) {
3781                    mFallbackActions.put(keyCode, fallbackAction);
3782                } else if (event.getAction() == KeyEvent.ACTION_UP) {
3783                    mFallbackActions.remove(keyCode);
3784                    fallbackAction.recycle();
3785                }
3786            }
3787        }
3788
3789        if (DEBUG_INPUT) {
3790            if (fallbackEvent == null) {
3791                Slog.d(TAG, "No fallback.");
3792            } else {
3793                Slog.d(TAG, "Performing fallback: " + fallbackEvent);
3794            }
3795        }
3796        return fallbackEvent;
3797    }
3798
3799    private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
3800        int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
3801        if ((actions & ACTION_PASS_TO_USER) != 0) {
3802            long delayMillis = interceptKeyBeforeDispatching(
3803                    win, fallbackEvent, policyFlags);
3804            if (delayMillis == 0) {
3805                return true;
3806            }
3807        }
3808        return false;
3809    }
3810
3811    @Override
3812    public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
3813            throws RemoteException {
3814        synchronized (mLock) {
3815            IShortcutService service = mShortcutKeyServices.get(shortcutCode);
3816            if (service != null && service.asBinder().pingBinder()) {
3817                throw new RemoteException("Key already exists.");
3818            }
3819
3820            mShortcutKeyServices.put(shortcutCode, shortcutService);
3821        }
3822    }
3823
3824    @Override
3825    public void onKeyguardOccludedChangedLw(boolean occluded) {
3826        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
3827            mPendingKeyguardOccluded = occluded;
3828            mKeyguardOccludedChanged = true;
3829        } else {
3830            setKeyguardOccludedLw(occluded);
3831        }
3832    }
3833
3834    private int handleStartTransitionForKeyguardLw(int transit, @Nullable Animation anim) {
3835        if (mKeyguardOccludedChanged) {
3836            if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded="
3837                    + mPendingKeyguardOccluded);
3838            mKeyguardOccludedChanged = false;
3839            if (setKeyguardOccludedLw(mPendingKeyguardOccluded)) {
3840                return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER;
3841            }
3842        }
3843        if (AppTransition.isKeyguardGoingAwayTransit(transit)) {
3844            if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation");
3845            final long startTime = anim != null
3846                    ? SystemClock.uptimeMillis() + anim.getStartOffset()
3847                    : SystemClock.uptimeMillis();
3848            final long duration = anim != null
3849                    ? anim.getDuration()
3850                    : 0;
3851            startKeyguardExitAnimation(startTime, duration);
3852        }
3853        return 0;
3854    }
3855
3856    private void launchAssistLongPressAction() {
3857        performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
3858        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
3859
3860        // launch the search activity
3861        Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
3862        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3863        try {
3864            // TODO: This only stops the factory-installed search manager.
3865            // Need to formalize an API to handle others
3866            SearchManager searchManager = getSearchManager();
3867            if (searchManager != null) {
3868                searchManager.stopSearch();
3869            }
3870            startActivityAsUser(intent, UserHandle.CURRENT);
3871        } catch (ActivityNotFoundException e) {
3872            Slog.w(TAG, "No activity to handle assist long press action.", e);
3873        }
3874    }
3875
3876    private void launchAssistAction(String hint, int deviceId) {
3877        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
3878        if (!isUserSetupComplete()) {
3879            // Disable opening assist window during setup
3880            return;
3881        }
3882        Bundle args = null;
3883        if (deviceId > Integer.MIN_VALUE) {
3884            args = new Bundle();
3885            args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
3886        }
3887        if ((mContext.getResources().getConfiguration().uiMode
3888                & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
3889            // On TV, use legacy handling until assistants are implemented in the proper way.
3890            ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
3891                    .launchLegacyAssist(hint, UserHandle.myUserId(), args);
3892        } else {
3893            if (hint != null) {
3894                if (args == null) {
3895                    args = new Bundle();
3896                }
3897                args.putBoolean(hint, true);
3898            }
3899            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3900            if (statusbar != null) {
3901                statusbar.startAssist(args);
3902            }
3903        }
3904    }
3905
3906    private void startActivityAsUser(Intent intent, UserHandle handle) {
3907        if (isUserSetupComplete()) {
3908            mContext.startActivityAsUser(intent, handle);
3909        } else {
3910            Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent);
3911        }
3912    }
3913
3914    private SearchManager getSearchManager() {
3915        if (mSearchManager == null) {
3916            mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
3917        }
3918        return mSearchManager;
3919    }
3920
3921    private void preloadRecentApps() {
3922        mPreloadedRecentApps = true;
3923        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3924        if (statusbar != null) {
3925            statusbar.preloadRecentApps();
3926        }
3927    }
3928
3929    private void cancelPreloadRecentApps() {
3930        if (mPreloadedRecentApps) {
3931            mPreloadedRecentApps = false;
3932            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3933            if (statusbar != null) {
3934                statusbar.cancelPreloadRecentApps();
3935            }
3936        }
3937    }
3938
3939    private void toggleRecentApps() {
3940        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3941        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3942        if (statusbar != null) {
3943            statusbar.toggleRecentApps();
3944        }
3945    }
3946
3947    @Override
3948    public void showRecentApps(boolean fromHome) {
3949        mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
3950        mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget();
3951    }
3952
3953    private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
3954        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3955        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3956        if (statusbar != null) {
3957            statusbar.showRecentApps(triggeredFromAltTab, fromHome);
3958        }
3959    }
3960
3961    private void toggleKeyboardShortcutsMenu(int deviceId) {
3962        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3963        if (statusbar != null) {
3964            statusbar.toggleKeyboardShortcutsMenu(deviceId);
3965        }
3966    }
3967
3968    private void dismissKeyboardShortcutsMenu() {
3969        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3970        if (statusbar != null) {
3971            statusbar.dismissKeyboardShortcutsMenu();
3972        }
3973    }
3974
3975    private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
3976        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3977        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3978        if (statusbar != null) {
3979            statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
3980        }
3981    }
3982
3983    void launchHomeFromHotKey() {
3984        launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/);
3985    }
3986
3987    /**
3988     * A home key -> launch home action was detected.  Take the appropriate action
3989     * given the situation with the keyguard.
3990     */
3991    void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) {
3992        if (respectKeyguard) {
3993            if (isKeyguardShowingAndNotOccluded()) {
3994                // don't launch home if keyguard showing
3995                return;
3996            }
3997
3998            if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) {
3999                // when in keyguard restricted mode, must first verify unlock
4000                // before launching home
4001                mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
4002                    @Override
4003                    public void onKeyguardExitResult(boolean success) {
4004                        if (success) {
4005                            try {
4006                                ActivityManager.getService().stopAppSwitches();
4007                            } catch (RemoteException e) {
4008                            }
4009                            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
4010                            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
4011                        }
4012                    }
4013                });
4014                return;
4015            }
4016        }
4017
4018        // no keyguard stuff to worry about, just launch home!
4019        try {
4020            ActivityManager.getService().stopAppSwitches();
4021        } catch (RemoteException e) {
4022        }
4023        if (mRecentsVisible) {
4024            // Hide Recents and notify it to launch Home
4025            if (awakenFromDreams) {
4026                awakenDreams();
4027            }
4028            hideRecentApps(false, true);
4029        } else {
4030            // Otherwise, just launch Home
4031            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
4032            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
4033        }
4034    }
4035
4036    private final Runnable mClearHideNavigationFlag = new Runnable() {
4037        @Override
4038        public void run() {
4039            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
4040                // Clear flags.
4041                mForceClearedSystemUiFlags &=
4042                        ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
4043            }
4044            mWindowManagerFuncs.reevaluateStatusBarVisibility();
4045        }
4046    };
4047
4048    /**
4049     * Input handler used while nav bar is hidden.  Captures any touch on the screen,
4050     * to determine when the nav bar should be shown and prevent applications from
4051     * receiving those touches.
4052     */
4053    final class HideNavInputEventReceiver extends InputEventReceiver {
4054        public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
4055            super(inputChannel, looper);
4056        }
4057
4058        @Override
4059        public void onInputEvent(InputEvent event) {
4060            boolean handled = false;
4061            try {
4062                if (event instanceof MotionEvent
4063                        && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
4064                    final MotionEvent motionEvent = (MotionEvent)event;
4065                    if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
4066                        // When the user taps down, we re-show the nav bar.
4067                        boolean changed = false;
4068                        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
4069                            if (mInputConsumer == null) {
4070                                return;
4071                            }
4072                            // Any user activity always causes us to show the
4073                            // navigation controls, if they had been hidden.
4074                            // We also clear the low profile and only content
4075                            // flags so that tapping on the screen will atomically
4076                            // restore all currently hidden screen decorations.
4077                            int newVal = mResettingSystemUiFlags |
4078                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
4079                                    View.SYSTEM_UI_FLAG_LOW_PROFILE |
4080                                    View.SYSTEM_UI_FLAG_FULLSCREEN;
4081                            if (mResettingSystemUiFlags != newVal) {
4082                                mResettingSystemUiFlags = newVal;
4083                                changed = true;
4084                            }
4085                            // We don't allow the system's nav bar to be hidden
4086                            // again for 1 second, to prevent applications from
4087                            // spamming us and keeping it from being shown.
4088                            newVal = mForceClearedSystemUiFlags |
4089                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
4090                            if (mForceClearedSystemUiFlags != newVal) {
4091                                mForceClearedSystemUiFlags = newVal;
4092                                changed = true;
4093                                mHandler.postDelayed(mClearHideNavigationFlag, 1000);
4094                            }
4095                        }
4096                        if (changed) {
4097                            mWindowManagerFuncs.reevaluateStatusBarVisibility();
4098                        }
4099                    }
4100                }
4101            } finally {
4102                finishInputEvent(event, handled);
4103            }
4104        }
4105    }
4106
4107    @Override
4108    public void setRecentsVisibilityLw(boolean visible) {
4109        mRecentsVisible = visible;
4110    }
4111
4112    @Override
4113    public void setTvPipVisibilityLw(boolean visible) {
4114        mTvPictureInPictureVisible = visible;
4115    }
4116
4117    @Override
4118    public int adjustSystemUiVisibilityLw(int visibility) {
4119        mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4120        mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4121
4122        // Reset any bits in mForceClearingStatusBarVisibility that
4123        // are now clear.
4124        mResettingSystemUiFlags &= visibility;
4125        // Clear any bits in the new visibility that are currently being
4126        // force cleared, before reporting it.
4127        return visibility & ~mResettingSystemUiFlags
4128                & ~mForceClearedSystemUiFlags;
4129    }
4130
4131    @Override
4132    public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
4133            int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets,
4134            Rect outStableInsets, Rect outOutsets) {
4135        final int fl = PolicyControl.getWindowFlags(null, attrs);
4136        final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
4137        final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
4138
4139        final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
4140        if (useOutsets) {
4141            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
4142            if (outset > 0) {
4143                if (displayRotation == Surface.ROTATION_0) {
4144                    outOutsets.bottom += outset;
4145                } else if (displayRotation == Surface.ROTATION_90) {
4146                    outOutsets.right += outset;
4147                } else if (displayRotation == Surface.ROTATION_180) {
4148                    outOutsets.top += outset;
4149                } else if (displayRotation == Surface.ROTATION_270) {
4150                    outOutsets.left += outset;
4151                }
4152            }
4153        }
4154
4155        if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4156                == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4157            int availRight, availBottom;
4158            if (canHideNavigationBar() &&
4159                    (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
4160                availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4161                availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4162            } else {
4163                availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
4164                availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4165            }
4166            if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4167                if ((fl & FLAG_FULLSCREEN) != 0) {
4168                    outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop,
4169                            availRight - mStableFullscreenRight,
4170                            availBottom - mStableFullscreenBottom);
4171                } else {
4172                    outContentInsets.set(mStableLeft, mStableTop,
4173                            availRight - mStableRight, availBottom - mStableBottom);
4174                }
4175            } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
4176                outContentInsets.setEmpty();
4177            } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
4178                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
4179                outContentInsets.set(mCurLeft, mCurTop,
4180                        availRight - mCurRight, availBottom - mCurBottom);
4181            } else {
4182                outContentInsets.set(mCurLeft, mCurTop,
4183                        availRight - mCurRight, availBottom - mCurBottom);
4184            }
4185
4186            outStableInsets.set(mStableLeft, mStableTop,
4187                    availRight - mStableRight, availBottom - mStableBottom);
4188            if (taskBounds != null) {
4189                calculateRelevantTaskInsets(taskBounds, outContentInsets,
4190                        displayWidth, displayHeight);
4191                calculateRelevantTaskInsets(taskBounds, outStableInsets,
4192                        displayWidth, displayHeight);
4193            }
4194            return mForceShowSystemBars;
4195        }
4196        outContentInsets.setEmpty();
4197        outStableInsets.setEmpty();
4198        return mForceShowSystemBars;
4199    }
4200
4201    /**
4202     * For any given task bounds, the insets relevant for these bounds given the insets relevant
4203     * for the entire display.
4204     */
4205    private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth,
4206            int displayHeight) {
4207        mTmpRect.set(0, 0, displayWidth, displayHeight);
4208        mTmpRect.inset(inOutInsets);
4209        mTmpRect.intersect(taskBounds);
4210        int leftInset = mTmpRect.left - taskBounds.left;
4211        int topInset = mTmpRect.top - taskBounds.top;
4212        int rightInset = taskBounds.right - mTmpRect.right;
4213        int bottomInset = taskBounds.bottom - mTmpRect.bottom;
4214        inOutInsets.set(leftInset, topInset, rightInset, bottomInset);
4215    }
4216
4217    private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
4218        return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
4219                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
4220    }
4221
4222    /** {@inheritDoc} */
4223    @Override
4224    public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
4225                              int displayRotation, int uiMode) {
4226        mDisplayRotation = displayRotation;
4227        final int overscanLeft, overscanTop, overscanRight, overscanBottom;
4228        if (isDefaultDisplay) {
4229            switch (displayRotation) {
4230                case Surface.ROTATION_90:
4231                    overscanLeft = mOverscanTop;
4232                    overscanTop = mOverscanRight;
4233                    overscanRight = mOverscanBottom;
4234                    overscanBottom = mOverscanLeft;
4235                    break;
4236                case Surface.ROTATION_180:
4237                    overscanLeft = mOverscanRight;
4238                    overscanTop = mOverscanBottom;
4239                    overscanRight = mOverscanLeft;
4240                    overscanBottom = mOverscanTop;
4241                    break;
4242                case Surface.ROTATION_270:
4243                    overscanLeft = mOverscanBottom;
4244                    overscanTop = mOverscanLeft;
4245                    overscanRight = mOverscanTop;
4246                    overscanBottom = mOverscanRight;
4247                    break;
4248                default:
4249                    overscanLeft = mOverscanLeft;
4250                    overscanTop = mOverscanTop;
4251                    overscanRight = mOverscanRight;
4252                    overscanBottom = mOverscanBottom;
4253                    break;
4254            }
4255        } else {
4256            overscanLeft = 0;
4257            overscanTop = 0;
4258            overscanRight = 0;
4259            overscanBottom = 0;
4260        }
4261        mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0;
4262        mOverscanScreenTop = mRestrictedOverscanScreenTop = 0;
4263        mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth;
4264        mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight;
4265        mSystemLeft = 0;
4266        mSystemTop = 0;
4267        mSystemRight = displayWidth;
4268        mSystemBottom = displayHeight;
4269        mUnrestrictedScreenLeft = overscanLeft;
4270        mUnrestrictedScreenTop = overscanTop;
4271        mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight;
4272        mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom;
4273        mRestrictedScreenLeft = mUnrestrictedScreenLeft;
4274        mRestrictedScreenTop = mUnrestrictedScreenTop;
4275        mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth;
4276        mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight;
4277        mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft
4278                = mCurLeft = mUnrestrictedScreenLeft;
4279        mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop
4280                = mCurTop = mUnrestrictedScreenTop;
4281        mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight
4282                = mCurRight = displayWidth - overscanRight;
4283        mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom
4284                = mCurBottom = displayHeight - overscanBottom;
4285        mDockLayer = 0x10000000;
4286        mStatusBarLayer = -1;
4287
4288        // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
4289        final Rect pf = mTmpParentFrame;
4290        final Rect df = mTmpDisplayFrame;
4291        final Rect of = mTmpOverscanFrame;
4292        final Rect vf = mTmpVisibleFrame;
4293        final Rect dcf = mTmpDecorFrame;
4294        pf.left = df.left = of.left = vf.left = mDockLeft;
4295        pf.top = df.top = of.top = vf.top = mDockTop;
4296        pf.right = df.right = of.right = vf.right = mDockRight;
4297        pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom;
4298        dcf.setEmpty();  // Decor frame N/A for system bars.
4299
4300        if (isDefaultDisplay) {
4301            // For purposes of putting out fake window up to steal focus, we will
4302            // drive nav being hidden only by whether it is requested.
4303            final int sysui = mLastSystemUiFlags;
4304            boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
4305            boolean navTranslucent = (sysui
4306                    & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
4307            boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
4308            boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
4309            boolean navAllowedHidden = immersive || immersiveSticky;
4310            navTranslucent &= !immersiveSticky;  // transient trumps translucent
4311            boolean isKeyguardShowing = isStatusBarKeyguard() && !mKeyguardOccluded;
4312            if (!isKeyguardShowing) {
4313                navTranslucent &= areTranslucentBarsAllowed();
4314            }
4315            boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null
4316                    && mStatusBar.getAttrs().height == MATCH_PARENT
4317                    && mStatusBar.getAttrs().width == MATCH_PARENT;
4318
4319            // When the navigation bar isn't visible, we put up a fake
4320            // input window to catch all touch events.  This way we can
4321            // detect when the user presses anywhere to bring back the nav
4322            // bar and ensure the application doesn't see the event.
4323            if (navVisible || navAllowedHidden) {
4324                if (mInputConsumer != null) {
4325                    mHandler.sendMessage(
4326                            mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
4327                    mInputConsumer = null;
4328                }
4329            } else if (mInputConsumer == null) {
4330                mInputConsumer = mWindowManagerFuncs.createInputConsumer(mHandler.getLooper(),
4331                        INPUT_CONSUMER_NAVIGATION,
4332                        (channel, looper) -> new HideNavInputEventReceiver(channel, looper));
4333                // As long as mInputConsumer is active, hover events are not dispatched to the app
4334                // and the pointer icon is likely to become stale. Hide it to avoid confusion.
4335                InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL);
4336            }
4337
4338            // For purposes of positioning and showing the nav bar, if we have
4339            // decided that it can't be hidden (because of the screen aspect ratio),
4340            // then take that into account.
4341            navVisible |= !canHideNavigationBar();
4342
4343            boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight,
4344                    displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom, dcf, navVisible, navTranslucent,
4345                    navAllowedHidden, statusBarExpandedNotKeyguard);
4346            if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
4347                    mDockLeft, mDockTop, mDockRight, mDockBottom));
4348            updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing);
4349            if (updateSysUiVisibility) {
4350                updateSystemUiVisibilityLw();
4351            }
4352        }
4353    }
4354
4355    private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui,
4356            boolean isKeyguardShowing) {
4357        // decide where the status bar goes ahead of time
4358        if (mStatusBar != null) {
4359            // apply any navigation bar insets
4360            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4361            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4362            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4363            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
4364                    + mUnrestrictedScreenTop;
4365            vf.left = mStableLeft;
4366            vf.top = mStableTop;
4367            vf.right = mStableRight;
4368            vf.bottom = mStableBottom;
4369
4370            mStatusBarLayer = mStatusBar.getSurfaceLayer();
4371
4372            // Let the status bar determine its size.
4373            mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
4374                    vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
4375                    dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */);
4376
4377            // For layout, the status bar is always at the top with our fixed height.
4378            mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
4379
4380            boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
4381            boolean statusBarTranslucent = (sysui
4382                    & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
4383            if (!isKeyguardShowing) {
4384                statusBarTranslucent &= areTranslucentBarsAllowed();
4385            }
4386
4387            // If the status bar is hidden, we don't want to cause
4388            // windows behind it to scroll.
4389            if (mStatusBar.isVisibleLw() && !statusBarTransient) {
4390                // Status bar may go away, so the screen area it occupies
4391                // is available to apps but just covering them when the
4392                // status bar is visible.
4393                mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
4394
4395                mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4396                mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4397                mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4398                mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4399
4400                if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " +
4401                        String.format(
4402                                "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
4403                                mDockLeft, mDockTop, mDockRight, mDockBottom,
4404                                mContentLeft, mContentTop, mContentRight, mContentBottom,
4405                                mCurLeft, mCurTop, mCurRight, mCurBottom));
4406            }
4407            if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
4408                    && !statusBarTransient && !statusBarTranslucent
4409                    && !mStatusBarController.wasRecentlyTranslucent()) {
4410                // If the opaque status bar is currently requested to be visible,
4411                // and not in the process of animating on or off, then
4412                // we can tell the app that it is covered by it.
4413                mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
4414            }
4415            if (mStatusBarController.checkHiddenLw()) {
4416                return true;
4417            }
4418        }
4419        return false;
4420    }
4421
4422    private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation,
4423            int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf,
4424            boolean navVisible, boolean navTranslucent, boolean navAllowedHidden,
4425            boolean statusBarExpandedNotKeyguard) {
4426        if (mNavigationBar != null) {
4427            boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
4428            // Force the navigation bar to its appropriate place and
4429            // size.  We need to do this directly, instead of relying on
4430            // it to bubble up from the nav bar, because this needs to
4431            // change atomically with screen rotations.
4432            mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight,
4433                    displayRotation);
4434            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
4435                // It's a system nav bar or a portrait screen; nav bar goes on bottom.
4436                int top = displayHeight - overscanBottom
4437                        - getNavigationBarHeight(displayRotation, uiMode);
4438                mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
4439                mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
4440                if (transientNavBarShowing) {
4441                    mNavigationBarController.setBarShowingLw(true);
4442                } else if (navVisible) {
4443                    mNavigationBarController.setBarShowingLw(true);
4444                    mDockBottom = mTmpNavigationFrame.top;
4445                    mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
4446                    mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
4447                } else {
4448                    // We currently want to hide the navigation UI - unless we expanded the status
4449                    // bar.
4450                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4451                }
4452                if (navVisible && !navTranslucent && !navAllowedHidden
4453                        && !mNavigationBar.isAnimatingLw()
4454                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4455                    // If the opaque nav bar is currently requested to be visible,
4456                    // and not in the process of animating on or off, then
4457                    // we can tell the app that it is covered by it.
4458                    mSystemBottom = mTmpNavigationFrame.top;
4459                }
4460            } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4461                // Landscape screen; nav bar goes to the right.
4462                int left = displayWidth - overscanRight
4463                        - getNavigationBarWidth(displayRotation, uiMode);
4464                mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
4465                mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
4466                if (transientNavBarShowing) {
4467                    mNavigationBarController.setBarShowingLw(true);
4468                } else if (navVisible) {
4469                    mNavigationBarController.setBarShowingLw(true);
4470                    mDockRight = mTmpNavigationFrame.left;
4471                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4472                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4473                } else {
4474                    // We currently want to hide the navigation UI - unless we expanded the status
4475                    // bar.
4476                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4477                }
4478                if (navVisible && !navTranslucent && !navAllowedHidden
4479                        && !mNavigationBar.isAnimatingLw()
4480                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4481                    // If the nav bar is currently requested to be visible,
4482                    // and not in the process of animating on or off, then
4483                    // we can tell the app that it is covered by it.
4484                    mSystemRight = mTmpNavigationFrame.left;
4485                }
4486            } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4487                // Seascape screen; nav bar goes to the left.
4488                int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode);
4489                mTmpNavigationFrame.set(overscanLeft, 0, right, displayHeight);
4490                mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right;
4491                if (transientNavBarShowing) {
4492                    mNavigationBarController.setBarShowingLw(true);
4493                } else if (navVisible) {
4494                    mNavigationBarController.setBarShowingLw(true);
4495                    mDockLeft = mTmpNavigationFrame.right;
4496                    // TODO: not so sure about those:
4497                    mRestrictedScreenLeft = mRestrictedOverscanScreenLeft = mDockLeft;
4498                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4499                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4500                } else {
4501                    // We currently want to hide the navigation UI - unless we expanded the status
4502                    // bar.
4503                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4504                }
4505                if (navVisible && !navTranslucent && !navAllowedHidden
4506                        && !mNavigationBar.isAnimatingLw()
4507                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4508                    // If the nav bar is currently requested to be visible,
4509                    // and not in the process of animating on or off, then
4510                    // we can tell the app that it is covered by it.
4511                    mSystemLeft = mTmpNavigationFrame.right;
4512                }
4513            }
4514            // Make sure the content and current rectangles are updated to
4515            // account for the restrictions from the navigation bar.
4516            mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4517            mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4518            mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4519            mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4520            mStatusBarLayer = mNavigationBar.getSurfaceLayer();
4521            // And compute the final frame.
4522            mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
4523                    mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
4524                    mTmpNavigationFrame, mTmpNavigationFrame);
4525            if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
4526            if (mNavigationBarController.checkHiddenLw()) {
4527                return true;
4528            }
4529        }
4530        return false;
4531    }
4532
4533    private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
4534        if (mNavigationBarCanMove && displayWidth > displayHeight) {
4535            if (displayRotation == Surface.ROTATION_270) {
4536                return NAV_BAR_LEFT;
4537            } else {
4538                return NAV_BAR_RIGHT;
4539            }
4540        }
4541        return NAV_BAR_BOTTOM;
4542    }
4543
4544    /** {@inheritDoc} */
4545    @Override
4546    public int getSystemDecorLayerLw() {
4547        if (mStatusBar != null && mStatusBar.isVisibleLw()) {
4548            return mStatusBar.getSurfaceLayer();
4549        }
4550
4551        if (mNavigationBar != null && mNavigationBar.isVisibleLw()) {
4552            return mNavigationBar.getSurfaceLayer();
4553        }
4554
4555        return 0;
4556    }
4557
4558    @Override
4559    public void getContentRectLw(Rect r) {
4560        r.set(mContentLeft, mContentTop, mContentRight, mContentBottom);
4561    }
4562
4563    void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
4564            boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
4565        if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
4566            // Here's a special case: if this attached window is a panel that is
4567            // above the dock window, and the window it is attached to is below
4568            // the dock window, then the frames we computed for the window it is
4569            // attached to can not be used because the dock is effectively part
4570            // of the underlying window and the attached window is floating on top
4571            // of the whole thing.  So, we ignore the attached window and explicitly
4572            // compute the frames that would be appropriate without the dock.
4573            df.left = of.left = cf.left = vf.left = mDockLeft;
4574            df.top = of.top = cf.top = vf.top = mDockTop;
4575            df.right = of.right = cf.right = vf.right = mDockRight;
4576            df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom;
4577        } else {
4578            // The effective display frame of the attached window depends on
4579            // whether it is taking care of insetting its content.  If not,
4580            // we need to use the parent's content frame so that the entire
4581            // window is positioned within that content.  Otherwise we can use
4582            // the overscan frame and let the attached window take care of
4583            // positioning its content appropriately.
4584            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4585                // Set the content frame of the attached window to the parent's decor frame
4586                // (same as content frame when IME isn't present) if specifically requested by
4587                // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
4588                // Otherwise, use the overscan frame.
4589                cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
4590                        ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
4591            } else {
4592                // If the window is resizing, then we want to base the content
4593                // frame on our attached content frame to resize...  however,
4594                // things can be tricky if the attached window is NOT in resize
4595                // mode, in which case its content frame will be larger.
4596                // Ungh.  So to deal with that, make sure the content frame
4597                // we end up using is not covering the IM dock.
4598                cf.set(attached.getContentFrameLw());
4599                if (attached.isVoiceInteraction()) {
4600                    if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft;
4601                    if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop;
4602                    if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight;
4603                    if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom;
4604                } else if (attached.getSurfaceLayer() < mDockLayer) {
4605                    if (cf.left < mContentLeft) cf.left = mContentLeft;
4606                    if (cf.top < mContentTop) cf.top = mContentTop;
4607                    if (cf.right > mContentRight) cf.right = mContentRight;
4608                    if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
4609                }
4610            }
4611            df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
4612            of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
4613            vf.set(attached.getVisibleFrameLw());
4614        }
4615        // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
4616        // window should be positioned relative to its parent or the entire
4617        // screen.
4618        pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
4619                ? attached.getFrameLw() : df);
4620    }
4621
4622    private void applyStableConstraints(int sysui, int fl, Rect r) {
4623        if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4624            // If app is requesting a stable layout, don't let the
4625            // content insets go below the stable values.
4626            if ((fl & FLAG_FULLSCREEN) != 0) {
4627                if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft;
4628                if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop;
4629                if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight;
4630                if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom;
4631            } else {
4632                if (r.left < mStableLeft) r.left = mStableLeft;
4633                if (r.top < mStableTop) r.top = mStableTop;
4634                if (r.right > mStableRight) r.right = mStableRight;
4635                if (r.bottom > mStableBottom) r.bottom = mStableBottom;
4636            }
4637        }
4638    }
4639
4640    private boolean canReceiveInput(WindowState win) {
4641        boolean notFocusable =
4642                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
4643        boolean altFocusableIm =
4644                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
4645        boolean notFocusableForIm = notFocusable ^ altFocusableIm;
4646        return !notFocusableForIm;
4647    }
4648
4649    /** {@inheritDoc} */
4650    @Override
4651    public void layoutWindowLw(WindowState win, WindowState attached) {
4652        // We've already done the navigation bar and status bar. If the status bar can receive
4653        // input, we need to layout it again to accomodate for the IME window.
4654        if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) {
4655            return;
4656        }
4657        final WindowManager.LayoutParams attrs = win.getAttrs();
4658        final boolean isDefaultDisplay = win.isDefaultDisplay();
4659        final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
4660                (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
4661        if (needsToOffsetInputMethodTarget) {
4662            if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
4663            offsetInputMethodWindowLw(mLastInputMethodWindow);
4664        }
4665
4666        final int fl = PolicyControl.getWindowFlags(win, attrs);
4667        final int pfl = attrs.privateFlags;
4668        final int sim = attrs.softInputMode;
4669        final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
4670
4671        final Rect pf = mTmpParentFrame;
4672        final Rect df = mTmpDisplayFrame;
4673        final Rect of = mTmpOverscanFrame;
4674        final Rect cf = mTmpContentFrame;
4675        final Rect vf = mTmpVisibleFrame;
4676        final Rect dcf = mTmpDecorFrame;
4677        final Rect sf = mTmpStableFrame;
4678        Rect osf = null;
4679        dcf.setEmpty();
4680
4681        final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
4682                && mNavigationBar != null && mNavigationBar.isVisibleLw());
4683
4684        final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
4685
4686        if (isDefaultDisplay) {
4687            sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom);
4688        } else {
4689            sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom);
4690        }
4691
4692        if (!isDefaultDisplay) {
4693            if (attached != null) {
4694                // If this window is attached to another, our display
4695                // frame is the same as the one we are attached to.
4696                setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4697            } else {
4698                // Give the window full screen.
4699                pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4700                pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4701                pf.right = df.right = of.right = cf.right
4702                        = mOverscanScreenLeft + mOverscanScreenWidth;
4703                pf.bottom = df.bottom = of.bottom = cf.bottom
4704                        = mOverscanScreenTop + mOverscanScreenHeight;
4705            }
4706        } else if (attrs.type == TYPE_INPUT_METHOD) {
4707            pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
4708            pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
4709            pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
4710            // IM dock windows layout below the nav bar...
4711            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4712            // ...with content insets above the nav bar
4713            cf.bottom = vf.bottom = mStableBottom;
4714            if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
4715                // The status bar forces the navigation bar while it's visible. Make sure the IME
4716                // avoids the navigation bar in that case.
4717                if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4718                    pf.right = df.right = of.right = cf.right = vf.right = mStableRight;
4719                } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4720                    pf.left = df.left = of.left = cf.left = vf.left = mStableLeft;
4721                }
4722            }
4723            // IM dock windows always go to the bottom of the screen.
4724            attrs.gravity = Gravity.BOTTOM;
4725            mDockLayer = win.getSurfaceLayer();
4726        } else if (attrs.type == TYPE_VOICE_INTERACTION) {
4727            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4728            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4729            pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4730            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4731            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4732                cf.left = mDockLeft;
4733                cf.top = mDockTop;
4734                cf.right = mDockRight;
4735                cf.bottom = mDockBottom;
4736            } else {
4737                cf.left = mContentLeft;
4738                cf.top = mContentTop;
4739                cf.right = mContentRight;
4740                cf.bottom = mContentBottom;
4741            }
4742            if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4743                vf.left = mCurLeft;
4744                vf.top = mCurTop;
4745                vf.right = mCurRight;
4746                vf.bottom = mCurBottom;
4747            } else {
4748                vf.set(cf);
4749            }
4750        } else if (attrs.type == TYPE_WALLPAPER) {
4751           layoutWallpaper(win, pf, df, of, cf);
4752        } else if (win == mStatusBar) {
4753            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4754            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4755            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4756            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop;
4757            cf.left = vf.left = mStableLeft;
4758            cf.top = vf.top = mStableTop;
4759            cf.right = vf.right = mStableRight;
4760            vf.bottom = mStableBottom;
4761
4762            if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
4763                cf.bottom = mContentBottom;
4764            } else {
4765                cf.bottom = mDockBottom;
4766                vf.bottom = mContentBottom;
4767            }
4768        } else {
4769
4770            // Default policy decor for the default display
4771            dcf.left = mSystemLeft;
4772            dcf.top = mSystemTop;
4773            dcf.right = mSystemRight;
4774            dcf.bottom = mSystemBottom;
4775            final boolean inheritTranslucentDecor = (attrs.privateFlags
4776                    & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0;
4777            final boolean isAppWindow =
4778                    attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW &&
4779                    attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
4780            final boolean topAtRest =
4781                    win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
4782            if (isAppWindow && !inheritTranslucentDecor && !topAtRest) {
4783                if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
4784                        && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0
4785                        && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
4786                        && (fl & WindowManager.LayoutParams.
4787                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
4788                        && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) {
4789                    // Ensure policy decor includes status bar
4790                    dcf.top = mStableTop;
4791                }
4792                if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0
4793                        && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
4794                        && (fl & WindowManager.LayoutParams.
4795                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
4796                    // Ensure policy decor includes navigation bar
4797                    dcf.bottom = mStableBottom;
4798                    dcf.right = mStableRight;
4799                }
4800            }
4801
4802            if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4803                    == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4804                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
4805                            + "): IN_SCREEN, INSET_DECOR");
4806                // This is the case for a normal activity window: we want it
4807                // to cover all of the screen space, and it can take care of
4808                // moving its contents to account for screen decorations that
4809                // intrude into that space.
4810                if (attached != null) {
4811                    // If this window is attached to another, our display
4812                    // frame is the same as the one we are attached to.
4813                    setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4814                } else {
4815                    if (attrs.type == TYPE_STATUS_BAR_PANEL
4816                            || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
4817                        // Status bar panels are the only windows who can go on top of
4818                        // the status bar.  They are protected by the STATUS_BAR_SERVICE
4819                        // permission, so they have the same privileges as the status
4820                        // bar itself.
4821                        //
4822                        // However, they should still dodge the navigation bar if it exists.
4823
4824                        pf.left = df.left = of.left = hasNavBar
4825                                ? mDockLeft : mUnrestrictedScreenLeft;
4826                        pf.top = df.top = of.top = mUnrestrictedScreenTop;
4827                        pf.right = df.right = of.right = hasNavBar
4828                                ? mRestrictedScreenLeft+mRestrictedScreenWidth
4829                                : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4830                        pf.bottom = df.bottom = of.bottom = hasNavBar
4831                                ? mRestrictedScreenTop+mRestrictedScreenHeight
4832                                : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4833
4834                        if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4835                                        "Laying out status bar window: (%d,%d - %d,%d)",
4836                                        pf.left, pf.top, pf.right, pf.bottom));
4837                    } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4838                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4839                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4840                        // Asking to layout into the overscan region, so give it that pure
4841                        // unrestricted area.
4842                        pf.left = df.left = of.left = mOverscanScreenLeft;
4843                        pf.top = df.top = of.top = mOverscanScreenTop;
4844                        pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth;
4845                        pf.bottom = df.bottom = of.bottom = mOverscanScreenTop
4846                                + mOverscanScreenHeight;
4847                    } else if (canHideNavigationBar()
4848                            && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4849                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4850                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4851                        // Asking for layout as if the nav bar is hidden, lets the
4852                        // application extend into the unrestricted overscan screen area.  We
4853                        // only do this for application windows to ensure no window that
4854                        // can be above the nav bar can do this.
4855                        pf.left = df.left = mOverscanScreenLeft;
4856                        pf.top = df.top = mOverscanScreenTop;
4857                        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
4858                        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
4859                        // We need to tell the app about where the frame inside the overscan
4860                        // is, so it can inset its content by that amount -- it didn't ask
4861                        // to actually extend itself into the overscan region.
4862                        of.left = mUnrestrictedScreenLeft;
4863                        of.top = mUnrestrictedScreenTop;
4864                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4865                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4866                    } else {
4867                        pf.left = df.left = mRestrictedOverscanScreenLeft;
4868                        pf.top = df.top = mRestrictedOverscanScreenTop;
4869                        pf.right = df.right = mRestrictedOverscanScreenLeft
4870                                + mRestrictedOverscanScreenWidth;
4871                        pf.bottom = df.bottom = mRestrictedOverscanScreenTop
4872                                + mRestrictedOverscanScreenHeight;
4873                        // We need to tell the app about where the frame inside the overscan
4874                        // is, so it can inset its content by that amount -- it didn't ask
4875                        // to actually extend itself into the overscan region.
4876                        of.left = mUnrestrictedScreenLeft;
4877                        of.top = mUnrestrictedScreenTop;
4878                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4879                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4880                    }
4881
4882                    if ((fl & FLAG_FULLSCREEN) == 0) {
4883                        if (win.isVoiceInteraction()) {
4884                            cf.left = mVoiceContentLeft;
4885                            cf.top = mVoiceContentTop;
4886                            cf.right = mVoiceContentRight;
4887                            cf.bottom = mVoiceContentBottom;
4888                        } else {
4889                            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4890                                cf.left = mDockLeft;
4891                                cf.top = mDockTop;
4892                                cf.right = mDockRight;
4893                                cf.bottom = mDockBottom;
4894                            } else {
4895                                cf.left = mContentLeft;
4896                                cf.top = mContentTop;
4897                                cf.right = mContentRight;
4898                                cf.bottom = mContentBottom;
4899                            }
4900                        }
4901                    } else {
4902                        // Full screen windows are always given a layout that is as if the
4903                        // status bar and other transient decors are gone.  This is to avoid
4904                        // bad states when moving from a window that is not hding the
4905                        // status bar to one that is.
4906                        cf.left = mRestrictedScreenLeft;
4907                        cf.top = mRestrictedScreenTop;
4908                        cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
4909                        cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4910                    }
4911                    applyStableConstraints(sysUiFl, fl, cf);
4912                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4913                        vf.left = mCurLeft;
4914                        vf.top = mCurTop;
4915                        vf.right = mCurRight;
4916                        vf.bottom = mCurBottom;
4917                    } else {
4918                        vf.set(cf);
4919                    }
4920                }
4921            } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
4922                    & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
4923                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
4924                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4925                        "): IN_SCREEN");
4926                // A window that has requested to fill the entire screen just
4927                // gets everything, period.
4928                if (attrs.type == TYPE_STATUS_BAR_PANEL
4929                        || attrs.type == TYPE_STATUS_BAR_SUB_PANEL
4930                        || attrs.type == TYPE_VOLUME_OVERLAY) {
4931                    pf.left = df.left = of.left = cf.left = hasNavBar
4932                            ? mDockLeft : mUnrestrictedScreenLeft;
4933                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
4934                    pf.right = df.right = of.right = cf.right = hasNavBar
4935                                        ? mRestrictedScreenLeft+mRestrictedScreenWidth
4936                                        : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4937                    pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar
4938                                          ? mRestrictedScreenTop+mRestrictedScreenHeight
4939                                          : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4940                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4941                                    "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
4942                                    pf.left, pf.top, pf.right, pf.bottom));
4943                } else if (attrs.type == TYPE_NAVIGATION_BAR
4944                        || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
4945                    // The navigation bar has Real Ultimate Power.
4946                    pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4947                    pf.top = df.top = of.top = mUnrestrictedScreenTop;
4948                    pf.right = df.right = of.right = mUnrestrictedScreenLeft
4949                            + mUnrestrictedScreenWidth;
4950                    pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop
4951                            + mUnrestrictedScreenHeight;
4952                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4953                                    "Laying out navigation bar window: (%d,%d - %d,%d)",
4954                                    pf.left, pf.top, pf.right, pf.bottom));
4955                } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
4956                                || attrs.type == TYPE_BOOT_PROGRESS
4957                                || attrs.type == TYPE_SCREENSHOT)
4958                        && ((fl & FLAG_FULLSCREEN) != 0)) {
4959                    // Fullscreen secure system overlays get what they ask for. Screenshot region
4960                    // selection overlay should also expand to full screen.
4961                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4962                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4963                    pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
4964                            + mOverscanScreenWidth;
4965                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
4966                            + mOverscanScreenHeight;
4967                } else if (attrs.type == TYPE_BOOT_PROGRESS) {
4968                    // Boot progress screen always covers entire display.
4969                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4970                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4971                    pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
4972                            + mOverscanScreenWidth;
4973                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
4974                            + mOverscanScreenHeight;
4975                } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4976                        && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4977                        && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4978                    // Asking to layout into the overscan region, so give it that pure
4979                    // unrestricted area.
4980                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4981                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4982                    pf.right = df.right = of.right = cf.right
4983                            = mOverscanScreenLeft + mOverscanScreenWidth;
4984                    pf.bottom = df.bottom = of.bottom = cf.bottom
4985                            = mOverscanScreenTop + mOverscanScreenHeight;
4986                } else if (canHideNavigationBar()
4987                        && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4988                        && (attrs.type == TYPE_STATUS_BAR
4989                            || attrs.type == TYPE_TOAST
4990                            || attrs.type == TYPE_DOCK_DIVIDER
4991                            || attrs.type == TYPE_VOICE_INTERACTION_STARTING
4992                            || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4993                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
4994                    // Asking for layout as if the nav bar is hidden, lets the
4995                    // application extend into the unrestricted screen area.  We
4996                    // only do this for application windows (or toasts) to ensure no window that
4997                    // can be above the nav bar can do this.
4998                    // XXX This assumes that an app asking for this will also
4999                    // ask for layout in only content.  We can't currently figure out
5000                    // what the screen would be if only laying out to hide the nav bar.
5001                    pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
5002                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
5003                    pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft
5004                            + mUnrestrictedScreenWidth;
5005                    pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
5006                            + mUnrestrictedScreenHeight;
5007                } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
5008                    pf.left = df.left = of.left = mRestrictedScreenLeft;
5009                    pf.top = df.top = of.top  = mRestrictedScreenTop;
5010                    pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
5011                    pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop
5012                            + mRestrictedScreenHeight;
5013                    if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5014                        cf.left = mDockLeft;
5015                        cf.top = mDockTop;
5016                        cf.right = mDockRight;
5017                        cf.bottom = mDockBottom;
5018                    } else {
5019                        cf.left = mContentLeft;
5020                        cf.top = mContentTop;
5021                        cf.right = mContentRight;
5022                        cf.bottom = mContentBottom;
5023                    }
5024                } else {
5025                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
5026                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
5027                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
5028                            + mRestrictedScreenWidth;
5029                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
5030                            + mRestrictedScreenHeight;
5031                }
5032
5033                applyStableConstraints(sysUiFl, fl, cf);
5034
5035                if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5036                    vf.left = mCurLeft;
5037                    vf.top = mCurTop;
5038                    vf.right = mCurRight;
5039                    vf.bottom = mCurBottom;
5040                } else {
5041                    vf.set(cf);
5042                }
5043            } else if (attached != null) {
5044                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5045                        "): attached to " + attached);
5046                // A child window should be placed inside of the same visible
5047                // frame that its parent had.
5048                setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf);
5049            } else {
5050                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5051                        "): normal window");
5052                // Otherwise, a normal window must be placed inside the content
5053                // of all screen decorations.
5054                if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) {
5055                    // Status bar panels and the volume dialog are the only windows who can go on
5056                    // top of the status bar.  They are protected by the STATUS_BAR_SERVICE
5057                    // permission, so they have the same privileges as the status
5058                    // bar itself.
5059                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
5060                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
5061                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
5062                            + mRestrictedScreenWidth;
5063                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
5064                            + mRestrictedScreenHeight;
5065                } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) {
5066                    // These dialogs are stable to interim decor changes.
5067                    pf.left = df.left = of.left = cf.left = mStableLeft;
5068                    pf.top = df.top = of.top = cf.top = mStableTop;
5069                    pf.right = df.right = of.right = cf.right = mStableRight;
5070                    pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom;
5071                } else {
5072                    pf.left = mContentLeft;
5073                    pf.top = mContentTop;
5074                    pf.right = mContentRight;
5075                    pf.bottom = mContentBottom;
5076                    if (win.isVoiceInteraction()) {
5077                        df.left = of.left = cf.left = mVoiceContentLeft;
5078                        df.top = of.top = cf.top = mVoiceContentTop;
5079                        df.right = of.right = cf.right = mVoiceContentRight;
5080                        df.bottom = of.bottom = cf.bottom = mVoiceContentBottom;
5081                    } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5082                        df.left = of.left = cf.left = mDockLeft;
5083                        df.top = of.top = cf.top = mDockTop;
5084                        df.right = of.right = cf.right = mDockRight;
5085                        df.bottom = of.bottom = cf.bottom = mDockBottom;
5086                    } else {
5087                        df.left = of.left = cf.left = mContentLeft;
5088                        df.top = of.top = cf.top = mContentTop;
5089                        df.right = of.right = cf.right = mContentRight;
5090                        df.bottom = of.bottom = cf.bottom = mContentBottom;
5091                    }
5092                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5093                        vf.left = mCurLeft;
5094                        vf.top = mCurTop;
5095                        vf.right = mCurRight;
5096                        vf.bottom = mCurBottom;
5097                    } else {
5098                        vf.set(cf);
5099                    }
5100                }
5101            }
5102        }
5103
5104        // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
5105        // Also, we don't allow windows in multi-window mode to extend out of the screen.
5106        if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR
5107                && !win.isInMultiWindowMode()) {
5108            df.left = df.top = -10000;
5109            df.right = df.bottom = 10000;
5110            if (attrs.type != TYPE_WALLPAPER) {
5111                of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
5112                of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
5113            }
5114        }
5115
5116        // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we
5117        // need to provide information to the clients that want to pretend that you can draw there.
5118        // We only want to apply outsets to certain types of windows. For example, we never want to
5119        // apply the outsets to floating dialogs, because they wouldn't make sense there.
5120        final boolean useOutsets = shouldUseOutsets(attrs, fl);
5121        if (isDefaultDisplay && useOutsets) {
5122            osf = mTmpOutsetFrame;
5123            osf.set(cf.left, cf.top, cf.right, cf.bottom);
5124            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
5125            if (outset > 0) {
5126                int rotation = mDisplayRotation;
5127                if (rotation == Surface.ROTATION_0) {
5128                    osf.bottom += outset;
5129                } else if (rotation == Surface.ROTATION_90) {
5130                    osf.right += outset;
5131                } else if (rotation == Surface.ROTATION_180) {
5132                    osf.top -= outset;
5133                } else if (rotation == Surface.ROTATION_270) {
5134                    osf.left -= outset;
5135                }
5136                if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset
5137                        + " with rotation " + rotation + ", result: " + osf);
5138            }
5139        }
5140
5141        if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
5142                + ": sim=#" + Integer.toHexString(sim)
5143                + " attach=" + attached + " type=" + attrs.type
5144                + String.format(" flags=0x%08x", fl)
5145                + " pf=" + pf.toShortString() + " df=" + df.toShortString()
5146                + " of=" + of.toShortString()
5147                + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
5148                + " dcf=" + dcf.toShortString()
5149                + " sf=" + sf.toShortString()
5150                + " osf=" + (osf == null ? "null" : osf.toShortString()));
5151
5152        win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf);
5153
5154        // Dock windows carve out the bottom of the screen, so normal windows
5155        // can't appear underneath them.
5156        if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleLw()
5157                && !win.getGivenInsetsPendingLw()) {
5158            setLastInputMethodWindowLw(null, null);
5159            offsetInputMethodWindowLw(win);
5160        }
5161        if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleLw()
5162                && !win.getGivenInsetsPendingLw()) {
5163            offsetVoiceInputWindowLw(win);
5164        }
5165    }
5166
5167    private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) {
5168
5169        // The wallpaper also has Real Ultimate Power, but we want to tell
5170        // it about the overscan area.
5171        pf.left = df.left = mOverscanScreenLeft;
5172        pf.top = df.top = mOverscanScreenTop;
5173        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
5174        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
5175        of.left = cf.left = mUnrestrictedScreenLeft;
5176        of.top = cf.top = mUnrestrictedScreenTop;
5177        of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5178        of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5179    }
5180
5181    private void offsetInputMethodWindowLw(WindowState win) {
5182        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5183        top += win.getGivenContentInsetsLw().top;
5184        if (mContentBottom > top) {
5185            mContentBottom = top;
5186        }
5187        if (mVoiceContentBottom > top) {
5188            mVoiceContentBottom = top;
5189        }
5190        top = win.getVisibleFrameLw().top;
5191        top += win.getGivenVisibleInsetsLw().top;
5192        if (mCurBottom > top) {
5193            mCurBottom = top;
5194        }
5195        if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
5196                + mDockBottom + " mContentBottom="
5197                + mContentBottom + " mCurBottom=" + mCurBottom);
5198    }
5199
5200    private void offsetVoiceInputWindowLw(WindowState win) {
5201        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5202        top += win.getGivenContentInsetsLw().top;
5203        if (mVoiceContentBottom > top) {
5204            mVoiceContentBottom = top;
5205        }
5206    }
5207
5208    /** {@inheritDoc} */
5209    @Override
5210    public void finishLayoutLw() {
5211        return;
5212    }
5213
5214    /** {@inheritDoc} */
5215    @Override
5216    public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
5217        mTopFullscreenOpaqueWindowState = null;
5218        mTopFullscreenOpaqueOrDimmingWindowState = null;
5219        mTopDockedOpaqueWindowState = null;
5220        mTopDockedOpaqueOrDimmingWindowState = null;
5221        mForceStatusBar = false;
5222        mForceStatusBarFromKeyguard = false;
5223        mForceStatusBarTransparent = false;
5224        mForcingShowNavBar = false;
5225        mForcingShowNavBarLayer = -1;
5226
5227        mAllowLockscreenWhenOn = false;
5228        mShowingDream = false;
5229    }
5230
5231    /** {@inheritDoc} */
5232    @Override
5233    public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
5234            WindowState attached, WindowState imeTarget) {
5235        final boolean visible = !win.isGoneForLayoutLw();
5236        if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisible=" + visible);
5237        applyKeyguardPolicyLw(win, imeTarget);
5238        final int fl = PolicyControl.getWindowFlags(win, attrs);
5239        if (mTopFullscreenOpaqueWindowState == null && visible && attrs.type == TYPE_INPUT_METHOD) {
5240            mForcingShowNavBar = true;
5241            mForcingShowNavBarLayer = win.getSurfaceLayer();
5242        }
5243        if (attrs.type == TYPE_STATUS_BAR) {
5244            if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
5245                mForceStatusBarFromKeyguard = true;
5246            }
5247            if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
5248                mForceStatusBarTransparent = true;
5249            }
5250        }
5251
5252        // Don't allow snapshots to influence SystemUI visibility flags.
5253        // TODO: Revisit this once SystemUI flags for snapshots are handled correctly
5254        boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
5255                && attrs.type < FIRST_SYSTEM_WINDOW
5256                && (attrs.privateFlags & PRIVATE_FLAG_TASK_SNAPSHOT) == 0;
5257        final int stackId = win.getStackId();
5258        if (mTopFullscreenOpaqueWindowState == null && visible) {
5259            if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
5260                mForceStatusBar = true;
5261            }
5262            if (attrs.type == TYPE_DREAM) {
5263                // If the lockscreen was showing when the dream started then wait
5264                // for the dream to draw before hiding the lockscreen.
5265                if (!mDreamingLockscreen
5266                        || (win.isVisibleLw() && win.hasDrawnLw())) {
5267                    mShowingDream = true;
5268                    appWindow = true;
5269                }
5270            }
5271
5272            // For app windows that are not attached, we decide if all windows in the app they
5273            // represent should be hidden or if we should hide the lockscreen. For attached app
5274            // windows we defer the decision to the window it is attached to.
5275            if (appWindow && attached == null) {
5276                if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
5277                    if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
5278                    mTopFullscreenOpaqueWindowState = win;
5279                    if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5280                        mTopFullscreenOpaqueOrDimmingWindowState = win;
5281                    }
5282                    if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
5283                        mAllowLockscreenWhenOn = true;
5284                    }
5285                }
5286            }
5287        }
5288
5289        // Voice interaction overrides both top fullscreen and top docked.
5290        if (visible && win.getAttrs().type == TYPE_VOICE_INTERACTION) {
5291            if (mTopFullscreenOpaqueWindowState == null) {
5292                mTopFullscreenOpaqueWindowState = win;
5293                if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5294                    mTopFullscreenOpaqueOrDimmingWindowState = win;
5295                }
5296            }
5297            if (mTopDockedOpaqueWindowState == null) {
5298                mTopDockedOpaqueWindowState = win;
5299                if (mTopDockedOpaqueOrDimmingWindowState == null) {
5300                    mTopDockedOpaqueOrDimmingWindowState = win;
5301                }
5302            }
5303        }
5304
5305        // Keep track of the window if it's dimming but not necessarily fullscreen.
5306        if (mTopFullscreenOpaqueOrDimmingWindowState == null && visible
5307                && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
5308            mTopFullscreenOpaqueOrDimmingWindowState = win;
5309        }
5310
5311        // We need to keep track of the top "fullscreen" opaque window for the docked stack
5312        // separately, because both the "real fullscreen" opaque window and the one for the docked
5313        // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
5314        if (mTopDockedOpaqueWindowState == null && visible && appWindow && attached == null
5315                && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
5316            mTopDockedOpaqueWindowState = win;
5317            if (mTopDockedOpaqueOrDimmingWindowState == null) {
5318                mTopDockedOpaqueOrDimmingWindowState = win;
5319            }
5320        }
5321
5322        // Also keep track of any windows that are dimming but not necessarily fullscreen in the
5323        // docked stack.
5324        if (mTopDockedOpaqueOrDimmingWindowState == null && visible && win.isDimming()
5325                && stackId == DOCKED_STACK_ID) {
5326            mTopDockedOpaqueOrDimmingWindowState = win;
5327        }
5328    }
5329
5330    private void applyKeyguardPolicyLw(WindowState win, WindowState imeTarget) {
5331        if (canBeHiddenByKeyguardLw(win)) {
5332            if (shouldBeHiddenByKeyguard(win, imeTarget)) {
5333                win.hideLw(false /* doAnimation */);
5334            } else {
5335                win.showLw(false /* doAnimation */);
5336            }
5337        }
5338    }
5339
5340    private boolean isFullscreen(WindowManager.LayoutParams attrs) {
5341        return attrs.x == 0 && attrs.y == 0
5342                && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
5343                && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
5344    }
5345
5346    /** {@inheritDoc} */
5347    @Override
5348    public int finishPostLayoutPolicyLw() {
5349        int changes = 0;
5350        boolean topIsFullscreen = false;
5351
5352        final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
5353                ? mTopFullscreenOpaqueWindowState.getAttrs()
5354                : null;
5355
5356        // If we are not currently showing a dream then remember the current
5357        // lockscreen state.  We will use this to determine whether the dream
5358        // started while the lockscreen was showing and remember this state
5359        // while the dream is showing.
5360        if (!mShowingDream) {
5361            mDreamingLockscreen = isKeyguardShowingAndNotOccluded();
5362            if (mDreamingSleepTokenNeeded) {
5363                mDreamingSleepTokenNeeded = false;
5364                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
5365            }
5366        } else {
5367            if (!mDreamingSleepTokenNeeded) {
5368                mDreamingSleepTokenNeeded = true;
5369                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget();
5370            }
5371        }
5372
5373        if (mStatusBar != null) {
5374            if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
5375                    + " forcefkg=" + mForceStatusBarFromKeyguard
5376                    + " top=" + mTopFullscreenOpaqueWindowState);
5377            boolean shouldBeTransparent = mForceStatusBarTransparent
5378                    && !mForceStatusBar
5379                    && !mForceStatusBarFromKeyguard;
5380            if (!shouldBeTransparent) {
5381                mStatusBarController.setShowTransparent(false /* transparent */);
5382            } else if (!mStatusBar.isVisibleLw()) {
5383                mStatusBarController.setShowTransparent(true /* transparent */);
5384            }
5385
5386            WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs();
5387            boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT
5388                    && statusBarAttrs.width == MATCH_PARENT;
5389            if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
5390                    || statusBarExpanded) {
5391                if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
5392                if (mStatusBarController.setBarShowingLw(true)) {
5393                    changes |= FINISH_LAYOUT_REDO_LAYOUT;
5394                }
5395                // Maintain fullscreen layout until incoming animation is complete.
5396                topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
5397                // Transient status bar on the lockscreen is not allowed
5398                if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) {
5399                    mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
5400                            mLastSystemUiFlags, mLastSystemUiFlags);
5401                }
5402                if (statusBarExpanded && mNavigationBar != null) {
5403                    if (mNavigationBarController.setBarShowingLw(true)) {
5404                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5405                    }
5406                }
5407            } else if (mTopFullscreenOpaqueWindowState != null) {
5408                final int fl = PolicyControl.getWindowFlags(null, lp);
5409                if (localLOGV) {
5410                    Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
5411                            + " shown position: "
5412                            + mTopFullscreenOpaqueWindowState.getShownPositionLw());
5413                    Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
5414                            + " lp.flags=0x" + Integer.toHexString(fl));
5415                }
5416                topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
5417                        || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
5418                // The subtle difference between the window for mTopFullscreenOpaqueWindowState
5419                // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
5420                // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
5421                // case though.
5422                if (mStatusBarController.isTransientShowing()) {
5423                    if (mStatusBarController.setBarShowingLw(true)) {
5424                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5425                    }
5426                } else if (topIsFullscreen
5427                        && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)
5428                        && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) {
5429                    if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
5430                    if (mStatusBarController.setBarShowingLw(false)) {
5431                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5432                    } else {
5433                        if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
5434                    }
5435                } else {
5436                    if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
5437                    if (mStatusBarController.setBarShowingLw(true)) {
5438                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5439                    }
5440                }
5441            }
5442        }
5443
5444        if (mTopIsFullscreen != topIsFullscreen) {
5445            if (!topIsFullscreen) {
5446                // Force another layout when status bar becomes fully shown.
5447                changes |= FINISH_LAYOUT_REDO_LAYOUT;
5448            }
5449            mTopIsFullscreen = topIsFullscreen;
5450        }
5451
5452        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5453            // If the navigation bar has been hidden or shown, we need to do another
5454            // layout pass to update that window.
5455            changes |= FINISH_LAYOUT_REDO_LAYOUT;
5456        }
5457
5458        if (mShowingDream != mLastShowingDream) {
5459            mLastShowingDream = mShowingDream;
5460            mWindowManagerFuncs.notifyShowingDreamChanged();
5461        }
5462
5463        // update since mAllowLockscreenWhenOn might have changed
5464        updateLockScreenTimeout();
5465        return changes;
5466    }
5467
5468    /**
5469     * Updates the occluded state of the Keyguard.
5470     *
5471     * @return Whether the flags have changed and we have to redo the layout.
5472     */
5473    private boolean setKeyguardOccludedLw(boolean isOccluded) {
5474        if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded);
5475        boolean wasOccluded = mKeyguardOccluded;
5476        boolean showing = mKeyguardDelegate.isShowing();
5477        if (wasOccluded && !isOccluded && showing) {
5478            mKeyguardOccluded = false;
5479            mKeyguardDelegate.setOccluded(false, true /* animate */);
5480            mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
5481            if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
5482                mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5483            }
5484            return true;
5485        } else if (!wasOccluded && isOccluded && showing) {
5486            mKeyguardOccluded = true;
5487            mKeyguardDelegate.setOccluded(true, false /* animate */);
5488            mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
5489            mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
5490            return true;
5491        } else if (wasOccluded != isOccluded) {
5492            mKeyguardOccluded = isOccluded;
5493            mKeyguardDelegate.setOccluded(isOccluded, false /* animate */);
5494            return false;
5495        } else {
5496            return false;
5497        }
5498    }
5499
5500    private boolean isStatusBarKeyguard() {
5501        return mStatusBar != null
5502                && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
5503    }
5504
5505    @Override
5506    public boolean allowAppAnimationsLw() {
5507        if (mShowingDream) {
5508            // If keyguard or dreams is currently visible, no reason to animate behind it.
5509            return false;
5510        }
5511        return true;
5512    }
5513
5514    @Override
5515    public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
5516        mFocusedWindow = newFocus;
5517        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5518            // If the navigation bar has been hidden or shown, we need to do another
5519            // layout pass to update that window.
5520            return FINISH_LAYOUT_REDO_LAYOUT;
5521        }
5522        return 0;
5523    }
5524
5525    /** {@inheritDoc} */
5526    @Override
5527    public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
5528        // lid changed state
5529        final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
5530        if (newLidState == mLidState) {
5531            return;
5532        }
5533
5534        mLidState = newLidState;
5535        applyLidSwitchState();
5536        updateRotation(true);
5537
5538        if (lidOpen) {
5539            wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
5540                    "android.policy:LID");
5541        } else if (!mLidControlsSleep) {
5542            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
5543        }
5544    }
5545
5546    @Override
5547    public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
5548        int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
5549        if (mCameraLensCoverState == lensCoverState) {
5550            return;
5551        }
5552        if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
5553                lensCoverState == CAMERA_LENS_UNCOVERED) {
5554            Intent intent;
5555            final boolean keyguardActive = mKeyguardDelegate == null ? false :
5556                    mKeyguardDelegate.isShowing();
5557            if (keyguardActive) {
5558                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
5559            } else {
5560                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
5561            }
5562            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
5563                    "android.policy:CAMERA_COVER");
5564            startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
5565        }
5566        mCameraLensCoverState = lensCoverState;
5567    }
5568
5569    void setHdmiPlugged(boolean plugged) {
5570        if (mHdmiPlugged != plugged) {
5571            mHdmiPlugged = plugged;
5572            updateRotation(true, true);
5573            Intent intent = new Intent(ACTION_HDMI_PLUGGED);
5574            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
5575            intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
5576            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
5577        }
5578    }
5579
5580    void initializeHdmiState() {
5581        boolean plugged = false;
5582        // watch for HDMI plug messages if the hdmi switch exists
5583        if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
5584            mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
5585
5586            final String filename = "/sys/class/switch/hdmi/state";
5587            FileReader reader = null;
5588            try {
5589                reader = new FileReader(filename);
5590                char[] buf = new char[15];
5591                int n = reader.read(buf);
5592                if (n > 1) {
5593                    plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
5594                }
5595            } catch (IOException ex) {
5596                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5597            } catch (NumberFormatException ex) {
5598                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5599            } finally {
5600                if (reader != null) {
5601                    try {
5602                        reader.close();
5603                    } catch (IOException ex) {
5604                    }
5605                }
5606            }
5607        }
5608        // This dance forces the code in setHdmiPlugged to run.
5609        // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
5610        mHdmiPlugged = !plugged;
5611        setHdmiPlugged(!mHdmiPlugged);
5612    }
5613
5614    final Object mScreenshotLock = new Object();
5615    ServiceConnection mScreenshotConnection = null;
5616
5617    final Runnable mScreenshotTimeout = new Runnable() {
5618        @Override public void run() {
5619            synchronized (mScreenshotLock) {
5620                if (mScreenshotConnection != null) {
5621                    mContext.unbindService(mScreenshotConnection);
5622                    mScreenshotConnection = null;
5623                    notifyScreenshotError();
5624                }
5625            }
5626        }
5627    };
5628
5629    // Assume this is called from the Handler thread.
5630    private void takeScreenshot(final int screenshotType) {
5631        synchronized (mScreenshotLock) {
5632            if (mScreenshotConnection != null) {
5633                return;
5634            }
5635            final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
5636                    SYSUI_SCREENSHOT_SERVICE);
5637            final Intent serviceIntent = new Intent();
5638            serviceIntent.setComponent(serviceComponent);
5639            ServiceConnection conn = new ServiceConnection() {
5640                @Override
5641                public void onServiceConnected(ComponentName name, IBinder service) {
5642                    synchronized (mScreenshotLock) {
5643                        if (mScreenshotConnection != this) {
5644                            return;
5645                        }
5646                        Messenger messenger = new Messenger(service);
5647                        Message msg = Message.obtain(null, screenshotType);
5648                        final ServiceConnection myConn = this;
5649                        Handler h = new Handler(mHandler.getLooper()) {
5650                            @Override
5651                            public void handleMessage(Message msg) {
5652                                synchronized (mScreenshotLock) {
5653                                    if (mScreenshotConnection == myConn) {
5654                                        mContext.unbindService(mScreenshotConnection);
5655                                        mScreenshotConnection = null;
5656                                        mHandler.removeCallbacks(mScreenshotTimeout);
5657                                    }
5658                                }
5659                            }
5660                        };
5661                        msg.replyTo = new Messenger(h);
5662                        msg.arg1 = msg.arg2 = 0;
5663                        if (mStatusBar != null && mStatusBar.isVisibleLw())
5664                            msg.arg1 = 1;
5665                        if (mNavigationBar != null && mNavigationBar.isVisibleLw())
5666                            msg.arg2 = 1;
5667                        try {
5668                            messenger.send(msg);
5669                        } catch (RemoteException e) {
5670                        }
5671                    }
5672                }
5673
5674                @Override
5675                public void onServiceDisconnected(ComponentName name) {
5676                    synchronized (mScreenshotLock) {
5677                        if (mScreenshotConnection != null) {
5678                            mContext.unbindService(mScreenshotConnection);
5679                            mScreenshotConnection = null;
5680                            mHandler.removeCallbacks(mScreenshotTimeout);
5681                            notifyScreenshotError();
5682                        }
5683                    }
5684                }
5685            };
5686            if (mContext.bindServiceAsUser(serviceIntent, conn,
5687                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
5688                    UserHandle.CURRENT)) {
5689                mScreenshotConnection = conn;
5690                mHandler.postDelayed(mScreenshotTimeout, 10000);
5691            }
5692        }
5693    }
5694
5695    /**
5696     * Notifies the screenshot service to show an error.
5697     */
5698    private void notifyScreenshotError() {
5699        // If the service process is killed, then ask it to clean up after itself
5700        final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
5701                SYSUI_SCREENSHOT_ERROR_RECEIVER);
5702        Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
5703        errorIntent.setComponent(errorComponent);
5704        errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
5705                Intent.FLAG_RECEIVER_FOREGROUND);
5706        mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT);
5707    }
5708
5709    /** {@inheritDoc} */
5710    @Override
5711    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
5712        if (!mSystemBooted) {
5713            // If we have not yet booted, don't let key events do anything.
5714            return 0;
5715        }
5716
5717        final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
5718        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
5719        final boolean canceled = event.isCanceled();
5720        final int keyCode = event.getKeyCode();
5721
5722        final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
5723
5724        // If screen is off then we treat the case where the keyguard is open but hidden
5725        // the same as if it were open and in front.
5726        // This will prevent any keys other than the power button from waking the screen
5727        // when the keyguard is hidden by another activity.
5728        final boolean keyguardActive = (mKeyguardDelegate == null ? false :
5729                                            (interactive ?
5730                                                isKeyguardShowingAndNotOccluded() :
5731                                                mKeyguardDelegate.isShowing()));
5732
5733        if (DEBUG_INPUT) {
5734            Log.d(TAG, "interceptKeyTq keycode=" + keyCode
5735                    + " interactive=" + interactive + " keyguardActive=" + keyguardActive
5736                    + " policyFlags=" + Integer.toHexString(policyFlags));
5737        }
5738
5739        // Basic policy based on interactive state.
5740        int result;
5741        boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
5742                || event.isWakeKey();
5743        if (interactive || (isInjected && !isWakeKey)) {
5744            // When the device is interactive or the key is injected pass the
5745            // key to the application.
5746            result = ACTION_PASS_TO_USER;
5747            isWakeKey = false;
5748
5749            if (interactive) {
5750                // If the screen is awake, but the button pressed was the one that woke the device
5751                // then don't pass it to the application
5752                if (keyCode == mPendingWakeKey && !down) {
5753                    result = 0;
5754                }
5755                // Reset the pending key
5756                mPendingWakeKey = PENDING_KEY_NULL;
5757            }
5758        } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
5759            // If we're currently dozing with the screen on and the keyguard showing, pass the key
5760            // to the application but preserve its wake key status to make sure we still move
5761            // from dozing to fully interactive if we would normally go from off to fully
5762            // interactive.
5763            result = ACTION_PASS_TO_USER;
5764            // Since we're dispatching the input, reset the pending key
5765            mPendingWakeKey = PENDING_KEY_NULL;
5766        } else {
5767            // When the screen is off and the key is not injected, determine whether
5768            // to wake the device but don't pass the key to the application.
5769            result = 0;
5770            if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
5771                isWakeKey = false;
5772            }
5773            // Cache the wake key on down event so we can also avoid sending the up event to the app
5774            if (isWakeKey && down) {
5775                mPendingWakeKey = keyCode;
5776            }
5777        }
5778
5779        // If the key would be handled globally, just return the result, don't worry about special
5780        // key processing.
5781        if (isValidGlobalKey(keyCode)
5782                && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
5783            if (isWakeKey) {
5784                wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5785            }
5786            return result;
5787        }
5788
5789        boolean useHapticFeedback = down
5790                && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
5791                && event.getRepeatCount() == 0;
5792
5793        // Handle special keys.
5794        switch (keyCode) {
5795            case KeyEvent.KEYCODE_BACK: {
5796                if (down) {
5797                    interceptBackKeyDown();
5798                } else {
5799                    boolean handled = interceptBackKeyUp(event);
5800
5801                    // Don't pass back press to app if we've already handled it via long press
5802                    if (handled) {
5803                        result &= ~ACTION_PASS_TO_USER;
5804                    }
5805                }
5806                break;
5807            }
5808
5809            case KeyEvent.KEYCODE_VOLUME_DOWN:
5810            case KeyEvent.KEYCODE_VOLUME_UP:
5811            case KeyEvent.KEYCODE_VOLUME_MUTE: {
5812                if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
5813                    if (down) {
5814                        if (interactive && !mScreenshotChordVolumeDownKeyTriggered
5815                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5816                            mScreenshotChordVolumeDownKeyTriggered = true;
5817                            mScreenshotChordVolumeDownKeyTime = event.getDownTime();
5818                            mScreenshotChordVolumeDownKeyConsumed = false;
5819                            cancelPendingPowerKeyAction();
5820                            interceptScreenshotChord();
5821                            if (!isKeyguardLocked()) {
5822                                interceptAccessibilityShortcutChord();
5823                            }
5824                        }
5825                    } else {
5826                        mScreenshotChordVolumeDownKeyTriggered = false;
5827                        cancelPendingScreenshotChordAction();
5828                        cancelPendingAccessibilityShortcutAction();
5829                    }
5830                } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
5831                    if (down) {
5832                        if (interactive && !mA11yShortcutChordVolumeUpKeyTriggered
5833                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5834                            mA11yShortcutChordVolumeUpKeyTriggered = true;
5835                            mA11yShortcutChordVolumeUpKeyTime = event.getDownTime();
5836                            mA11yShortcutChordVolumeUpKeyConsumed = false;
5837                            cancelPendingPowerKeyAction();
5838                            cancelPendingScreenshotChordAction();
5839                            if (!isKeyguardLocked()) {
5840                                interceptAccessibilityShortcutChord();
5841                            }
5842                        }
5843                    } else {
5844                        mA11yShortcutChordVolumeUpKeyTriggered = false;
5845                        cancelPendingScreenshotChordAction();
5846                        cancelPendingAccessibilityShortcutAction();
5847                    }
5848                }
5849                if (down) {
5850                    TelecomManager telecomManager = getTelecommService();
5851                    if (telecomManager != null) {
5852                        if (telecomManager.isRinging()) {
5853                            // If an incoming call is ringing, either VOLUME key means
5854                            // "silence ringer".  We handle these keys here, rather than
5855                            // in the InCallScreen, to make sure we'll respond to them
5856                            // even if the InCallScreen hasn't come to the foreground yet.
5857                            // Look for the DOWN event here, to agree with the "fallback"
5858                            // behavior in the InCallScreen.
5859                            Log.i(TAG, "interceptKeyBeforeQueueing:"
5860                                  + " VOLUME key-down while ringing: Silence ringer!");
5861
5862                            // Silence the ringer.  (It's safe to call this
5863                            // even if the ringer has already been silenced.)
5864                            telecomManager.silenceRinger();
5865
5866                            // And *don't* pass this key thru to the current activity
5867                            // (which is probably the InCallScreen.)
5868                            result &= ~ACTION_PASS_TO_USER;
5869                            break;
5870                        }
5871                        if (telecomManager.isInCall()
5872                                && (result & ACTION_PASS_TO_USER) == 0) {
5873                            // If we are in call but we decided not to pass the key to
5874                            // the application, just pass it to the session service.
5875                            MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
5876                                    event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
5877                            break;
5878                        }
5879                    }
5880                }
5881                if (mUseTvRouting) {
5882                    // On TVs, defer special key handlings to
5883                    // {@link interceptKeyBeforeDispatching()}.
5884                    result |= ACTION_PASS_TO_USER;
5885                } else if ((result & ACTION_PASS_TO_USER) == 0) {
5886                    // If we aren't passing to the user and no one else
5887                    // handled it send it to the session manager to
5888                    // figure out.
5889                    MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
5890                            event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
5891                }
5892                break;
5893            }
5894
5895            case KeyEvent.KEYCODE_ENDCALL: {
5896                result &= ~ACTION_PASS_TO_USER;
5897                if (down) {
5898                    TelecomManager telecomManager = getTelecommService();
5899                    boolean hungUp = false;
5900                    if (telecomManager != null) {
5901                        hungUp = telecomManager.endCall();
5902                    }
5903                    if (interactive && !hungUp) {
5904                        mEndCallKeyHandled = false;
5905                        mHandler.postDelayed(mEndCallLongPress,
5906                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
5907                    } else {
5908                        mEndCallKeyHandled = true;
5909                    }
5910                } else {
5911                    if (!mEndCallKeyHandled) {
5912                        mHandler.removeCallbacks(mEndCallLongPress);
5913                        if (!canceled) {
5914                            if ((mEndcallBehavior
5915                                    & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
5916                                if (goHome()) {
5917                                    break;
5918                                }
5919                            }
5920                            if ((mEndcallBehavior
5921                                    & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
5922                                mPowerManager.goToSleep(event.getEventTime(),
5923                                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
5924                                isWakeKey = false;
5925                            }
5926                        }
5927                    }
5928                }
5929                break;
5930            }
5931
5932            case KeyEvent.KEYCODE_POWER: {
5933                // Any activity on the power button stops the accessibility shortcut
5934                cancelPendingAccessibilityShortcutAction();
5935                result &= ~ACTION_PASS_TO_USER;
5936                isWakeKey = false; // wake-up will be handled separately
5937                if (down) {
5938                    interceptPowerKeyDown(event, interactive);
5939                } else {
5940                    interceptPowerKeyUp(event, interactive, canceled);
5941                }
5942                break;
5943            }
5944
5945            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
5946                // fall through
5947            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
5948                // fall through
5949            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
5950                // fall through
5951            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
5952                result &= ~ACTION_PASS_TO_USER;
5953                interceptSystemNavigationKey(event);
5954                break;
5955            }
5956
5957            case KeyEvent.KEYCODE_SLEEP: {
5958                result &= ~ACTION_PASS_TO_USER;
5959                isWakeKey = false;
5960                if (!mPowerManager.isInteractive()) {
5961                    useHapticFeedback = false; // suppress feedback if already non-interactive
5962                }
5963                if (down) {
5964                    sleepPress(event.getEventTime());
5965                } else {
5966                    sleepRelease(event.getEventTime());
5967                }
5968                break;
5969            }
5970
5971            case KeyEvent.KEYCODE_SOFT_SLEEP: {
5972                result &= ~ACTION_PASS_TO_USER;
5973                isWakeKey = false;
5974                if (!down) {
5975                    mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
5976                }
5977                break;
5978            }
5979
5980            case KeyEvent.KEYCODE_WAKEUP: {
5981                result &= ~ACTION_PASS_TO_USER;
5982                isWakeKey = true;
5983                break;
5984            }
5985
5986            case KeyEvent.KEYCODE_MEDIA_PLAY:
5987            case KeyEvent.KEYCODE_MEDIA_PAUSE:
5988            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
5989            case KeyEvent.KEYCODE_HEADSETHOOK:
5990            case KeyEvent.KEYCODE_MUTE:
5991            case KeyEvent.KEYCODE_MEDIA_STOP:
5992            case KeyEvent.KEYCODE_MEDIA_NEXT:
5993            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
5994            case KeyEvent.KEYCODE_MEDIA_REWIND:
5995            case KeyEvent.KEYCODE_MEDIA_RECORD:
5996            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
5997            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
5998                if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
5999                    // If the global session is active pass all media keys to it
6000                    // instead of the active window.
6001                    result &= ~ACTION_PASS_TO_USER;
6002                }
6003                if ((result & ACTION_PASS_TO_USER) == 0) {
6004                    // Only do this if we would otherwise not pass it to the user. In that
6005                    // case, the PhoneWindow class will do the same thing, except it will
6006                    // only do it if the showing app doesn't process the key on its own.
6007                    // Note that we need to make a copy of the key event here because the
6008                    // original key event will be recycled when we return.
6009                    mBroadcastWakeLock.acquire();
6010                    Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
6011                            new KeyEvent(event));
6012                    msg.setAsynchronous(true);
6013                    msg.sendToTarget();
6014                }
6015                break;
6016            }
6017
6018            case KeyEvent.KEYCODE_CALL: {
6019                if (down) {
6020                    TelecomManager telecomManager = getTelecommService();
6021                    if (telecomManager != null) {
6022                        if (telecomManager.isRinging()) {
6023                            Log.i(TAG, "interceptKeyBeforeQueueing:"
6024                                  + " CALL key-down while ringing: Answer the call!");
6025                            telecomManager.acceptRingingCall();
6026
6027                            // And *don't* pass this key thru to the current activity
6028                            // (which is presumably the InCallScreen.)
6029                            result &= ~ACTION_PASS_TO_USER;
6030                        }
6031                    }
6032                }
6033                break;
6034            }
6035            case KeyEvent.KEYCODE_VOICE_ASSIST: {
6036                // Only do this if we would otherwise not pass it to the user. In that case,
6037                // interceptKeyBeforeDispatching would apply a similar but different policy in
6038                // order to invoke voice assist actions. Note that we need to make a copy of the
6039                // key event here because the original key event will be recycled when we return.
6040                if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
6041                    mBroadcastWakeLock.acquire();
6042                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
6043                            keyguardActive ? 1 : 0, 0);
6044                    msg.setAsynchronous(true);
6045                    msg.sendToTarget();
6046                }
6047                break;
6048            }
6049            case KeyEvent.KEYCODE_WINDOW: {
6050                if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
6051                    if (mTvPictureInPictureVisible) {
6052                        // Consumes the key only if picture-in-picture is visible
6053                        // to show picture-in-picture control menu.
6054                        // This gives a chance to the foreground activity
6055                        // to customize PIP key behavior.
6056                        if (!down) {
6057                            showTvPictureInPictureMenu(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        StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
7944        if (statusBar != null) {
7945            statusBar.setCurrentUser(newUserId);
7946        }
7947        setLastInputMethodWindowLw(null, null);
7948    }
7949
7950    @Override
7951    public void setSwitchingUser(boolean switching) {
7952        mKeyguardDelegate.setSwitchingUser(switching);
7953    }
7954
7955    @Override
7956    public boolean canMagnifyWindow(int windowType) {
7957        switch (windowType) {
7958            case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
7959            case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
7960            case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
7961            case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
7962                return false;
7963            }
7964        }
7965        return true;
7966    }
7967
7968    @Override
7969    public boolean isTopLevelWindow(int windowType) {
7970        if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
7971                && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
7972            return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
7973        }
7974        return true;
7975    }
7976
7977    @Override
7978    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
7979        // For the upside down rotation we don't rotate seamlessly as the navigation
7980        // bar moves position.
7981        // Note most apps (using orientation:sensor or user as opposed to fullSensor)
7982        // will not enter the reverse portrait orientation, so actually the
7983        // orientation won't change at all.
7984        if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
7985            return false;
7986        }
7987        // If the navigation bar can't change sides, then it will
7988        // jump when we change orientations and we don't rotate
7989        // seamlessly.
7990        if (!mNavigationBarCanMove) {
7991            return false;
7992        }
7993        int delta = newRotation - oldRotation;
7994        if (delta < 0) delta += 4;
7995        // Likewise we don't rotate seamlessly for 180 degree rotations
7996        // in this case the surfaces never resize, and our logic to
7997        // revert the transformations on size change will fail. We could
7998        // fix this in the future with the "tagged" frames idea.
7999        if (delta == Surface.ROTATION_180) {
8000            return false;
8001        }
8002
8003        final WindowState w = mTopFullscreenOpaqueWindowState;
8004        if (w != mFocusedWindow) {
8005            return false;
8006        }
8007
8008        // We only enable seamless rotation if the top window has requested
8009        // it and is in the fullscreen opaque state. Seamless rotation
8010        // requires freezing various Surface states and won't work well
8011        // with animations, so we disable it in the animation case for now.
8012        if (w != null && !w.isAnimatingLw() &&
8013                ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) ||
8014                        (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) {
8015            return true;
8016        }
8017        return false;
8018    }
8019
8020    @Override
8021    public void dump(String prefix, PrintWriter pw, String[] args) {
8022        pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
8023                pw.print(" mSystemReady="); pw.print(mSystemReady);
8024                pw.print(" mSystemBooted="); pw.println(mSystemBooted);
8025        pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
8026                pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
8027                pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
8028                pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
8029        if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
8030                || mForceClearedSystemUiFlags != 0) {
8031            pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
8032                    pw.print(Integer.toHexString(mLastSystemUiFlags));
8033                    pw.print(" mResettingSystemUiFlags=0x");
8034                    pw.print(Integer.toHexString(mResettingSystemUiFlags));
8035                    pw.print(" mForceClearedSystemUiFlags=0x");
8036                    pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
8037        }
8038        if (mLastFocusNeedsMenu) {
8039            pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
8040                    pw.println(mLastFocusNeedsMenu);
8041        }
8042        pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
8043                pw.println(mWakeGestureEnabledSetting);
8044
8045        pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
8046        pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
8047                pw.print(" mDockMode="); pw.print(mDockMode);
8048                pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
8049                pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
8050                pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
8051        pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
8052                pw.print(" mUserRotation="); pw.print(mUserRotation);
8053                pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
8054        pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
8055        pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
8056                pw.print(mCarDockEnablesAccelerometer);
8057                pw.print(" mDeskDockEnablesAccelerometer=");
8058                pw.println(mDeskDockEnablesAccelerometer);
8059        pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
8060                pw.print(mLidKeyboardAccessibility);
8061                pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
8062                pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
8063                pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
8064        pw.print(prefix);
8065                pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
8066        pw.print(prefix);
8067                pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
8068                pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
8069        pw.print(prefix);
8070                pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
8071                pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
8072        pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
8073        pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
8074        pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
8075                pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
8076        pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
8077                pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
8078        pw.print(prefix); pw.print("mOrientationSensorEnabled=");
8079                pw.println(mOrientationSensorEnabled);
8080        pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
8081                pw.print(","); pw.print(mOverscanScreenTop);
8082                pw.print(") "); pw.print(mOverscanScreenWidth);
8083                pw.print("x"); pw.println(mOverscanScreenHeight);
8084        if (mOverscanLeft != 0 || mOverscanTop != 0
8085                || mOverscanRight != 0 || mOverscanBottom != 0) {
8086            pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
8087                    pw.print(" top="); pw.print(mOverscanTop);
8088                    pw.print(" right="); pw.print(mOverscanRight);
8089                    pw.print(" bottom="); pw.println(mOverscanBottom);
8090        }
8091        pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
8092                pw.print(mRestrictedOverscanScreenLeft);
8093                pw.print(","); pw.print(mRestrictedOverscanScreenTop);
8094                pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
8095                pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
8096        pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
8097                pw.print(","); pw.print(mUnrestrictedScreenTop);
8098                pw.print(") "); pw.print(mUnrestrictedScreenWidth);
8099                pw.print("x"); pw.println(mUnrestrictedScreenHeight);
8100        pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
8101                pw.print(","); pw.print(mRestrictedScreenTop);
8102                pw.print(") "); pw.print(mRestrictedScreenWidth);
8103                pw.print("x"); pw.println(mRestrictedScreenHeight);
8104        pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
8105                pw.print(","); pw.print(mStableFullscreenTop);
8106                pw.print(")-("); pw.print(mStableFullscreenRight);
8107                pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
8108        pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
8109                pw.print(","); pw.print(mStableTop);
8110                pw.print(")-("); pw.print(mStableRight);
8111                pw.print(","); pw.print(mStableBottom); pw.println(")");
8112        pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
8113                pw.print(","); pw.print(mSystemTop);
8114                pw.print(")-("); pw.print(mSystemRight);
8115                pw.print(","); pw.print(mSystemBottom); pw.println(")");
8116        pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
8117                pw.print(","); pw.print(mCurTop);
8118                pw.print(")-("); pw.print(mCurRight);
8119                pw.print(","); pw.print(mCurBottom); pw.println(")");
8120        pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
8121                pw.print(","); pw.print(mContentTop);
8122                pw.print(")-("); pw.print(mContentRight);
8123                pw.print(","); pw.print(mContentBottom); pw.println(")");
8124        pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft);
8125                pw.print(","); pw.print(mVoiceContentTop);
8126                pw.print(")-("); pw.print(mVoiceContentRight);
8127                pw.print(","); pw.print(mVoiceContentBottom); pw.println(")");
8128        pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
8129                pw.print(","); pw.print(mDockTop);
8130                pw.print(")-("); pw.print(mDockRight);
8131                pw.print(","); pw.print(mDockBottom); pw.println(")");
8132        pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
8133                pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
8134        pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
8135                pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
8136                pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
8137        if (mLastInputMethodWindow != null) {
8138            pw.print(prefix); pw.print("mLastInputMethodWindow=");
8139                    pw.println(mLastInputMethodWindow);
8140        }
8141        if (mLastInputMethodTargetWindow != null) {
8142            pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
8143                    pw.println(mLastInputMethodTargetWindow);
8144        }
8145        if (mStatusBar != null) {
8146            pw.print(prefix); pw.print("mStatusBar=");
8147                    pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
8148                    pw.println(isStatusBarKeyguard());
8149        }
8150        if (mNavigationBar != null) {
8151            pw.print(prefix); pw.print("mNavigationBar=");
8152                    pw.println(mNavigationBar);
8153        }
8154        if (mFocusedWindow != null) {
8155            pw.print(prefix); pw.print("mFocusedWindow=");
8156                    pw.println(mFocusedWindow);
8157        }
8158        if (mFocusedApp != null) {
8159            pw.print(prefix); pw.print("mFocusedApp=");
8160                    pw.println(mFocusedApp);
8161        }
8162        if (mTopFullscreenOpaqueWindowState != null) {
8163            pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
8164                    pw.println(mTopFullscreenOpaqueWindowState);
8165        }
8166        if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
8167            pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
8168                    pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
8169        }
8170        if (mForcingShowNavBar) {
8171            pw.print(prefix); pw.print("mForcingShowNavBar=");
8172                    pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
8173                    pw.println(mForcingShowNavBarLayer);
8174        }
8175        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
8176                pw.print(" mKeyguardOccluded="); pw.println(mKeyguardOccluded);
8177                pw.print(" mKeyguardOccludedChanged="); pw.println(mKeyguardOccludedChanged);
8178                pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded);
8179        pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
8180                pw.print(" mForceStatusBarFromKeyguard=");
8181                pw.println(mForceStatusBarFromKeyguard);
8182        pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
8183        pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
8184                pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
8185                pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
8186        pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
8187                pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
8188                pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior);
8189                pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
8190        pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
8191                pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
8192        pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
8193                pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
8194        pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
8195                pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
8196        pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
8197
8198        mGlobalKeyManager.dump(prefix, pw);
8199        mStatusBarController.dump(pw, prefix);
8200        mNavigationBarController.dump(pw, prefix);
8201        PolicyControl.dump(prefix, pw);
8202
8203        if (mWakeGestureListener != null) {
8204            mWakeGestureListener.dump(pw, prefix);
8205        }
8206        if (mOrientationListener != null) {
8207            mOrientationListener.dump(pw, prefix);
8208        }
8209        if (mBurnInProtectionHelper != null) {
8210            mBurnInProtectionHelper.dump(prefix, pw);
8211        }
8212        if (mKeyguardDelegate != null) {
8213            mKeyguardDelegate.dump(prefix, pw);
8214        }
8215    }
8216}
8217