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