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