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