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