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