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