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