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