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