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