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