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