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