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