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