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