PhoneWindowManager.java revision 28f0e5bf48e2d02e1f063670e435b1232f07ba03
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
181    // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
182    // No longer recommended for desk docks;
183    static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
184
185    static final boolean ALTERNATE_CAR_MODE_NAV_SIZE = false;
186
187    static final int SHORT_PRESS_POWER_NOTHING = 0;
188    static final int SHORT_PRESS_POWER_GO_TO_SLEEP = 1;
189    static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2;
190    static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3;
191    static final int SHORT_PRESS_POWER_GO_HOME = 4;
192
193    static final int LONG_PRESS_POWER_NOTHING = 0;
194    static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
195    static final int LONG_PRESS_POWER_SHUT_OFF = 2;
196    static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
197
198    static final int LONG_PRESS_BACK_NOTHING = 0;
199    static final int LONG_PRESS_BACK_GO_TO_VOICE_ASSIST = 1;
200
201    static final int MULTI_PRESS_POWER_NOTHING = 0;
202    static final int MULTI_PRESS_POWER_THEATER_MODE = 1;
203    static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2;
204
205    // Number of presses needed before we induce panic press behavior on the back button
206    static final int PANIC_PRESS_BACK_COUNT = 4;
207    static final int PANIC_PRESS_BACK_NOTHING = 0;
208    static final int PANIC_PRESS_BACK_HOME = 1;
209
210    // These need to match the documentation/constant in
211    // core/res/res/values/config.xml
212    static final int LONG_PRESS_HOME_NOTHING = 0;
213    static final int LONG_PRESS_HOME_RECENT_SYSTEM_UI = 1;
214    static final int LONG_PRESS_HOME_ASSIST = 2;
215    static final int LAST_LONG_PRESS_HOME_BEHAVIOR = LONG_PRESS_HOME_ASSIST;
216
217    static final int DOUBLE_TAP_HOME_NOTHING = 0;
218    static final int DOUBLE_TAP_HOME_RECENT_SYSTEM_UI = 1;
219
220    static final int SHORT_PRESS_WINDOW_NOTHING = 0;
221    static final int SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE = 1;
222
223    static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP = 0;
224    static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME = 1;
225
226    static final int PENDING_KEY_NULL = -1;
227
228    // Controls navigation bar opacity depending on which workspace stacks are currently
229    // visible.
230    // Nav bar is always opaque when either the freeform stack or docked stack is visible.
231    static final int NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED = 0;
232    // Nav bar is always translucent when the freeform stack is visible, otherwise always opaque.
233    static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1;
234
235    static final int APPLICATION_MEDIA_SUBLAYER = -2;
236    static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
237    static final int APPLICATION_PANEL_SUBLAYER = 1;
238    static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
239    static final int APPLICATION_ABOVE_SUB_PANEL_SUBLAYER = 3;
240
241    static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
242    static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
243    static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
244    static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
245    static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";
246
247    /**
248     * These are the system UI flags that, when changing, can cause the layout
249     * of the screen to change.
250     */
251    static final int SYSTEM_UI_CHANGING_LAYOUT =
252              View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
253            | View.SYSTEM_UI_FLAG_FULLSCREEN
254            | View.STATUS_BAR_TRANSLUCENT
255            | View.NAVIGATION_BAR_TRANSLUCENT
256            | View.STATUS_BAR_TRANSPARENT
257            | View.NAVIGATION_BAR_TRANSPARENT;
258
259    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
260            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
261            .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
262            .build();
263
264    // The panic gesture may become active only after the keyguard is dismissed and the immersive
265    // app shows again. If that doesn't happen for 30s we drop the gesture.
266    private static final long PANIC_GESTURE_EXPIRATION = 30000;
267
268    private static final String SYSUI_PACKAGE = "com.android.systemui";
269    private static final String SYSUI_SCREENSHOT_SERVICE =
270            "com.android.systemui.screenshot.TakeScreenshotService";
271    private static final String SYSUI_SCREENSHOT_ERROR_RECEIVER =
272            "com.android.systemui.screenshot.ScreenshotServiceErrorReceiver";
273
274    private static final int NAV_BAR_BOTTOM = 0;
275    private static final int NAV_BAR_RIGHT = 1;
276    private static final int NAV_BAR_LEFT = 2;
277
278    /**
279     * Keyguard stuff
280     */
281    private WindowState mKeyguardScrim;
282    private boolean mKeyguardHidden;
283    private boolean mKeyguardDrawnOnce;
284
285    /* Table of Application Launch keys.  Maps from key codes to intent categories.
286     *
287     * These are special keys that are used to launch particular kinds of applications,
288     * such as a web browser.  HID defines nearly a hundred of them in the Consumer (0x0C)
289     * usage page.  We don't support quite that many yet...
290     */
291    static SparseArray<String> sApplicationLaunchKeyCategories;
292    static {
293        sApplicationLaunchKeyCategories = new SparseArray<String>();
294        sApplicationLaunchKeyCategories.append(
295                KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER);
296        sApplicationLaunchKeyCategories.append(
297                KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL);
298        sApplicationLaunchKeyCategories.append(
299                KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS);
300        sApplicationLaunchKeyCategories.append(
301                KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR);
302        sApplicationLaunchKeyCategories.append(
303                KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC);
304        sApplicationLaunchKeyCategories.append(
305                KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
306    }
307
308    /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
309    static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;
310
311    /** Amount of time (in milliseconds) a toast window can be shown. */
312    public static final int TOAST_WINDOW_TIMEOUT = 3500; // 3.5 seconds
313
314    /**
315     * Lock protecting internal state.  Must not call out into window
316     * manager with lock held.  (This lock will be acquired in places
317     * where the window manager is calling in with its own lock held.)
318     */
319    private final Object mLock = new Object();
320
321    Context mContext;
322    IWindowManager mWindowManager;
323    WindowManagerFuncs mWindowManagerFuncs;
324    WindowManagerInternal mWindowManagerInternal;
325    PowerManager mPowerManager;
326    ActivityManagerInternal mActivityManagerInternal;
327    InputManagerInternal mInputManagerInternal;
328    DreamManagerInternal mDreamManagerInternal;
329    PowerManagerInternal mPowerManagerInternal;
330    IStatusBarService mStatusBarService;
331    StatusBarManagerInternal mStatusBarManagerInternal;
332    boolean mPreloadedRecentApps;
333    final Object mServiceAquireLock = new Object();
334    Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
335    SearchManager mSearchManager;
336    AccessibilityManager mAccessibilityManager;
337    BurnInProtectionHelper mBurnInProtectionHelper;
338    AppOpsManager mAppOpsManager;
339    private boolean mHasFeatureWatch;
340
341    // Vibrator pattern for haptic feedback of a long press.
342    long[] mLongPressVibePattern;
343
344    // Vibrator pattern for haptic feedback of virtual key press.
345    long[] mVirtualKeyVibePattern;
346
347    // Vibrator pattern for a short vibration.
348    long[] mKeyboardTapVibePattern;
349
350    // Vibrator pattern for a short vibration when tapping on an hour/minute tick of a Clock.
351    long[] mClockTickVibePattern;
352
353    // Vibrator pattern for a short vibration when tapping on a day/month/year date of a Calendar.
354    long[] mCalendarDateVibePattern;
355
356    // Vibrator pattern for haptic feedback during boot when safe mode is disabled.
357    long[] mSafeModeDisabledVibePattern;
358
359    // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
360    long[] mSafeModeEnabledVibePattern;
361
362    // Vibrator pattern for haptic feedback of a context click.
363    long[] mContextClickVibePattern;
364
365    /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
366    boolean mEnableShiftMenuBugReports = false;
367
368    boolean mSafeMode;
369    WindowState mStatusBar = null;
370    int mStatusBarHeight;
371    WindowState mNavigationBar = null;
372    boolean mHasNavigationBar = false;
373    boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?
374    int mNavigationBarPosition = NAV_BAR_BOTTOM;
375    int[] mNavigationBarHeightForRotationDefault = new int[4];
376    int[] mNavigationBarWidthForRotationDefault = new int[4];
377    int[] mNavigationBarHeightForRotationInCarMode = new int[4];
378    int[] mNavigationBarWidthForRotationInCarMode = new int[4];
379
380    private LongSparseArray<IShortcutService> mShortcutKeyServices = new LongSparseArray<>();
381
382    // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
383    // This is for car dock and this is updated from resource.
384    private boolean mEnableCarDockHomeCapture = true;
385
386    boolean mBootMessageNeedsHiding;
387    KeyguardServiceDelegate mKeyguardDelegate;
388    final Runnable mWindowManagerDrawCallback = new Runnable() {
389        @Override
390        public void run() {
391            if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!");
392            mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);
393        }
394    };
395    final DrawnListener mKeyguardDrawnCallback = new DrawnListener() {
396        @Override
397        public void onDrawn() {
398            if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn.");
399            mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
400        }
401    };
402
403    GlobalActions mGlobalActions;
404    Handler mHandler;
405    WindowState mLastInputMethodWindow = null;
406    WindowState mLastInputMethodTargetWindow = null;
407
408    // FIXME This state is shared between the input reader and handler thread.
409    // Technically it's broken and buggy but it has been like this for many years
410    // and we have not yet seen any problems.  Someday we'll rewrite this logic
411    // so that only one thread is involved in handling input policy.  Unfortunately
412    // it's on a critical path for power management so we can't just post the work to the
413    // handler thread.  We'll need to resolve this someday by teaching the input dispatcher
414    // to hold wakelocks during dispatch and eliminating the critical path.
415    volatile boolean mPowerKeyHandled;
416    volatile boolean mBackKeyHandled;
417    volatile boolean mBeganFromNonInteractive;
418    volatile int mPowerKeyPressCounter;
419    volatile int mBackKeyPressCounter;
420    volatile boolean mEndCallKeyHandled;
421    volatile boolean mCameraGestureTriggeredDuringGoingToSleep;
422    volatile boolean mGoingToSleep;
423    volatile boolean mRecentsVisible;
424    volatile boolean mTvPictureInPictureVisible;
425
426    // Used to hold the last user key used to wake the device.  This helps us prevent up events
427    // from being passed to the foregrounded app without a corresponding down event
428    volatile int mPendingWakeKey = PENDING_KEY_NULL;
429
430    int mRecentAppsHeldModifiers;
431    boolean mLanguageSwitchKeyPressed;
432
433    int mLidState = LID_ABSENT;
434    int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT;
435    boolean mHaveBuiltInKeyboard;
436
437    boolean mSystemReady;
438    boolean mSystemBooted;
439    private boolean mDeferBindKeyguard;
440    boolean mHdmiPlugged;
441    HdmiControl mHdmiControl;
442    IUiModeManager mUiModeManager;
443    int mUiMode;
444    int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
445    int mLidOpenRotation;
446    int mCarDockRotation;
447    int mDeskDockRotation;
448    int mUndockedHdmiRotation;
449    int mDemoHdmiRotation;
450    boolean mDemoHdmiRotationLock;
451    int mDemoRotation;
452    boolean mDemoRotationLock;
453
454    boolean mWakeGestureEnabledSetting;
455    MyWakeGestureListener mWakeGestureListener;
456
457    // Default display does not rotate, apps that require non-default orientation will have to
458    // have the orientation emulated.
459    private boolean mForceDefaultOrientation = false;
460
461    int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
462    int mUserRotation = Surface.ROTATION_0;
463    boolean mAccelerometerDefault;
464
465    boolean mSupportAutoRotation;
466    int mAllowAllRotations = -1;
467    boolean mCarDockEnablesAccelerometer;
468    boolean mDeskDockEnablesAccelerometer;
469    int mLidKeyboardAccessibility;
470    int mLidNavigationAccessibility;
471    boolean mLidControlsScreenLock;
472    boolean mLidControlsSleep;
473    int mShortPressOnPowerBehavior;
474    int mLongPressOnPowerBehavior;
475    int mDoublePressOnPowerBehavior;
476    int mTriplePressOnPowerBehavior;
477    int mLongPressOnBackBehavior;
478    int mPanicPressOnBackBehavior;
479    int mShortPressOnSleepBehavior;
480    int mShortPressWindowBehavior;
481    boolean mAwake;
482    boolean mScreenOnEarly;
483    boolean mScreenOnFully;
484    ScreenOnListener mScreenOnListener;
485    boolean mKeyguardDrawComplete;
486    boolean mWindowManagerDrawComplete;
487    boolean mOrientationSensorEnabled = false;
488    int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
489    boolean mHasSoftInput = false;
490    boolean mTranslucentDecorEnabled = true;
491    boolean mUseTvRouting;
492
493    int mPointerLocationMode = 0; // guarded by mLock
494
495    // The last window we were told about in focusChanged.
496    WindowState mFocusedWindow;
497    IApplicationToken mFocusedApp;
498
499    PointerLocationView mPointerLocationView;
500
501    // The current size of the screen; really; extends into the overscan area of
502    // the screen and doesn't account for any system elements like the status bar.
503    int mOverscanScreenLeft, mOverscanScreenTop;
504    int mOverscanScreenWidth, mOverscanScreenHeight;
505    // The current visible size of the screen; really; (ir)regardless of whether the status
506    // bar can be hidden but not extending into the overscan area.
507    int mUnrestrictedScreenLeft, mUnrestrictedScreenTop;
508    int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight;
509    // Like mOverscanScreen*, but allowed to move into the overscan region where appropriate.
510    int mRestrictedOverscanScreenLeft, mRestrictedOverscanScreenTop;
511    int mRestrictedOverscanScreenWidth, mRestrictedOverscanScreenHeight;
512    // The current size of the screen; these may be different than (0,0)-(dw,dh)
513    // if the status bar can't be hidden; in that case it effectively carves out
514    // that area of the display from all other windows.
515    int mRestrictedScreenLeft, mRestrictedScreenTop;
516    int mRestrictedScreenWidth, mRestrictedScreenHeight;
517    // During layout, the current screen borders accounting for any currently
518    // visible system UI elements.
519    int mSystemLeft, mSystemTop, mSystemRight, mSystemBottom;
520    // For applications requesting stable content insets, these are them.
521    int mStableLeft, mStableTop, mStableRight, mStableBottom;
522    // For applications requesting stable content insets but have also set the
523    // fullscreen window flag, these are the stable dimensions without the status bar.
524    int mStableFullscreenLeft, mStableFullscreenTop;
525    int mStableFullscreenRight, mStableFullscreenBottom;
526    // During layout, the current screen borders with all outer decoration
527    // (status bar, input method dock) accounted for.
528    int mCurLeft, mCurTop, mCurRight, mCurBottom;
529    // During layout, the frame in which content should be displayed
530    // to the user, accounting for all screen decoration except for any
531    // space they deem as available for other content.  This is usually
532    // the same as mCur*, but may be larger if the screen decor has supplied
533    // content insets.
534    int mContentLeft, mContentTop, mContentRight, mContentBottom;
535    // During layout, the frame in which voice content should be displayed
536    // to the user, accounting for all screen decoration except for any
537    // space they deem as available for other content.
538    int mVoiceContentLeft, mVoiceContentTop, mVoiceContentRight, mVoiceContentBottom;
539    // During layout, the current screen borders along which input method
540    // windows are placed.
541    int mDockLeft, mDockTop, mDockRight, mDockBottom;
542    // During layout, the layer at which the doc window is placed.
543    int mDockLayer;
544    // During layout, this is the layer of the status bar.
545    int mStatusBarLayer;
546    int mLastSystemUiFlags;
547    // Bits that we are in the process of clearing, so we want to prevent
548    // them from being set by applications until everything has been updated
549    // to have them clear.
550    int mResettingSystemUiFlags = 0;
551    // Bits that we are currently always keeping cleared.
552    int mForceClearedSystemUiFlags = 0;
553    int mLastFullscreenStackSysUiFlags;
554    int mLastDockedStackSysUiFlags;
555    final Rect mNonDockedStackBounds = new Rect();
556    final Rect mDockedStackBounds = new Rect();
557    final Rect mLastNonDockedStackBounds = new Rect();
558    final Rect mLastDockedStackBounds = new Rect();
559
560    // What we last reported to system UI about whether the compatibility
561    // menu needs to be displayed.
562    boolean mLastFocusNeedsMenu = false;
563    // If nonzero, a panic gesture was performed at that time in uptime millis and is still pending.
564    private long mPendingPanicGestureUptime;
565
566    InputConsumer mInputConsumer = null;
567
568    static final Rect mTmpParentFrame = new Rect();
569    static final Rect mTmpDisplayFrame = new Rect();
570    static final Rect mTmpOverscanFrame = new Rect();
571    static final Rect mTmpContentFrame = new Rect();
572    static final Rect mTmpVisibleFrame = new Rect();
573    static final Rect mTmpDecorFrame = new Rect();
574    static final Rect mTmpStableFrame = new Rect();
575    static final Rect mTmpNavigationFrame = new Rect();
576    static final Rect mTmpOutsetFrame = new Rect();
577    private static final Rect mTmpRect = new Rect();
578
579    WindowState mTopFullscreenOpaqueWindowState;
580    WindowState mTopFullscreenOpaqueOrDimmingWindowState;
581    WindowState mTopDockedOpaqueWindowState;
582    WindowState mTopDockedOpaqueOrDimmingWindowState;
583    HashSet<IApplicationToken> mAppsToBeHidden = new HashSet<IApplicationToken>();
584    HashSet<IApplicationToken> mAppsThatDismissKeyguard = new HashSet<IApplicationToken>();
585    boolean mTopIsFullscreen;
586    boolean mForceStatusBar;
587    boolean mForceStatusBarFromKeyguard;
588    private boolean mForceStatusBarTransparent;
589    int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
590    boolean mHideLockScreen;
591    boolean mForcingShowNavBar;
592    int mForcingShowNavBarLayer;
593
594    // States of keyguard dismiss.
595    private static final int DISMISS_KEYGUARD_NONE = 0; // Keyguard not being dismissed.
596    private static final int DISMISS_KEYGUARD_START = 1; // Keyguard needs to be dismissed.
597    private static final int DISMISS_KEYGUARD_CONTINUE = 2; // Keyguard has been dismissed.
598    int mDismissKeyguard = DISMISS_KEYGUARD_NONE;
599
600    /**
601     * Indicates that we asked the Keyguard to be dismissed and we just wait for the Keyguard to
602     * dismiss itself.
603     */
604    @GuardedBy("Lw")
605    private boolean mCurrentlyDismissingKeyguard;
606
607    /** The window that is currently dismissing the keyguard. Dismissing the keyguard must only
608     * be done once per window. */
609    private WindowState mWinDismissingKeyguard;
610
611    /** When window is currently dismissing the keyguard, dismissing the keyguard must handle
612     * the keygaurd secure state change instantly case, e.g. the use case of inserting a PIN
613     * lock SIM card. This variable is used to record the previous keyguard secure state for
614     * monitoring secure state change on window dismissing keyguard. */
615    private boolean mSecureDismissingKeyguard;
616
617    /** The window that is currently showing "over" the keyguard. If there is an app window
618     * belonging to another app on top of this the keyguard shows. If there is a fullscreen
619     * app window under this, still dismiss the keyguard but don't show the app underneath. Show
620     * the wallpaper. */
621    private WindowState mWinShowWhenLocked;
622
623    boolean mShowingLockscreen;
624    boolean mShowingDream;
625    boolean mDreamingLockscreen;
626    boolean mDreamingSleepTokenNeeded;
627    SleepToken mDreamingSleepToken;
628    SleepToken mScreenOffSleepToken;
629    boolean mKeyguardSecure;
630    boolean mKeyguardSecureIncludingHidden;
631    volatile boolean mKeyguardOccluded;
632    boolean mHomePressed;
633    boolean mHomeConsumed;
634    boolean mHomeDoubleTapPending;
635    Intent mHomeIntent;
636    Intent mCarDockIntent;
637    Intent mDeskDockIntent;
638    boolean mSearchKeyShortcutPending;
639    boolean mConsumeSearchKeyUp;
640    boolean mAssistKeyLongPressed;
641    boolean mPendingMetaAction;
642    boolean mPendingCapsLockToggle;
643    int mMetaState;
644    int mInitialMetaState;
645    boolean mForceShowSystemBars;
646
647    // support for activating the lock screen while the screen is on
648    boolean mAllowLockscreenWhenOn;
649    int mLockScreenTimeout;
650    boolean mLockScreenTimerActive;
651
652    // Behavior of ENDCALL Button.  (See Settings.System.END_BUTTON_BEHAVIOR.)
653    int mEndcallBehavior;
654
655    // Behavior of POWER button while in-call and screen on.
656    // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
657    int mIncallPowerBehavior;
658
659    // Behavior of Back button while in-call and screen on
660    int mIncallBackBehavior;
661
662    Display mDisplay;
663
664    private int mDisplayRotation;
665
666    int mLandscapeRotation = 0;  // default landscape rotation
667    int mSeascapeRotation = 0;   // "other" landscape rotation, 180 degrees from mLandscapeRotation
668    int mPortraitRotation = 0;   // default portrait rotation
669    int mUpsideDownRotation = 0; // "other" portrait rotation
670
671    int mOverscanLeft = 0;
672    int mOverscanTop = 0;
673    int mOverscanRight = 0;
674    int mOverscanBottom = 0;
675
676    // What we do when the user long presses on home
677    private int mLongPressOnHomeBehavior;
678
679    // What we do when the user double-taps on home
680    private int mDoubleTapOnHomeBehavior;
681
682    // Allowed theater mode wake actions
683    private boolean mAllowTheaterModeWakeFromKey;
684    private boolean mAllowTheaterModeWakeFromPowerKey;
685    private boolean mAllowTheaterModeWakeFromMotion;
686    private boolean mAllowTheaterModeWakeFromMotionWhenNotDreaming;
687    private boolean mAllowTheaterModeWakeFromCameraLens;
688    private boolean mAllowTheaterModeWakeFromLidSwitch;
689    private boolean mAllowTheaterModeWakeFromWakeGesture;
690
691    // Whether to support long press from power button in non-interactive mode
692    private boolean mSupportLongPressPowerWhenNonInteractive;
693
694    // Whether to go to sleep entering theater mode from power button
695    private boolean mGoToSleepOnButtonPressTheaterMode;
696
697    // Screenshot trigger states
698    // Time to volume and power must be pressed within this interval of each other.
699    private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
700    // Increase the chord delay when taking a screenshot from the keyguard
701    private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f;
702    private boolean mScreenshotChordEnabled;
703    private boolean mScreenshotChordVolumeDownKeyTriggered;
704    private long mScreenshotChordVolumeDownKeyTime;
705    private boolean mScreenshotChordVolumeDownKeyConsumed;
706    private boolean mScreenshotChordVolumeUpKeyTriggered;
707    private boolean mScreenshotChordPowerKeyTriggered;
708    private long mScreenshotChordPowerKeyTime;
709
710    /* The number of steps between min and max brightness */
711    private static final int BRIGHTNESS_STEPS = 10;
712
713    SettingsObserver mSettingsObserver;
714    ShortcutManager mShortcutManager;
715    PowerManager.WakeLock mBroadcastWakeLock;
716    PowerManager.WakeLock mPowerKeyWakeLock;
717    boolean mHavePendingMediaKeyRepeatWithWakeLock;
718
719    private int mCurrentUserId;
720
721    // Maps global key codes to the components that will handle them.
722    private GlobalKeyManager mGlobalKeyManager;
723
724    // Fallback actions by key code.
725    private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions =
726            new SparseArray<KeyCharacterMap.FallbackAction>();
727
728    private final LogDecelerateInterpolator mLogDecelerateInterpolator
729            = new LogDecelerateInterpolator(100, 0);
730
731    private final MutableBoolean mTmpBoolean = new MutableBoolean(false);
732
733    private static final int MSG_ENABLE_POINTER_LOCATION = 1;
734    private static final int MSG_DISABLE_POINTER_LOCATION = 2;
735    private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
736    private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
737    private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
738    private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6;
739    private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7;
740    private static final int MSG_DISPATCH_SHOW_RECENTS = 9;
741    private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10;
742    private static final int MSG_HIDE_BOOT_MESSAGE = 11;
743    private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12;
744    private static final int MSG_POWER_DELAYED_PRESS = 13;
745    private static final int MSG_POWER_LONG_PRESS = 14;
746    private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 15;
747    private static final int MSG_REQUEST_TRANSIENT_BARS = 16;
748    private static final int MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU = 17;
749    private static final int MSG_BACK_LONG_PRESS = 18;
750    private static final int MSG_DISPOSE_INPUT_CONSUMER = 19;
751    private static final int MSG_BACK_DELAYED_PRESS = 20;
752
753    private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
754    private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
755
756    private class PolicyHandler extends Handler {
757        @Override
758        public void handleMessage(Message msg) {
759            switch (msg.what) {
760                case MSG_ENABLE_POINTER_LOCATION:
761                    enablePointerLocation();
762                    break;
763                case MSG_DISABLE_POINTER_LOCATION:
764                    disablePointerLocation();
765                    break;
766                case MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK:
767                    dispatchMediaKeyWithWakeLock((KeyEvent)msg.obj);
768                    break;
769                case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK:
770                    dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj);
771                    break;
772                case MSG_DISPATCH_SHOW_RECENTS:
773                    showRecentApps(false, msg.arg1 != 0);
774                    break;
775                case MSG_DISPATCH_SHOW_GLOBAL_ACTIONS:
776                    showGlobalActionsInternal();
777                    break;
778                case MSG_KEYGUARD_DRAWN_COMPLETE:
779                    if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete");
780                    finishKeyguardDrawn();
781                    break;
782                case MSG_KEYGUARD_DRAWN_TIMEOUT:
783                    Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete");
784                    finishKeyguardDrawn();
785                    break;
786                case MSG_WINDOW_MANAGER_DRAWN_COMPLETE:
787                    if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete");
788                    finishWindowsDrawn();
789                    break;
790                case MSG_HIDE_BOOT_MESSAGE:
791                    handleHideBootMessage();
792                    break;
793                case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK:
794                    launchVoiceAssistWithWakeLock(msg.arg1 != 0);
795                    break;
796                case MSG_POWER_DELAYED_PRESS:
797                    powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2);
798                    finishPowerKeyPress();
799                    break;
800                case MSG_POWER_LONG_PRESS:
801                    powerLongPress();
802                    break;
803                case MSG_UPDATE_DREAMING_SLEEP_TOKEN:
804                    updateDreamingSleepToken(msg.arg1 != 0);
805                    break;
806                case MSG_REQUEST_TRANSIENT_BARS:
807                    WindowState targetBar = (msg.arg1 == MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS) ?
808                            mStatusBar : mNavigationBar;
809                    if (targetBar != null) {
810                        requestTransientBars(targetBar);
811                    }
812                    break;
813                case MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU:
814                    showTvPictureInPictureMenuInternal();
815                    break;
816                case MSG_BACK_LONG_PRESS:
817                    backLongPress();
818                    finishBackKeyPress();
819                    break;
820                case MSG_DISPOSE_INPUT_CONSUMER:
821                    disposeInputConsumer((InputConsumer) msg.obj);
822                    break;
823                case MSG_BACK_DELAYED_PRESS:
824                    backMultiPressAction((Long) msg.obj, msg.arg1);
825                    finishBackKeyPress();
826                    break;
827            }
828        }
829    }
830
831    private UEventObserver mHDMIObserver = new UEventObserver() {
832        @Override
833        public void onUEvent(UEventObserver.UEvent event) {
834            setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
835        }
836    };
837
838    class SettingsObserver extends ContentObserver {
839        SettingsObserver(Handler handler) {
840            super(handler);
841        }
842
843        void observe() {
844            // Observe all users' changes
845            ContentResolver resolver = mContext.getContentResolver();
846            resolver.registerContentObserver(Settings.System.getUriFor(
847                    Settings.System.END_BUTTON_BEHAVIOR), false, this,
848                    UserHandle.USER_ALL);
849            resolver.registerContentObserver(Settings.Secure.getUriFor(
850                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this,
851                    UserHandle.USER_ALL);
852            resolver.registerContentObserver(Settings.Secure.getUriFor(
853                    Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR), false, this,
854                    UserHandle.USER_ALL);
855            resolver.registerContentObserver(Settings.Secure.getUriFor(
856                    Settings.Secure.WAKE_GESTURE_ENABLED), false, this,
857                    UserHandle.USER_ALL);
858            resolver.registerContentObserver(Settings.System.getUriFor(
859                    Settings.System.ACCELEROMETER_ROTATION), false, this,
860                    UserHandle.USER_ALL);
861            resolver.registerContentObserver(Settings.System.getUriFor(
862                    Settings.System.USER_ROTATION), false, this,
863                    UserHandle.USER_ALL);
864            resolver.registerContentObserver(Settings.System.getUriFor(
865                    Settings.System.SCREEN_OFF_TIMEOUT), false, this,
866                    UserHandle.USER_ALL);
867            resolver.registerContentObserver(Settings.System.getUriFor(
868                    Settings.System.POINTER_LOCATION), false, this,
869                    UserHandle.USER_ALL);
870            resolver.registerContentObserver(Settings.Secure.getUriFor(
871                    Settings.Secure.DEFAULT_INPUT_METHOD), false, this,
872                    UserHandle.USER_ALL);
873            resolver.registerContentObserver(Settings.Secure.getUriFor(
874                    Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this,
875                    UserHandle.USER_ALL);
876            resolver.registerContentObserver(Settings.Global.getUriFor(
877                    Settings.Global.POLICY_CONTROL), false, this,
878                    UserHandle.USER_ALL);
879            updateSettings();
880        }
881
882        @Override public void onChange(boolean selfChange) {
883            updateSettings();
884            updateRotation(false);
885        }
886    }
887
888    class MyWakeGestureListener extends WakeGestureListener {
889        MyWakeGestureListener(Context context, Handler handler) {
890            super(context, handler);
891        }
892
893        @Override
894        public void onWakeUp() {
895            synchronized (mLock) {
896                if (shouldEnableWakeGestureLp()) {
897                    performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
898                    wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture,
899                            "android.policy:GESTURE");
900                }
901            }
902        }
903    }
904
905    class MyOrientationListener extends WindowOrientationListener {
906        private final Runnable mUpdateRotationRunnable = new Runnable() {
907            @Override
908            public void run() {
909                // send interaction hint to improve redraw performance
910                mPowerManagerInternal.powerHint(PowerManagerInternal.POWER_HINT_INTERACTION, 0);
911                updateRotation(false);
912            }
913        };
914
915        MyOrientationListener(Context context, Handler handler) {
916            super(context, handler);
917        }
918
919        @Override
920        public void onProposedRotationChanged(int rotation) {
921            if (localLOGV) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
922            mHandler.post(mUpdateRotationRunnable);
923        }
924    }
925    MyOrientationListener mOrientationListener;
926
927    private final StatusBarController mStatusBarController = new StatusBarController();
928
929    private final BarController mNavigationBarController = new BarController("NavigationBar",
930            View.NAVIGATION_BAR_TRANSIENT,
931            View.NAVIGATION_BAR_UNHIDE,
932            View.NAVIGATION_BAR_TRANSLUCENT,
933            StatusBarManager.WINDOW_NAVIGATION_BAR,
934            WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
935            View.NAVIGATION_BAR_TRANSPARENT);
936
937    private ImmersiveModeConfirmation mImmersiveModeConfirmation;
938
939    private SystemGesturesPointerEventListener mSystemGestures;
940
941    IStatusBarService getStatusBarService() {
942        synchronized (mServiceAquireLock) {
943            if (mStatusBarService == null) {
944                mStatusBarService = IStatusBarService.Stub.asInterface(
945                        ServiceManager.getService("statusbar"));
946            }
947            return mStatusBarService;
948        }
949    }
950
951    StatusBarManagerInternal getStatusBarManagerInternal() {
952        synchronized (mServiceAquireLock) {
953            if (mStatusBarManagerInternal == null) {
954                mStatusBarManagerInternal =
955                        LocalServices.getService(StatusBarManagerInternal.class);
956            }
957            return mStatusBarManagerInternal;
958        }
959    }
960
961    /*
962     * We always let the sensor be switched on by default except when
963     * the user has explicitly disabled sensor based rotation or when the
964     * screen is switched off.
965     */
966    boolean needSensorRunningLp() {
967        if (mSupportAutoRotation) {
968            if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
969                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
970                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
971                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
972                // If the application has explicitly requested to follow the
973                // orientation, then we need to turn the sensor on.
974                return true;
975            }
976        }
977        if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
978                (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
979                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
980                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
981            // enable accelerometer if we are docked in a dock that enables accelerometer
982            // orientation management,
983            return true;
984        }
985        if (mUserRotationMode == USER_ROTATION_LOCKED) {
986            // If the setting for using the sensor by default is enabled, then
987            // we will always leave it on.  Note that the user could go to
988            // a window that forces an orientation that does not use the
989            // sensor and in theory we could turn it off... however, when next
990            // turning it on we won't have a good value for the current
991            // orientation for a little bit, which can cause orientation
992            // changes to lag, so we'd like to keep it always on.  (It will
993            // still be turned off when the screen is off.)
994            return false;
995        }
996        return mSupportAutoRotation;
997    }
998
999    /*
1000     * Various use cases for invoking this function
1001     * screen turning off, should always disable listeners if already enabled
1002     * screen turned on and current app has sensor based orientation, enable listeners
1003     * if not already enabled
1004     * screen turned on and current app does not have sensor orientation, disable listeners if
1005     * already enabled
1006     * screen turning on and current app has sensor based orientation, enable listeners if needed
1007     * screen turning on and current app has nosensor based orientation, do nothing
1008     */
1009    void updateOrientationListenerLp() {
1010        if (!mOrientationListener.canDetectOrientation()) {
1011            // If sensor is turned off or nonexistent for some reason
1012            return;
1013        }
1014        // Could have been invoked due to screen turning on or off or
1015        // change of the currently visible window's orientation.
1016        if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly
1017                + ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation
1018                + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled
1019                + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
1020                + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
1021        boolean disable = true;
1022        // Note: We postpone the rotating of the screen until the keyguard as well as the
1023        // window manager have reported a draw complete.
1024        if (mScreenOnEarly && mAwake &&
1025                mKeyguardDrawComplete && mWindowManagerDrawComplete) {
1026            if (needSensorRunningLp()) {
1027                disable = false;
1028                //enable listener if not already enabled
1029                if (!mOrientationSensorEnabled) {
1030                    mOrientationListener.enable();
1031                    if(localLOGV) Slog.v(TAG, "Enabling listeners");
1032                    mOrientationSensorEnabled = true;
1033                }
1034            }
1035        }
1036        //check if sensors need to be disabled
1037        if (disable && mOrientationSensorEnabled) {
1038            mOrientationListener.disable();
1039            if(localLOGV) Slog.v(TAG, "Disabling listeners");
1040            mOrientationSensorEnabled = false;
1041        }
1042    }
1043
1044    private void interceptBackKeyDown() {
1045        MetricsLogger.count(mContext, "key_back_down", 1);
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                }
3278            }
3279        } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
3280            if (down) {
3281                if (repeatCount == 0) {
3282                    mSearchKeyShortcutPending = true;
3283                    mConsumeSearchKeyUp = false;
3284                }
3285            } else {
3286                mSearchKeyShortcutPending = false;
3287                if (mConsumeSearchKeyUp) {
3288                    mConsumeSearchKeyUp = false;
3289                    return -1;
3290                }
3291            }
3292            return 0;
3293        } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
3294            if (!keyguardOn) {
3295                if (down && repeatCount == 0) {
3296                    preloadRecentApps();
3297                } else if (!down) {
3298                    toggleRecentApps();
3299                }
3300            }
3301            return -1;
3302        } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) {
3303            if (down) {
3304                IStatusBarService service = getStatusBarService();
3305                if (service != null) {
3306                    try {
3307                        service.expandNotificationsPanel();
3308                    } catch (RemoteException e) {
3309                        // do nothing.
3310                    }
3311                }
3312            }
3313        } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed()
3314                && event.isCtrlPressed()) {
3315            if (down && repeatCount == 0) {
3316                int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION
3317                        : TAKE_SCREENSHOT_FULLSCREEN;
3318                mScreenshotRunnable.setScreenshotType(type);
3319                mHandler.post(mScreenshotRunnable);
3320                return -1;
3321            }
3322        } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
3323            if (down && repeatCount == 0 && !isKeyguardLocked()) {
3324                toggleKeyboardShortcutsMenu(event.getDeviceId());
3325            }
3326        } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
3327            if (down) {
3328                if (repeatCount == 0) {
3329                    mAssistKeyLongPressed = false;
3330                } else if (repeatCount == 1) {
3331                    mAssistKeyLongPressed = true;
3332                    if (!keyguardOn) {
3333                         launchAssistLongPressAction();
3334                    }
3335                }
3336            } else {
3337                if (mAssistKeyLongPressed) {
3338                    mAssistKeyLongPressed = false;
3339                } else {
3340                    if (!keyguardOn) {
3341                        launchAssistAction(null, event.getDeviceId());
3342                    }
3343                }
3344            }
3345            return -1;
3346        } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
3347            if (!down) {
3348                Intent voiceIntent;
3349                if (!keyguardOn) {
3350                    voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
3351                } else {
3352                    IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
3353                            ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
3354                    if (dic != null) {
3355                        try {
3356                            dic.exitIdle("voice-search");
3357                        } catch (RemoteException e) {
3358                        }
3359                    }
3360                    voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
3361                    voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
3362                }
3363                startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
3364            }
3365        } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
3366            if (down && repeatCount == 0) {
3367                mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
3368                mHandler.post(mScreenshotRunnable);
3369            }
3370            return -1;
3371        } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP
3372                || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) {
3373            if (down) {
3374                int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
3375
3376                // Disable autobrightness if it's on
3377                int auto = Settings.System.getIntForUser(
3378                        mContext.getContentResolver(),
3379                        Settings.System.SCREEN_BRIGHTNESS_MODE,
3380                        Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3381                        UserHandle.USER_CURRENT_OR_SELF);
3382                if (auto != 0) {
3383                    Settings.System.putIntForUser(mContext.getContentResolver(),
3384                            Settings.System.SCREEN_BRIGHTNESS_MODE,
3385                            Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3386                            UserHandle.USER_CURRENT_OR_SELF);
3387                }
3388
3389                int min = mPowerManager.getMinimumScreenBrightnessSetting();
3390                int max = mPowerManager.getMaximumScreenBrightnessSetting();
3391                int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction;
3392                int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
3393                        Settings.System.SCREEN_BRIGHTNESS,
3394                        mPowerManager.getDefaultScreenBrightnessSetting(),
3395                        UserHandle.USER_CURRENT_OR_SELF);
3396                brightness += step;
3397                // Make sure we don't go beyond the limits.
3398                brightness = Math.min(max, brightness);
3399                brightness = Math.max(min, brightness);
3400
3401                Settings.System.putIntForUser(mContext.getContentResolver(),
3402                        Settings.System.SCREEN_BRIGHTNESS, brightness,
3403                        UserHandle.USER_CURRENT_OR_SELF);
3404                startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
3405                        UserHandle.CURRENT_OR_SELF);
3406            }
3407            return -1;
3408        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
3409                || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3410                || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
3411            if (mUseTvRouting) {
3412                // On TVs volume keys never go to the foreground app.
3413                dispatchDirectAudioEvent(event);
3414                return -1;
3415            }
3416        }
3417
3418        // Toggle Caps Lock on META-ALT.
3419        boolean actionTriggered = false;
3420        if (KeyEvent.isModifierKey(keyCode)) {
3421            if (!mPendingCapsLockToggle) {
3422                // Start tracking meta state for combo.
3423                mInitialMetaState = mMetaState;
3424                mPendingCapsLockToggle = true;
3425            } else if (event.getAction() == KeyEvent.ACTION_UP) {
3426                int altOnMask = mMetaState & KeyEvent.META_ALT_MASK;
3427                int metaOnMask = mMetaState & KeyEvent.META_META_MASK;
3428
3429                // Check for Caps Lock toggle
3430                if ((metaOnMask != 0) && (altOnMask != 0)) {
3431                    // Check if nothing else is pressed
3432                    if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) {
3433                        // Handle Caps Lock Toggle
3434                        mInputManagerInternal.toggleCapsLock(event.getDeviceId());
3435                        actionTriggered = true;
3436                    }
3437                }
3438
3439                // Always stop tracking when key goes up.
3440                mPendingCapsLockToggle = false;
3441            }
3442        }
3443        // Store current meta state to be able to evaluate it later.
3444        mMetaState = metaState;
3445
3446        if (actionTriggered) {
3447            return -1;
3448        }
3449
3450        if (KeyEvent.isMetaKey(keyCode)) {
3451            if (down) {
3452                mPendingMetaAction = true;
3453            } else if (mPendingMetaAction) {
3454                launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId());
3455            }
3456            return -1;
3457        }
3458
3459        // Shortcuts are invoked through Search+key, so intercept those here
3460        // Any printing key that is chorded with Search should be consumed
3461        // even if no shortcut was invoked.  This prevents text from being
3462        // inadvertently inserted when using a keyboard that has built-in macro
3463        // shortcut keys (that emit Search+x) and some of them are not registered.
3464        if (mSearchKeyShortcutPending) {
3465            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3466            if (kcm.isPrintingKey(keyCode)) {
3467                mConsumeSearchKeyUp = true;
3468                mSearchKeyShortcutPending = false;
3469                if (down && repeatCount == 0 && !keyguardOn) {
3470                    Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
3471                    if (shortcutIntent != null) {
3472                        shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3473                        try {
3474                            startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3475                            dismissKeyboardShortcutsMenu();
3476                        } catch (ActivityNotFoundException ex) {
3477                            Slog.w(TAG, "Dropping shortcut key combination because "
3478                                    + "the activity to which it is registered was not found: "
3479                                    + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);
3480                        }
3481                    } else {
3482                        Slog.i(TAG, "Dropping unregistered shortcut key combination: "
3483                                + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));
3484                    }
3485                }
3486                return -1;
3487            }
3488        }
3489
3490        // Invoke shortcuts using Meta.
3491        if (down && repeatCount == 0 && !keyguardOn
3492                && (metaState & KeyEvent.META_META_ON) != 0) {
3493            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3494            if (kcm.isPrintingKey(keyCode)) {
3495                Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
3496                        metaState & ~(KeyEvent.META_META_ON
3497                                | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
3498                if (shortcutIntent != null) {
3499                    shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3500                    try {
3501                        startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3502                        dismissKeyboardShortcutsMenu();
3503                    } catch (ActivityNotFoundException ex) {
3504                        Slog.w(TAG, "Dropping shortcut key combination because "
3505                                + "the activity to which it is registered was not found: "
3506                                + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
3507                    }
3508                    return -1;
3509                }
3510            }
3511        }
3512
3513        // Handle application launch keys.
3514        if (down && repeatCount == 0 && !keyguardOn) {
3515            String category = sApplicationLaunchKeyCategories.get(keyCode);
3516            if (category != null) {
3517                Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
3518                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3519                try {
3520                    startActivityAsUser(intent, UserHandle.CURRENT);
3521                    dismissKeyboardShortcutsMenu();
3522                } catch (ActivityNotFoundException ex) {
3523                    Slog.w(TAG, "Dropping application launch key because "
3524                            + "the activity to which it is registered was not found: "
3525                            + "keyCode=" + keyCode + ", category=" + category, ex);
3526                }
3527                return -1;
3528            }
3529        }
3530
3531        // Display task switcher for ALT-TAB.
3532        if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
3533            if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
3534                final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
3535                if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
3536                    mRecentAppsHeldModifiers = shiftlessModifiers;
3537                    showRecentApps(true, false);
3538                    return -1;
3539                }
3540            }
3541        } else if (!down && mRecentAppsHeldModifiers != 0
3542                && (metaState & mRecentAppsHeldModifiers) == 0) {
3543            mRecentAppsHeldModifiers = 0;
3544            hideRecentApps(true, false);
3545        }
3546
3547        // Handle input method switching.
3548        if (down && repeatCount == 0
3549                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3550                        || (keyCode == KeyEvent.KEYCODE_SPACE
3551                                && (metaState & KeyEvent.META_META_MASK) != 0))) {
3552            final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0;
3553            mWindowManagerFuncs.switchInputMethod(forwardDirection);
3554            return -1;
3555        }
3556        if (mLanguageSwitchKeyPressed && !down
3557                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3558                        || keyCode == KeyEvent.KEYCODE_SPACE)) {
3559            mLanguageSwitchKeyPressed = false;
3560            return -1;
3561        }
3562
3563        if (isValidGlobalKey(keyCode)
3564                && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
3565            return -1;
3566        }
3567
3568        if (down) {
3569            long shortcutCode = keyCode;
3570            if (event.isCtrlPressed()) {
3571                shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
3572            }
3573
3574            if (event.isAltPressed()) {
3575                shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
3576            }
3577
3578            if (event.isShiftPressed()) {
3579                shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
3580            }
3581
3582            if (event.isMetaPressed()) {
3583                shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE;
3584            }
3585
3586            IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode);
3587            if (shortcutService != null) {
3588                try {
3589                    if (isUserSetupComplete()) {
3590                        shortcutService.notifyShortcutKeyPressed(shortcutCode);
3591                    }
3592                } catch (RemoteException e) {
3593                    mShortcutKeyServices.delete(shortcutCode);
3594                }
3595                return -1;
3596            }
3597        }
3598
3599        // Reserve all the META modifier combos for system behavior
3600        if ((metaState & KeyEvent.META_META_ON) != 0) {
3601            return -1;
3602        }
3603
3604        // Let the application handle the key.
3605        return 0;
3606    }
3607
3608    /** {@inheritDoc} */
3609    @Override
3610    public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
3611        // Note: This method is only called if the initial down was unhandled.
3612        if (DEBUG_INPUT) {
3613            Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
3614                    + ", flags=" + event.getFlags()
3615                    + ", keyCode=" + event.getKeyCode()
3616                    + ", scanCode=" + event.getScanCode()
3617                    + ", metaState=" + event.getMetaState()
3618                    + ", repeatCount=" + event.getRepeatCount()
3619                    + ", policyFlags=" + policyFlags);
3620        }
3621
3622        KeyEvent fallbackEvent = null;
3623        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3624            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3625            final int keyCode = event.getKeyCode();
3626            final int metaState = event.getMetaState();
3627            final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
3628                    && event.getRepeatCount() == 0;
3629
3630            // Check for fallback actions specified by the key character map.
3631            final FallbackAction fallbackAction;
3632            if (initialDown) {
3633                fallbackAction = kcm.getFallbackAction(keyCode, metaState);
3634            } else {
3635                fallbackAction = mFallbackActions.get(keyCode);
3636            }
3637
3638            if (fallbackAction != null) {
3639                if (DEBUG_INPUT) {
3640                    Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode
3641                            + " metaState=" + Integer.toHexString(fallbackAction.metaState));
3642                }
3643
3644                final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
3645                fallbackEvent = KeyEvent.obtain(
3646                        event.getDownTime(), event.getEventTime(),
3647                        event.getAction(), fallbackAction.keyCode,
3648                        event.getRepeatCount(), fallbackAction.metaState,
3649                        event.getDeviceId(), event.getScanCode(),
3650                        flags, event.getSource(), null);
3651
3652                if (!interceptFallback(win, fallbackEvent, policyFlags)) {
3653                    fallbackEvent.recycle();
3654                    fallbackEvent = null;
3655                }
3656
3657                if (initialDown) {
3658                    mFallbackActions.put(keyCode, fallbackAction);
3659                } else if (event.getAction() == KeyEvent.ACTION_UP) {
3660                    mFallbackActions.remove(keyCode);
3661                    fallbackAction.recycle();
3662                }
3663            }
3664        }
3665
3666        if (DEBUG_INPUT) {
3667            if (fallbackEvent == null) {
3668                Slog.d(TAG, "No fallback.");
3669            } else {
3670                Slog.d(TAG, "Performing fallback: " + fallbackEvent);
3671            }
3672        }
3673        return fallbackEvent;
3674    }
3675
3676    private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
3677        int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
3678        if ((actions & ACTION_PASS_TO_USER) != 0) {
3679            long delayMillis = interceptKeyBeforeDispatching(
3680                    win, fallbackEvent, policyFlags);
3681            if (delayMillis == 0) {
3682                return true;
3683            }
3684        }
3685        return false;
3686    }
3687
3688    @Override
3689    public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
3690            throws RemoteException {
3691        synchronized (mLock) {
3692            IShortcutService service = mShortcutKeyServices.get(shortcutCode);
3693            if (service != null && service.asBinder().pingBinder()) {
3694                throw new RemoteException("Key already exists.");
3695            }
3696
3697            mShortcutKeyServices.put(shortcutCode, shortcutService);
3698        }
3699    }
3700
3701    @Override
3702    public boolean canShowDismissingWindowWhileLockedLw() {
3703        // If the keyguard is trusted, it will unlock without a challenge. Therefore, if we are in
3704        // the process of dismissing Keyguard, we don't need to hide them as the phone will be
3705        // unlocked right away in any case.
3706        return mKeyguardDelegate != null && mKeyguardDelegate.isTrusted()
3707                && mCurrentlyDismissingKeyguard;
3708    }
3709
3710    private void launchAssistLongPressAction() {
3711        performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
3712        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
3713
3714        // launch the search activity
3715        Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
3716        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3717        try {
3718            // TODO: This only stops the factory-installed search manager.
3719            // Need to formalize an API to handle others
3720            SearchManager searchManager = getSearchManager();
3721            if (searchManager != null) {
3722                searchManager.stopSearch();
3723            }
3724            startActivityAsUser(intent, UserHandle.CURRENT);
3725        } catch (ActivityNotFoundException e) {
3726            Slog.w(TAG, "No activity to handle assist long press action.", e);
3727        }
3728    }
3729
3730    private void launchAssistAction(String hint, int deviceId) {
3731        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
3732        if (!isUserSetupComplete()) {
3733            // Disable opening assist window during setup
3734            return;
3735        }
3736        Bundle args = null;
3737        if (deviceId > Integer.MIN_VALUE) {
3738            args = new Bundle();
3739            args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
3740        }
3741        if ((mContext.getResources().getConfiguration().uiMode
3742                & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
3743            // On TV, use legacy handling until assistants are implemented in the proper way.
3744            ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
3745                    .launchLegacyAssist(hint, UserHandle.myUserId(), args);
3746        } else {
3747            if (hint != null) {
3748                if (args == null) {
3749                    args = new Bundle();
3750                }
3751                args.putBoolean(hint, true);
3752            }
3753            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3754            if (statusbar != null) {
3755                statusbar.startAssist(args);
3756            }
3757        }
3758    }
3759
3760    private void startActivityAsUser(Intent intent, UserHandle handle) {
3761        if (isUserSetupComplete()) {
3762            mContext.startActivityAsUser(intent, handle);
3763        } else {
3764            Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent);
3765        }
3766    }
3767
3768    private SearchManager getSearchManager() {
3769        if (mSearchManager == null) {
3770            mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
3771        }
3772        return mSearchManager;
3773    }
3774
3775    private void preloadRecentApps() {
3776        mPreloadedRecentApps = true;
3777        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3778        if (statusbar != null) {
3779            statusbar.preloadRecentApps();
3780        }
3781    }
3782
3783    private void cancelPreloadRecentApps() {
3784        if (mPreloadedRecentApps) {
3785            mPreloadedRecentApps = false;
3786            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3787            if (statusbar != null) {
3788                statusbar.cancelPreloadRecentApps();
3789            }
3790        }
3791    }
3792
3793    private void toggleRecentApps() {
3794        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3795        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3796        if (statusbar != null) {
3797            statusbar.toggleRecentApps();
3798        }
3799    }
3800
3801    @Override
3802    public void showRecentApps(boolean fromHome) {
3803        mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
3804        mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget();
3805    }
3806
3807    private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
3808        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3809        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3810        if (statusbar != null) {
3811            statusbar.showRecentApps(triggeredFromAltTab, fromHome);
3812        }
3813    }
3814
3815    private void toggleKeyboardShortcutsMenu(int deviceId) {
3816        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3817        if (statusbar != null) {
3818            statusbar.toggleKeyboardShortcutsMenu(deviceId);
3819        }
3820    }
3821
3822    private void dismissKeyboardShortcutsMenu() {
3823        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3824        if (statusbar != null) {
3825            statusbar.dismissKeyboardShortcutsMenu();
3826        }
3827    }
3828
3829    private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
3830        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3831        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3832        if (statusbar != null) {
3833            statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
3834        }
3835    }
3836
3837    void launchHomeFromHotKey() {
3838        launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/);
3839    }
3840
3841    /**
3842     * A home key -> launch home action was detected.  Take the appropriate action
3843     * given the situation with the keyguard.
3844     */
3845    void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) {
3846        if (respectKeyguard) {
3847            if (isKeyguardShowingAndNotOccluded()) {
3848                // don't launch home if keyguard showing
3849                return;
3850            }
3851
3852            if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) {
3853                // when in keyguard restricted mode, must first verify unlock
3854                // before launching home
3855                mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
3856                    @Override
3857                    public void onKeyguardExitResult(boolean success) {
3858                        if (success) {
3859                            try {
3860                                ActivityManagerNative.getDefault().stopAppSwitches();
3861                            } catch (RemoteException e) {
3862                            }
3863                            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
3864                            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
3865                        }
3866                    }
3867                });
3868                return;
3869            }
3870        }
3871
3872        // no keyguard stuff to worry about, just launch home!
3873        try {
3874            ActivityManagerNative.getDefault().stopAppSwitches();
3875        } catch (RemoteException e) {
3876        }
3877        if (mRecentsVisible) {
3878            // Hide Recents and notify it to launch Home
3879            if (awakenFromDreams) {
3880                awakenDreams();
3881            }
3882            hideRecentApps(false, true);
3883        } else {
3884            // Otherwise, just launch Home
3885            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
3886            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
3887        }
3888    }
3889
3890    private final Runnable mClearHideNavigationFlag = new Runnable() {
3891        @Override
3892        public void run() {
3893            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
3894                // Clear flags.
3895                mForceClearedSystemUiFlags &=
3896                        ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
3897            }
3898            mWindowManagerFuncs.reevaluateStatusBarVisibility();
3899        }
3900    };
3901
3902    /**
3903     * Input handler used while nav bar is hidden.  Captures any touch on the screen,
3904     * to determine when the nav bar should be shown and prevent applications from
3905     * receiving those touches.
3906     */
3907    final class HideNavInputEventReceiver extends InputEventReceiver {
3908        public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
3909            super(inputChannel, looper);
3910        }
3911
3912        @Override
3913        public void onInputEvent(InputEvent event) {
3914            boolean handled = false;
3915            try {
3916                if (event instanceof MotionEvent
3917                        && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
3918                    final MotionEvent motionEvent = (MotionEvent)event;
3919                    if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
3920                        // When the user taps down, we re-show the nav bar.
3921                        boolean changed = false;
3922                        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
3923                            if (mInputConsumer == null) {
3924                                return;
3925                            }
3926                            // Any user activity always causes us to show the
3927                            // navigation controls, if they had been hidden.
3928                            // We also clear the low profile and only content
3929                            // flags so that tapping on the screen will atomically
3930                            // restore all currently hidden screen decorations.
3931                            int newVal = mResettingSystemUiFlags |
3932                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
3933                                    View.SYSTEM_UI_FLAG_LOW_PROFILE |
3934                                    View.SYSTEM_UI_FLAG_FULLSCREEN;
3935                            if (mResettingSystemUiFlags != newVal) {
3936                                mResettingSystemUiFlags = newVal;
3937                                changed = true;
3938                            }
3939                            // We don't allow the system's nav bar to be hidden
3940                            // again for 1 second, to prevent applications from
3941                            // spamming us and keeping it from being shown.
3942                            newVal = mForceClearedSystemUiFlags |
3943                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
3944                            if (mForceClearedSystemUiFlags != newVal) {
3945                                mForceClearedSystemUiFlags = newVal;
3946                                changed = true;
3947                                mHandler.postDelayed(mClearHideNavigationFlag, 1000);
3948                            }
3949                        }
3950                        if (changed) {
3951                            mWindowManagerFuncs.reevaluateStatusBarVisibility();
3952                        }
3953                    }
3954                }
3955            } finally {
3956                finishInputEvent(event, handled);
3957            }
3958        }
3959    }
3960    final InputEventReceiver.Factory mHideNavInputEventReceiverFactory =
3961            new InputEventReceiver.Factory() {
3962        @Override
3963        public InputEventReceiver createInputEventReceiver(
3964                InputChannel inputChannel, Looper looper) {
3965            return new HideNavInputEventReceiver(inputChannel, looper);
3966        }
3967    };
3968
3969    @Override
3970    public void setRecentsVisibilityLw(boolean visible) {
3971        mRecentsVisible = visible;
3972    }
3973
3974    @Override
3975    public void setTvPipVisibilityLw(boolean visible) {
3976        mTvPictureInPictureVisible = visible;
3977    }
3978
3979    @Override
3980    public int adjustSystemUiVisibilityLw(int visibility) {
3981        mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
3982        mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
3983
3984        // Reset any bits in mForceClearingStatusBarVisibility that
3985        // are now clear.
3986        mResettingSystemUiFlags &= visibility;
3987        // Clear any bits in the new visibility that are currently being
3988        // force cleared, before reporting it.
3989        return visibility & ~mResettingSystemUiFlags
3990                & ~mForceClearedSystemUiFlags;
3991    }
3992
3993    @Override
3994    public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
3995            int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets,
3996            Rect outStableInsets, Rect outOutsets) {
3997        final int fl = PolicyControl.getWindowFlags(null, attrs);
3998        final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
3999        final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
4000
4001        final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
4002        if (useOutsets) {
4003            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
4004            if (outset > 0) {
4005                if (displayRotation == Surface.ROTATION_0) {
4006                    outOutsets.bottom += outset;
4007                } else if (displayRotation == Surface.ROTATION_90) {
4008                    outOutsets.right += outset;
4009                } else if (displayRotation == Surface.ROTATION_180) {
4010                    outOutsets.top += outset;
4011                } else if (displayRotation == Surface.ROTATION_270) {
4012                    outOutsets.left += outset;
4013                }
4014            }
4015        }
4016
4017        if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4018                == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4019            int availRight, availBottom;
4020            if (canHideNavigationBar() &&
4021                    (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
4022                availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4023                availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4024            } else {
4025                availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
4026                availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4027            }
4028            if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4029                if ((fl & FLAG_FULLSCREEN) != 0) {
4030                    outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop,
4031                            availRight - mStableFullscreenRight,
4032                            availBottom - mStableFullscreenBottom);
4033                } else {
4034                    outContentInsets.set(mStableLeft, mStableTop,
4035                            availRight - mStableRight, availBottom - mStableBottom);
4036                }
4037            } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
4038                outContentInsets.setEmpty();
4039            } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
4040                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
4041                outContentInsets.set(mCurLeft, mCurTop,
4042                        availRight - mCurRight, availBottom - mCurBottom);
4043            } else {
4044                outContentInsets.set(mCurLeft, mCurTop,
4045                        availRight - mCurRight, availBottom - mCurBottom);
4046            }
4047
4048            outStableInsets.set(mStableLeft, mStableTop,
4049                    availRight - mStableRight, availBottom - mStableBottom);
4050            if (taskBounds != null) {
4051                calculateRelevantTaskInsets(taskBounds, outContentInsets,
4052                        displayWidth, displayHeight);
4053                calculateRelevantTaskInsets(taskBounds, outStableInsets,
4054                        displayWidth, displayHeight);
4055            }
4056            return mForceShowSystemBars;
4057        }
4058        outContentInsets.setEmpty();
4059        outStableInsets.setEmpty();
4060        return mForceShowSystemBars;
4061    }
4062
4063    /**
4064     * For any given task bounds, the insets relevant for these bounds given the insets relevant
4065     * for the entire display.
4066     */
4067    private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth,
4068            int displayHeight) {
4069        mTmpRect.set(0, 0, displayWidth, displayHeight);
4070        mTmpRect.inset(inOutInsets);
4071        mTmpRect.intersect(taskBounds);
4072        int leftInset = mTmpRect.left - taskBounds.left;
4073        int topInset = mTmpRect.top - taskBounds.top;
4074        int rightInset = taskBounds.right - mTmpRect.right;
4075        int bottomInset = taskBounds.bottom - mTmpRect.bottom;
4076        inOutInsets.set(leftInset, topInset, rightInset, bottomInset);
4077    }
4078
4079    private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
4080        return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
4081                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
4082    }
4083
4084    /** {@inheritDoc} */
4085    @Override
4086    public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
4087                              int displayRotation, int uiMode) {
4088        mDisplayRotation = displayRotation;
4089        final int overscanLeft, overscanTop, overscanRight, overscanBottom;
4090        if (isDefaultDisplay) {
4091            switch (displayRotation) {
4092                case Surface.ROTATION_90:
4093                    overscanLeft = mOverscanTop;
4094                    overscanTop = mOverscanRight;
4095                    overscanRight = mOverscanBottom;
4096                    overscanBottom = mOverscanLeft;
4097                    break;
4098                case Surface.ROTATION_180:
4099                    overscanLeft = mOverscanRight;
4100                    overscanTop = mOverscanBottom;
4101                    overscanRight = mOverscanLeft;
4102                    overscanBottom = mOverscanTop;
4103                    break;
4104                case Surface.ROTATION_270:
4105                    overscanLeft = mOverscanBottom;
4106                    overscanTop = mOverscanLeft;
4107                    overscanRight = mOverscanTop;
4108                    overscanBottom = mOverscanRight;
4109                    break;
4110                default:
4111                    overscanLeft = mOverscanLeft;
4112                    overscanTop = mOverscanTop;
4113                    overscanRight = mOverscanRight;
4114                    overscanBottom = mOverscanBottom;
4115                    break;
4116            }
4117        } else {
4118            overscanLeft = 0;
4119            overscanTop = 0;
4120            overscanRight = 0;
4121            overscanBottom = 0;
4122        }
4123        mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0;
4124        mOverscanScreenTop = mRestrictedOverscanScreenTop = 0;
4125        mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth;
4126        mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight;
4127        mSystemLeft = 0;
4128        mSystemTop = 0;
4129        mSystemRight = displayWidth;
4130        mSystemBottom = displayHeight;
4131        mUnrestrictedScreenLeft = overscanLeft;
4132        mUnrestrictedScreenTop = overscanTop;
4133        mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight;
4134        mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom;
4135        mRestrictedScreenLeft = mUnrestrictedScreenLeft;
4136        mRestrictedScreenTop = mUnrestrictedScreenTop;
4137        mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth;
4138        mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight;
4139        mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft
4140                = mCurLeft = mUnrestrictedScreenLeft;
4141        mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop
4142                = mCurTop = mUnrestrictedScreenTop;
4143        mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight
4144                = mCurRight = displayWidth - overscanRight;
4145        mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom
4146                = mCurBottom = displayHeight - overscanBottom;
4147        mDockLayer = 0x10000000;
4148        mStatusBarLayer = -1;
4149
4150        // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
4151        final Rect pf = mTmpParentFrame;
4152        final Rect df = mTmpDisplayFrame;
4153        final Rect of = mTmpOverscanFrame;
4154        final Rect vf = mTmpVisibleFrame;
4155        final Rect dcf = mTmpDecorFrame;
4156        pf.left = df.left = of.left = vf.left = mDockLeft;
4157        pf.top = df.top = of.top = vf.top = mDockTop;
4158        pf.right = df.right = of.right = vf.right = mDockRight;
4159        pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom;
4160        dcf.setEmpty();  // Decor frame N/A for system bars.
4161
4162        if (isDefaultDisplay) {
4163            // For purposes of putting out fake window up to steal focus, we will
4164            // drive nav being hidden only by whether it is requested.
4165            final int sysui = mLastSystemUiFlags;
4166            boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
4167            boolean navTranslucent = (sysui
4168                    & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
4169            boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
4170            boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
4171            boolean navAllowedHidden = immersive || immersiveSticky;
4172            navTranslucent &= !immersiveSticky;  // transient trumps translucent
4173            boolean isKeyguardShowing = isStatusBarKeyguard() && !mHideLockScreen;
4174            if (!isKeyguardShowing) {
4175                navTranslucent &= areTranslucentBarsAllowed();
4176            }
4177            boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null
4178                    && mStatusBar.getAttrs().height == MATCH_PARENT
4179                    && mStatusBar.getAttrs().width == MATCH_PARENT;
4180
4181            // When the navigation bar isn't visible, we put up a fake
4182            // input window to catch all touch events.  This way we can
4183            // detect when the user presses anywhere to bring back the nav
4184            // bar and ensure the application doesn't see the event.
4185            if (navVisible || navAllowedHidden) {
4186                if (mInputConsumer != null) {
4187                    mHandler.sendMessage(
4188                            mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
4189                    mInputConsumer = null;
4190                }
4191            } else if (mInputConsumer == null) {
4192                mInputConsumer = mWindowManagerFuncs.addInputConsumer(mHandler.getLooper(),
4193                        mHideNavInputEventReceiverFactory);
4194            }
4195
4196            // For purposes of positioning and showing the nav bar, if we have
4197            // decided that it can't be hidden (because of the screen aspect ratio),
4198            // then take that into account.
4199            navVisible |= !canHideNavigationBar();
4200
4201            boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight,
4202                    displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom, dcf, navVisible, navTranslucent,
4203                    navAllowedHidden, statusBarExpandedNotKeyguard);
4204            if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
4205                    mDockLeft, mDockTop, mDockRight, mDockBottom));
4206            updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing);
4207            if (updateSysUiVisibility) {
4208                updateSystemUiVisibilityLw();
4209            }
4210        }
4211    }
4212
4213    private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui,
4214            boolean isKeyguardShowing) {
4215        // decide where the status bar goes ahead of time
4216        if (mStatusBar != null) {
4217            // apply any navigation bar insets
4218            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4219            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4220            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4221            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
4222                    + mUnrestrictedScreenTop;
4223            vf.left = mStableLeft;
4224            vf.top = mStableTop;
4225            vf.right = mStableRight;
4226            vf.bottom = mStableBottom;
4227
4228            mStatusBarLayer = mStatusBar.getSurfaceLayer();
4229
4230            // Let the status bar determine its size.
4231            mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
4232                    vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
4233                    dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */);
4234
4235            // For layout, the status bar is always at the top with our fixed height.
4236            mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
4237
4238            boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
4239            boolean statusBarTranslucent = (sysui
4240                    & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
4241            if (!isKeyguardShowing) {
4242                statusBarTranslucent &= areTranslucentBarsAllowed();
4243            }
4244
4245            // If the status bar is hidden, we don't want to cause
4246            // windows behind it to scroll.
4247            if (mStatusBar.isVisibleLw() && !statusBarTransient) {
4248                // Status bar may go away, so the screen area it occupies
4249                // is available to apps but just covering them when the
4250                // status bar is visible.
4251                mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
4252
4253                mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4254                mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4255                mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4256                mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4257
4258                if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " +
4259                        String.format(
4260                                "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
4261                                mDockLeft, mDockTop, mDockRight, mDockBottom,
4262                                mContentLeft, mContentTop, mContentRight, mContentBottom,
4263                                mCurLeft, mCurTop, mCurRight, mCurBottom));
4264            }
4265            if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
4266                    && !statusBarTransient && !statusBarTranslucent
4267                    && !mStatusBarController.wasRecentlyTranslucent()) {
4268                // If the opaque status bar is currently requested to be visible,
4269                // and not in the process of animating on or off, then
4270                // we can tell the app that it is covered by it.
4271                mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
4272            }
4273            if (mStatusBarController.checkHiddenLw()) {
4274                return true;
4275            }
4276        }
4277        return false;
4278    }
4279
4280    private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation,
4281            int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf,
4282            boolean navVisible, boolean navTranslucent, boolean navAllowedHidden,
4283            boolean statusBarExpandedNotKeyguard) {
4284        if (mNavigationBar != null) {
4285            boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
4286            // Force the navigation bar to its appropriate place and
4287            // size.  We need to do this directly, instead of relying on
4288            // it to bubble up from the nav bar, because this needs to
4289            // change atomically with screen rotations.
4290            mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight,
4291                    displayRotation);
4292            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
4293                // It's a system nav bar or a portrait screen; nav bar goes on bottom.
4294                int top = displayHeight - overscanBottom
4295                        - getNavigationBarHeight(displayRotation, uiMode);
4296                mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
4297                mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
4298                if (transientNavBarShowing) {
4299                    mNavigationBarController.setBarShowingLw(true);
4300                } else if (navVisible) {
4301                    mNavigationBarController.setBarShowingLw(true);
4302                    mDockBottom = mTmpNavigationFrame.top;
4303                    mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
4304                    mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
4305                } else {
4306                    // We currently want to hide the navigation UI - unless we expanded the status
4307                    // bar.
4308                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4309                }
4310                if (navVisible && !navTranslucent && !navAllowedHidden
4311                        && !mNavigationBar.isAnimatingLw()
4312                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4313                    // If the opaque nav bar is currently requested to be visible,
4314                    // and not in the process of animating on or off, then
4315                    // we can tell the app that it is covered by it.
4316                    mSystemBottom = mTmpNavigationFrame.top;
4317                }
4318            } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4319                // Landscape screen; nav bar goes to the right.
4320                int left = displayWidth - overscanRight
4321                        - getNavigationBarWidth(displayRotation, uiMode);
4322                mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
4323                mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
4324                if (transientNavBarShowing) {
4325                    mNavigationBarController.setBarShowingLw(true);
4326                } else if (navVisible) {
4327                    mNavigationBarController.setBarShowingLw(true);
4328                    mDockRight = mTmpNavigationFrame.left;
4329                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4330                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4331                } else {
4332                    // We currently want to hide the navigation UI - unless we expanded the status
4333                    // bar.
4334                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4335                }
4336                if (navVisible && !navTranslucent && !navAllowedHidden
4337                        && !mNavigationBar.isAnimatingLw()
4338                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4339                    // If the nav bar is currently requested to be visible,
4340                    // and not in the process of animating on or off, then
4341                    // we can tell the app that it is covered by it.
4342                    mSystemRight = mTmpNavigationFrame.left;
4343                }
4344            } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4345                // Seascape screen; nav bar goes to the left.
4346                int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode);
4347                mTmpNavigationFrame.set(overscanLeft, 0, right, displayHeight);
4348                mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right;
4349                if (transientNavBarShowing) {
4350                    mNavigationBarController.setBarShowingLw(true);
4351                } else if (navVisible) {
4352                    mNavigationBarController.setBarShowingLw(true);
4353                    mDockLeft = mTmpNavigationFrame.right;
4354                    // TODO: not so sure about those:
4355                    mRestrictedScreenLeft = mRestrictedOverscanScreenLeft = mDockLeft;
4356                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4357                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4358                } else {
4359                    // We currently want to hide the navigation UI - unless we expanded the status
4360                    // bar.
4361                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4362                }
4363                if (navVisible && !navTranslucent && !navAllowedHidden
4364                        && !mNavigationBar.isAnimatingLw()
4365                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4366                    // If the nav bar is currently requested to be visible,
4367                    // and not in the process of animating on or off, then
4368                    // we can tell the app that it is covered by it.
4369                    mSystemLeft = mTmpNavigationFrame.right;
4370                }
4371            }
4372            // Make sure the content and current rectangles are updated to
4373            // account for the restrictions from the navigation bar.
4374            mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4375            mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4376            mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4377            mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4378            mStatusBarLayer = mNavigationBar.getSurfaceLayer();
4379            // And compute the final frame.
4380            mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
4381                    mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
4382                    mTmpNavigationFrame, mTmpNavigationFrame);
4383            if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
4384            if (mNavigationBarController.checkHiddenLw()) {
4385                return true;
4386            }
4387        }
4388        return false;
4389    }
4390
4391    private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
4392        if (mNavigationBarCanMove && displayWidth > displayHeight) {
4393            if (displayRotation == Surface.ROTATION_270) {
4394                return NAV_BAR_LEFT;
4395            } else {
4396                return NAV_BAR_RIGHT;
4397            }
4398        }
4399        return NAV_BAR_BOTTOM;
4400    }
4401
4402    /** {@inheritDoc} */
4403    @Override
4404    public int getSystemDecorLayerLw() {
4405        if (mStatusBar != null && mStatusBar.isVisibleLw()) {
4406            return mStatusBar.getSurfaceLayer();
4407        }
4408
4409        if (mNavigationBar != null && mNavigationBar.isVisibleLw()) {
4410            return mNavigationBar.getSurfaceLayer();
4411        }
4412
4413        return 0;
4414    }
4415
4416    @Override
4417    public void getContentRectLw(Rect r) {
4418        r.set(mContentLeft, mContentTop, mContentRight, mContentBottom);
4419    }
4420
4421    void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
4422            boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
4423        if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
4424            // Here's a special case: if this attached window is a panel that is
4425            // above the dock window, and the window it is attached to is below
4426            // the dock window, then the frames we computed for the window it is
4427            // attached to can not be used because the dock is effectively part
4428            // of the underlying window and the attached window is floating on top
4429            // of the whole thing.  So, we ignore the attached window and explicitly
4430            // compute the frames that would be appropriate without the dock.
4431            df.left = of.left = cf.left = vf.left = mDockLeft;
4432            df.top = of.top = cf.top = vf.top = mDockTop;
4433            df.right = of.right = cf.right = vf.right = mDockRight;
4434            df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom;
4435        } else {
4436            // The effective display frame of the attached window depends on
4437            // whether it is taking care of insetting its content.  If not,
4438            // we need to use the parent's content frame so that the entire
4439            // window is positioned within that content.  Otherwise we can use
4440            // the overscan frame and let the attached window take care of
4441            // positioning its content appropriately.
4442            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4443                // Set the content frame of the attached window to the parent's decor frame
4444                // (same as content frame when IME isn't present) if specifically requested by
4445                // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
4446                // Otherwise, use the overscan frame.
4447                cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
4448                        ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
4449            } else {
4450                // If the window is resizing, then we want to base the content
4451                // frame on our attached content frame to resize...  however,
4452                // things can be tricky if the attached window is NOT in resize
4453                // mode, in which case its content frame will be larger.
4454                // Ungh.  So to deal with that, make sure the content frame
4455                // we end up using is not covering the IM dock.
4456                cf.set(attached.getContentFrameLw());
4457                if (attached.isVoiceInteraction()) {
4458                    if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft;
4459                    if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop;
4460                    if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight;
4461                    if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom;
4462                } else if (attached.getSurfaceLayer() < mDockLayer) {
4463                    if (cf.left < mContentLeft) cf.left = mContentLeft;
4464                    if (cf.top < mContentTop) cf.top = mContentTop;
4465                    if (cf.right > mContentRight) cf.right = mContentRight;
4466                    if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
4467                }
4468            }
4469            df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
4470            of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
4471            vf.set(attached.getVisibleFrameLw());
4472        }
4473        // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
4474        // window should be positioned relative to its parent or the entire
4475        // screen.
4476        pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
4477                ? attached.getFrameLw() : df);
4478    }
4479
4480    private void applyStableConstraints(int sysui, int fl, Rect r) {
4481        if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4482            // If app is requesting a stable layout, don't let the
4483            // content insets go below the stable values.
4484            if ((fl & FLAG_FULLSCREEN) != 0) {
4485                if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft;
4486                if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop;
4487                if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight;
4488                if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom;
4489            } else {
4490                if (r.left < mStableLeft) r.left = mStableLeft;
4491                if (r.top < mStableTop) r.top = mStableTop;
4492                if (r.right > mStableRight) r.right = mStableRight;
4493                if (r.bottom > mStableBottom) r.bottom = mStableBottom;
4494            }
4495        }
4496    }
4497
4498    private boolean canReceiveInput(WindowState win) {
4499        boolean notFocusable =
4500                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
4501        boolean altFocusableIm =
4502                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
4503        boolean notFocusableForIm = notFocusable ^ altFocusableIm;
4504        return !notFocusableForIm;
4505    }
4506
4507    /** {@inheritDoc} */
4508    @Override
4509    public void layoutWindowLw(WindowState win, WindowState attached) {
4510        // We've already done the navigation bar and status bar. If the status bar can receive
4511        // input, we need to layout it again to accomodate for the IME window.
4512        if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) {
4513            return;
4514        }
4515        final WindowManager.LayoutParams attrs = win.getAttrs();
4516        final boolean isDefaultDisplay = win.isDefaultDisplay();
4517        final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
4518                (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
4519        if (needsToOffsetInputMethodTarget) {
4520            if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
4521            offsetInputMethodWindowLw(mLastInputMethodWindow);
4522        }
4523
4524        final int fl = PolicyControl.getWindowFlags(win, attrs);
4525        final int pfl = attrs.privateFlags;
4526        final int sim = attrs.softInputMode;
4527        final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
4528
4529        final Rect pf = mTmpParentFrame;
4530        final Rect df = mTmpDisplayFrame;
4531        final Rect of = mTmpOverscanFrame;
4532        final Rect cf = mTmpContentFrame;
4533        final Rect vf = mTmpVisibleFrame;
4534        final Rect dcf = mTmpDecorFrame;
4535        final Rect sf = mTmpStableFrame;
4536        Rect osf = null;
4537        dcf.setEmpty();
4538
4539        final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
4540                && mNavigationBar != null && mNavigationBar.isVisibleLw());
4541
4542        final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
4543
4544        if (isDefaultDisplay) {
4545            sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom);
4546        } else {
4547            sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom);
4548        }
4549
4550        if (!isDefaultDisplay) {
4551            if (attached != null) {
4552                // If this window is attached to another, our display
4553                // frame is the same as the one we are attached to.
4554                setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4555            } else {
4556                // Give the window full screen.
4557                pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4558                pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4559                pf.right = df.right = of.right = cf.right
4560                        = mOverscanScreenLeft + mOverscanScreenWidth;
4561                pf.bottom = df.bottom = of.bottom = cf.bottom
4562                        = mOverscanScreenTop + mOverscanScreenHeight;
4563            }
4564        } else if (attrs.type == TYPE_INPUT_METHOD) {
4565            pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
4566            pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
4567            pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
4568            // IM dock windows layout below the nav bar...
4569            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4570            // ...with content insets above the nav bar
4571            cf.bottom = vf.bottom = mStableBottom;
4572            if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
4573                // The status bar forces the navigation bar while it's visible. Make sure the IME
4574                // avoids the navigation bar in that case.
4575                if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4576                    pf.right = df.right = of.right = cf.right = vf.right = mStableRight;
4577                } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4578                    pf.left = df.left = of.left = cf.left = vf.left = mStableLeft;
4579                }
4580            }
4581            // IM dock windows always go to the bottom of the screen.
4582            attrs.gravity = Gravity.BOTTOM;
4583            mDockLayer = win.getSurfaceLayer();
4584        } else if (attrs.type == TYPE_VOICE_INTERACTION) {
4585            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4586            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4587            pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4588            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4589            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4590                cf.left = mDockLeft;
4591                cf.top = mDockTop;
4592                cf.right = mDockRight;
4593                cf.bottom = mDockBottom;
4594            } else {
4595                cf.left = mContentLeft;
4596                cf.top = mContentTop;
4597                cf.right = mContentRight;
4598                cf.bottom = mContentBottom;
4599            }
4600            if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4601                vf.left = mCurLeft;
4602                vf.top = mCurTop;
4603                vf.right = mCurRight;
4604                vf.bottom = mCurBottom;
4605            } else {
4606                vf.set(cf);
4607            }
4608        } else if (attrs.type == TYPE_WALLPAPER) {
4609           layoutWallpaper(win, pf, df, of, cf);
4610        } else if (win == mStatusBar) {
4611            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4612            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4613            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4614            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop;
4615            cf.left = vf.left = mStableLeft;
4616            cf.top = vf.top = mStableTop;
4617            cf.right = vf.right = mStableRight;
4618            vf.bottom = mStableBottom;
4619
4620            if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
4621                cf.bottom = mContentBottom;
4622            } else {
4623                cf.bottom = mDockBottom;
4624                vf.bottom = mContentBottom;
4625            }
4626        } else {
4627
4628            // Default policy decor for the default display
4629            dcf.left = mSystemLeft;
4630            dcf.top = mSystemTop;
4631            dcf.right = mSystemRight;
4632            dcf.bottom = mSystemBottom;
4633            final boolean inheritTranslucentDecor = (attrs.privateFlags
4634                    & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0;
4635            final boolean isAppWindow =
4636                    attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW &&
4637                    attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
4638            final boolean topAtRest =
4639                    win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
4640            if (isAppWindow && !inheritTranslucentDecor && !topAtRest) {
4641                if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
4642                        && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0
4643                        && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
4644                        && (fl & WindowManager.LayoutParams.
4645                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
4646                        && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) {
4647                    // Ensure policy decor includes status bar
4648                    dcf.top = mStableTop;
4649                }
4650                if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0
4651                        && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
4652                        && (fl & WindowManager.LayoutParams.
4653                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
4654                    // Ensure policy decor includes navigation bar
4655                    dcf.bottom = mStableBottom;
4656                    dcf.right = mStableRight;
4657                }
4658            }
4659
4660            if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4661                    == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4662                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
4663                            + "): IN_SCREEN, INSET_DECOR");
4664                // This is the case for a normal activity window: we want it
4665                // to cover all of the screen space, and it can take care of
4666                // moving its contents to account for screen decorations that
4667                // intrude into that space.
4668                if (attached != null) {
4669                    // If this window is attached to another, our display
4670                    // frame is the same as the one we are attached to.
4671                    setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4672                } else {
4673                    if (attrs.type == TYPE_STATUS_BAR_PANEL
4674                            || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
4675                        // Status bar panels are the only windows who can go on top of
4676                        // the status bar.  They are protected by the STATUS_BAR_SERVICE
4677                        // permission, so they have the same privileges as the status
4678                        // bar itself.
4679                        //
4680                        // However, they should still dodge the navigation bar if it exists.
4681
4682                        pf.left = df.left = of.left = hasNavBar
4683                                ? mDockLeft : mUnrestrictedScreenLeft;
4684                        pf.top = df.top = of.top = mUnrestrictedScreenTop;
4685                        pf.right = df.right = of.right = hasNavBar
4686                                ? mRestrictedScreenLeft+mRestrictedScreenWidth
4687                                : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4688                        pf.bottom = df.bottom = of.bottom = hasNavBar
4689                                ? mRestrictedScreenTop+mRestrictedScreenHeight
4690                                : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4691
4692                        if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4693                                        "Laying out status bar window: (%d,%d - %d,%d)",
4694                                        pf.left, pf.top, pf.right, pf.bottom));
4695                    } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4696                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4697                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4698                        // Asking to layout into the overscan region, so give it that pure
4699                        // unrestricted area.
4700                        pf.left = df.left = of.left = mOverscanScreenLeft;
4701                        pf.top = df.top = of.top = mOverscanScreenTop;
4702                        pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth;
4703                        pf.bottom = df.bottom = of.bottom = mOverscanScreenTop
4704                                + mOverscanScreenHeight;
4705                    } else if (canHideNavigationBar()
4706                            && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4707                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4708                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4709                        // Asking for layout as if the nav bar is hidden, lets the
4710                        // application extend into the unrestricted overscan screen area.  We
4711                        // only do this for application windows to ensure no window that
4712                        // can be above the nav bar can do this.
4713                        pf.left = df.left = mOverscanScreenLeft;
4714                        pf.top = df.top = mOverscanScreenTop;
4715                        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
4716                        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
4717                        // We need to tell the app about where the frame inside the overscan
4718                        // is, so it can inset its content by that amount -- it didn't ask
4719                        // to actually extend itself into the overscan region.
4720                        of.left = mUnrestrictedScreenLeft;
4721                        of.top = mUnrestrictedScreenTop;
4722                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4723                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4724                    } else {
4725                        pf.left = df.left = mRestrictedOverscanScreenLeft;
4726                        pf.top = df.top = mRestrictedOverscanScreenTop;
4727                        pf.right = df.right = mRestrictedOverscanScreenLeft
4728                                + mRestrictedOverscanScreenWidth;
4729                        pf.bottom = df.bottom = mRestrictedOverscanScreenTop
4730                                + mRestrictedOverscanScreenHeight;
4731                        // We need to tell the app about where the frame inside the overscan
4732                        // is, so it can inset its content by that amount -- it didn't ask
4733                        // to actually extend itself into the overscan region.
4734                        of.left = mUnrestrictedScreenLeft;
4735                        of.top = mUnrestrictedScreenTop;
4736                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4737                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4738                    }
4739
4740                    if ((fl & FLAG_FULLSCREEN) == 0) {
4741                        if (win.isVoiceInteraction()) {
4742                            cf.left = mVoiceContentLeft;
4743                            cf.top = mVoiceContentTop;
4744                            cf.right = mVoiceContentRight;
4745                            cf.bottom = mVoiceContentBottom;
4746                        } else {
4747                            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4748                                cf.left = mDockLeft;
4749                                cf.top = mDockTop;
4750                                cf.right = mDockRight;
4751                                cf.bottom = mDockBottom;
4752                            } else {
4753                                cf.left = mContentLeft;
4754                                cf.top = mContentTop;
4755                                cf.right = mContentRight;
4756                                cf.bottom = mContentBottom;
4757                            }
4758                        }
4759                    } else {
4760                        // Full screen windows are always given a layout that is as if the
4761                        // status bar and other transient decors are gone.  This is to avoid
4762                        // bad states when moving from a window that is not hding the
4763                        // status bar to one that is.
4764                        cf.left = mRestrictedScreenLeft;
4765                        cf.top = mRestrictedScreenTop;
4766                        cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
4767                        cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4768                    }
4769                    applyStableConstraints(sysUiFl, fl, cf);
4770                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4771                        vf.left = mCurLeft;
4772                        vf.top = mCurTop;
4773                        vf.right = mCurRight;
4774                        vf.bottom = mCurBottom;
4775                    } else {
4776                        vf.set(cf);
4777                    }
4778                }
4779            } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
4780                    & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
4781                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
4782                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4783                        "): IN_SCREEN");
4784                // A window that has requested to fill the entire screen just
4785                // gets everything, period.
4786                if (attrs.type == TYPE_STATUS_BAR_PANEL
4787                        || attrs.type == TYPE_STATUS_BAR_SUB_PANEL
4788                        || attrs.type == TYPE_VOLUME_OVERLAY) {
4789                    pf.left = df.left = of.left = cf.left = hasNavBar
4790                            ? mDockLeft : mUnrestrictedScreenLeft;
4791                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
4792                    pf.right = df.right = of.right = cf.right = hasNavBar
4793                                        ? mRestrictedScreenLeft+mRestrictedScreenWidth
4794                                        : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4795                    pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar
4796                                          ? mRestrictedScreenTop+mRestrictedScreenHeight
4797                                          : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4798                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4799                                    "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
4800                                    pf.left, pf.top, pf.right, pf.bottom));
4801                } else if (attrs.type == TYPE_NAVIGATION_BAR
4802                        || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
4803                    // The navigation bar has Real Ultimate Power.
4804                    pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4805                    pf.top = df.top = of.top = mUnrestrictedScreenTop;
4806                    pf.right = df.right = of.right = mUnrestrictedScreenLeft
4807                            + mUnrestrictedScreenWidth;
4808                    pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop
4809                            + mUnrestrictedScreenHeight;
4810                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4811                                    "Laying out navigation bar window: (%d,%d - %d,%d)",
4812                                    pf.left, pf.top, pf.right, pf.bottom));
4813                } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
4814                                || attrs.type == TYPE_BOOT_PROGRESS
4815                                || attrs.type == TYPE_SCREENSHOT)
4816                        && ((fl & FLAG_FULLSCREEN) != 0)) {
4817                    // Fullscreen secure system overlays get what they ask for. Screenshot region
4818                    // selection overlay should also expand to full screen.
4819                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4820                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4821                    pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
4822                            + mOverscanScreenWidth;
4823                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
4824                            + mOverscanScreenHeight;
4825                } else if (attrs.type == TYPE_BOOT_PROGRESS) {
4826                    // Boot progress screen always covers entire display.
4827                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4828                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4829                    pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
4830                            + mOverscanScreenWidth;
4831                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
4832                            + mOverscanScreenHeight;
4833                } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4834                        && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4835                        && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4836                    // Asking to layout into the overscan region, so give it that pure
4837                    // unrestricted area.
4838                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4839                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4840                    pf.right = df.right = of.right = cf.right
4841                            = mOverscanScreenLeft + mOverscanScreenWidth;
4842                    pf.bottom = df.bottom = of.bottom = cf.bottom
4843                            = mOverscanScreenTop + mOverscanScreenHeight;
4844                } else if (canHideNavigationBar()
4845                        && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4846                        && (attrs.type == TYPE_STATUS_BAR
4847                            || attrs.type == TYPE_TOAST
4848                            || attrs.type == TYPE_DOCK_DIVIDER
4849                            || attrs.type == TYPE_VOICE_INTERACTION_STARTING
4850                            || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4851                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
4852                    // Asking for layout as if the nav bar is hidden, lets the
4853                    // application extend into the unrestricted screen area.  We
4854                    // only do this for application windows (or toasts) to ensure no window that
4855                    // can be above the nav bar can do this.
4856                    // XXX This assumes that an app asking for this will also
4857                    // ask for layout in only content.  We can't currently figure out
4858                    // what the screen would be if only laying out to hide the nav bar.
4859                    pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
4860                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
4861                    pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft
4862                            + mUnrestrictedScreenWidth;
4863                    pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
4864                            + mUnrestrictedScreenHeight;
4865                } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
4866                    pf.left = df.left = of.left = mRestrictedScreenLeft;
4867                    pf.top = df.top = of.top  = mRestrictedScreenTop;
4868                    pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
4869                    pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop
4870                            + mRestrictedScreenHeight;
4871                    if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4872                        cf.left = mDockLeft;
4873                        cf.top = mDockTop;
4874                        cf.right = mDockRight;
4875                        cf.bottom = mDockBottom;
4876                    } else {
4877                        cf.left = mContentLeft;
4878                        cf.top = mContentTop;
4879                        cf.right = mContentRight;
4880                        cf.bottom = mContentBottom;
4881                    }
4882                } else {
4883                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
4884                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
4885                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
4886                            + mRestrictedScreenWidth;
4887                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
4888                            + mRestrictedScreenHeight;
4889                }
4890
4891                applyStableConstraints(sysUiFl, fl, cf);
4892
4893                if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4894                    vf.left = mCurLeft;
4895                    vf.top = mCurTop;
4896                    vf.right = mCurRight;
4897                    vf.bottom = mCurBottom;
4898                } else {
4899                    vf.set(cf);
4900                }
4901            } else if (attached != null) {
4902                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4903                        "): attached to " + attached);
4904                // A child window should be placed inside of the same visible
4905                // frame that its parent had.
4906                setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf);
4907            } else {
4908                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4909                        "): normal window");
4910                // Otherwise, a normal window must be placed inside the content
4911                // of all screen decorations.
4912                if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) {
4913                    // Status bar panels and the volume dialog are the only windows who can go on
4914                    // top of the status bar.  They are protected by the STATUS_BAR_SERVICE
4915                    // permission, so they have the same privileges as the status
4916                    // bar itself.
4917                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
4918                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
4919                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
4920                            + mRestrictedScreenWidth;
4921                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
4922                            + mRestrictedScreenHeight;
4923                } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) {
4924                    // These dialogs are stable to interim decor changes.
4925                    pf.left = df.left = of.left = cf.left = mStableLeft;
4926                    pf.top = df.top = of.top = cf.top = mStableTop;
4927                    pf.right = df.right = of.right = cf.right = mStableRight;
4928                    pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom;
4929                } else {
4930                    pf.left = mContentLeft;
4931                    pf.top = mContentTop;
4932                    pf.right = mContentRight;
4933                    pf.bottom = mContentBottom;
4934                    if (win.isVoiceInteraction()) {
4935                        df.left = of.left = cf.left = mVoiceContentLeft;
4936                        df.top = of.top = cf.top = mVoiceContentTop;
4937                        df.right = of.right = cf.right = mVoiceContentRight;
4938                        df.bottom = of.bottom = cf.bottom = mVoiceContentBottom;
4939                    } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4940                        df.left = of.left = cf.left = mDockLeft;
4941                        df.top = of.top = cf.top = mDockTop;
4942                        df.right = of.right = cf.right = mDockRight;
4943                        df.bottom = of.bottom = cf.bottom = mDockBottom;
4944                    } else {
4945                        df.left = of.left = cf.left = mContentLeft;
4946                        df.top = of.top = cf.top = mContentTop;
4947                        df.right = of.right = cf.right = mContentRight;
4948                        df.bottom = of.bottom = cf.bottom = mContentBottom;
4949                    }
4950                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4951                        vf.left = mCurLeft;
4952                        vf.top = mCurTop;
4953                        vf.right = mCurRight;
4954                        vf.bottom = mCurBottom;
4955                    } else {
4956                        vf.set(cf);
4957                    }
4958                }
4959            }
4960        }
4961
4962        // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
4963        // Also, we don't allow windows in multi-window mode to extend out of the screen.
4964        if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR
4965                && !win.isInMultiWindowMode()) {
4966            df.left = df.top = -10000;
4967            df.right = df.bottom = 10000;
4968            if (attrs.type != TYPE_WALLPAPER) {
4969                of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
4970                of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
4971            }
4972        }
4973
4974        // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we
4975        // need to provide information to the clients that want to pretend that you can draw there.
4976        // We only want to apply outsets to certain types of windows. For example, we never want to
4977        // apply the outsets to floating dialogs, because they wouldn't make sense there.
4978        final boolean useOutsets = shouldUseOutsets(attrs, fl);
4979        if (isDefaultDisplay && useOutsets) {
4980            osf = mTmpOutsetFrame;
4981            osf.set(cf.left, cf.top, cf.right, cf.bottom);
4982            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
4983            if (outset > 0) {
4984                int rotation = mDisplayRotation;
4985                if (rotation == Surface.ROTATION_0) {
4986                    osf.bottom += outset;
4987                } else if (rotation == Surface.ROTATION_90) {
4988                    osf.right += outset;
4989                } else if (rotation == Surface.ROTATION_180) {
4990                    osf.top -= outset;
4991                } else if (rotation == Surface.ROTATION_270) {
4992                    osf.left -= outset;
4993                }
4994                if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset
4995                        + " with rotation " + rotation + ", result: " + osf);
4996            }
4997        }
4998
4999        if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
5000                + ": sim=#" + Integer.toHexString(sim)
5001                + " attach=" + attached + " type=" + attrs.type
5002                + String.format(" flags=0x%08x", fl)
5003                + " pf=" + pf.toShortString() + " df=" + df.toShortString()
5004                + " of=" + of.toShortString()
5005                + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
5006                + " dcf=" + dcf.toShortString()
5007                + " sf=" + sf.toShortString()
5008                + " osf=" + (osf == null ? "null" : osf.toShortString()));
5009
5010        win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf);
5011
5012        // Dock windows carve out the bottom of the screen, so normal windows
5013        // can't appear underneath them.
5014        if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleOrBehindKeyguardLw()
5015                && win.isDisplayedLw() && !win.getGivenInsetsPendingLw()) {
5016            setLastInputMethodWindowLw(null, null);
5017            offsetInputMethodWindowLw(win);
5018        }
5019        if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleOrBehindKeyguardLw()
5020                && !win.getGivenInsetsPendingLw()) {
5021            offsetVoiceInputWindowLw(win);
5022        }
5023    }
5024
5025    private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) {
5026
5027        // The wallpaper also has Real Ultimate Power, but we want to tell
5028        // it about the overscan area.
5029        pf.left = df.left = mOverscanScreenLeft;
5030        pf.top = df.top = mOverscanScreenTop;
5031        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
5032        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
5033        of.left = cf.left = mUnrestrictedScreenLeft;
5034        of.top = cf.top = mUnrestrictedScreenTop;
5035        of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5036        of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5037    }
5038
5039    private void offsetInputMethodWindowLw(WindowState win) {
5040        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5041        top += win.getGivenContentInsetsLw().top;
5042        if (mContentBottom > top) {
5043            mContentBottom = top;
5044        }
5045        if (mVoiceContentBottom > top) {
5046            mVoiceContentBottom = top;
5047        }
5048        top = win.getVisibleFrameLw().top;
5049        top += win.getGivenVisibleInsetsLw().top;
5050        if (mCurBottom > top) {
5051            mCurBottom = top;
5052        }
5053        if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
5054                + mDockBottom + " mContentBottom="
5055                + mContentBottom + " mCurBottom=" + mCurBottom);
5056    }
5057
5058    private void offsetVoiceInputWindowLw(WindowState win) {
5059        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5060        top += win.getGivenContentInsetsLw().top;
5061        if (mVoiceContentBottom > top) {
5062            mVoiceContentBottom = top;
5063        }
5064    }
5065
5066    /** {@inheritDoc} */
5067    @Override
5068    public void finishLayoutLw() {
5069        return;
5070    }
5071
5072    /** {@inheritDoc} */
5073    @Override
5074    public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
5075        mTopFullscreenOpaqueWindowState = null;
5076        mTopFullscreenOpaqueOrDimmingWindowState = null;
5077        mTopDockedOpaqueWindowState = null;
5078        mTopDockedOpaqueOrDimmingWindowState = null;
5079        mAppsToBeHidden.clear();
5080        mAppsThatDismissKeyguard.clear();
5081        mForceStatusBar = false;
5082        mForceStatusBarFromKeyguard = false;
5083        mForceStatusBarTransparent = false;
5084        mForcingShowNavBar = false;
5085        mForcingShowNavBarLayer = -1;
5086
5087        mHideLockScreen = false;
5088        mAllowLockscreenWhenOn = false;
5089        mDismissKeyguard = DISMISS_KEYGUARD_NONE;
5090        mShowingLockscreen = false;
5091        mShowingDream = false;
5092        mWinShowWhenLocked = null;
5093        mKeyguardSecure = isKeyguardSecure(mCurrentUserId);
5094        mKeyguardSecureIncludingHidden = mKeyguardSecure
5095                && (mKeyguardDelegate != null && mKeyguardDelegate.isShowing());
5096    }
5097
5098    /** {@inheritDoc} */
5099    @Override
5100    public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
5101            WindowState attached) {
5102        if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
5103                + win.isVisibleOrBehindKeyguardLw());
5104        final int fl = PolicyControl.getWindowFlags(win, attrs);
5105        if (mTopFullscreenOpaqueWindowState == null
5106                && win.isVisibleLw() && attrs.type == TYPE_INPUT_METHOD) {
5107            mForcingShowNavBar = true;
5108            mForcingShowNavBarLayer = win.getSurfaceLayer();
5109        }
5110        if (attrs.type == TYPE_STATUS_BAR) {
5111            if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
5112                mForceStatusBarFromKeyguard = true;
5113                mShowingLockscreen = true;
5114            }
5115            if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
5116                mForceStatusBarTransparent = true;
5117            }
5118        }
5119
5120        boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
5121                && attrs.type < FIRST_SYSTEM_WINDOW;
5122        final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0;
5123        final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0;
5124        final int stackId = win.getStackId();
5125        if (mTopFullscreenOpaqueWindowState == null &&
5126                win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
5127            if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
5128                if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
5129                    mForceStatusBarFromKeyguard = true;
5130                } else {
5131                    mForceStatusBar = true;
5132                }
5133            }
5134            if (attrs.type == TYPE_DREAM) {
5135                // If the lockscreen was showing when the dream started then wait
5136                // for the dream to draw before hiding the lockscreen.
5137                if (!mDreamingLockscreen
5138                        || (win.isVisibleLw() && win.hasDrawnLw())) {
5139                    mShowingDream = true;
5140                    appWindow = true;
5141                }
5142            }
5143
5144            final IApplicationToken appToken = win.getAppToken();
5145
5146            // For app windows that are not attached, we decide if all windows in the app they
5147            // represent should be hidden or if we should hide the lockscreen. For attached app
5148            // windows we defer the decision to the window it is attached to.
5149            if (appWindow && attached == null) {
5150                if (showWhenLocked) {
5151                    // Remove any previous windows with the same appToken.
5152                    mAppsToBeHidden.remove(appToken);
5153                    mAppsThatDismissKeyguard.remove(appToken);
5154                    if (mAppsToBeHidden.isEmpty()) {
5155                        if (dismissKeyguard && !mKeyguardSecure) {
5156                            mAppsThatDismissKeyguard.add(appToken);
5157                        } else if (win.isDrawnLw() || win.hasAppShownWindows()) {
5158                            mWinShowWhenLocked = win;
5159                            mHideLockScreen = true;
5160                            mForceStatusBarFromKeyguard = false;
5161                        }
5162                    }
5163                } else if (dismissKeyguard) {
5164                    if (mKeyguardSecure) {
5165                        mAppsToBeHidden.add(appToken);
5166                    } else {
5167                        mAppsToBeHidden.remove(appToken);
5168                    }
5169                    mAppsThatDismissKeyguard.add(appToken);
5170                } else {
5171                    mAppsToBeHidden.add(appToken);
5172                }
5173                if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
5174                    if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
5175                    mTopFullscreenOpaqueWindowState = win;
5176                    if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5177                        mTopFullscreenOpaqueOrDimmingWindowState = win;
5178                    }
5179                    if (!mAppsThatDismissKeyguard.isEmpty() &&
5180                            mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
5181                        if (DEBUG_LAYOUT) Slog.v(TAG,
5182                                "Setting mDismissKeyguard true by win " + win);
5183                        mDismissKeyguard = (mWinDismissingKeyguard == win
5184                                && mSecureDismissingKeyguard == mKeyguardSecure)
5185                                ? DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
5186                        mWinDismissingKeyguard = win;
5187                        mSecureDismissingKeyguard = mKeyguardSecure;
5188                        mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure;
5189                    } else if (mAppsToBeHidden.isEmpty() && showWhenLocked
5190                            && (win.isDrawnLw() || win.hasAppShownWindows())) {
5191                        if (DEBUG_LAYOUT) Slog.v(TAG,
5192                                "Setting mHideLockScreen to true by win " + win);
5193                        mHideLockScreen = true;
5194                        mForceStatusBarFromKeyguard = false;
5195                    }
5196                    if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
5197                        mAllowLockscreenWhenOn = true;
5198                    }
5199                }
5200
5201                if (!mKeyguardHidden && mWinShowWhenLocked != null &&
5202                        mWinShowWhenLocked.getAppToken() != win.getAppToken() &&
5203                        (attrs.flags & FLAG_SHOW_WHEN_LOCKED) == 0) {
5204                    win.hideLw(false);
5205                }
5206            }
5207        } else if (mTopFullscreenOpaqueWindowState == null && mWinShowWhenLocked == null) {
5208            // No TopFullscreenOpaqueWindow is showing, but we found a SHOW_WHEN_LOCKED window
5209            // that is being hidden in an animation - keep the
5210            // keyguard hidden until the new window shows up and
5211            // we know whether to show the keyguard or not.
5212            if (win.isAnimatingLw() && appWindow && showWhenLocked && mKeyguardHidden) {
5213                mHideLockScreen = true;
5214                mWinShowWhenLocked = win;
5215            }
5216        }
5217
5218        final boolean reallyVisible = win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw();
5219
5220        // Voice interaction overrides both top fullscreen and top docked.
5221        if (reallyVisible && win.getAttrs().type == TYPE_VOICE_INTERACTION) {
5222            if (mTopFullscreenOpaqueWindowState == null) {
5223                mTopFullscreenOpaqueWindowState = win;
5224                if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5225                    mTopFullscreenOpaqueOrDimmingWindowState = win;
5226                }
5227            }
5228            if (mTopDockedOpaqueWindowState == null) {
5229                mTopDockedOpaqueWindowState = win;
5230                if (mTopDockedOpaqueOrDimmingWindowState == null) {
5231                    mTopDockedOpaqueOrDimmingWindowState = win;
5232                }
5233            }
5234        }
5235
5236        // Keep track of the window if it's dimming but not necessarily fullscreen.
5237        if (mTopFullscreenOpaqueOrDimmingWindowState == null && reallyVisible
5238                && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
5239            mTopFullscreenOpaqueOrDimmingWindowState = win;
5240        }
5241
5242        // We need to keep track of the top "fullscreen" opaque window for the docked stack
5243        // separately, because both the "real fullscreen" opaque window and the one for the docked
5244        // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
5245        if (mTopDockedOpaqueWindowState == null && reallyVisible && appWindow && attached == null
5246                && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
5247            mTopDockedOpaqueWindowState = win;
5248            if (mTopDockedOpaqueOrDimmingWindowState == null) {
5249                mTopDockedOpaqueOrDimmingWindowState = win;
5250            }
5251        }
5252
5253        // Also keep track of any windows that are dimming but not necessarily fullscreen in the
5254        // docked stack.
5255        if (mTopDockedOpaqueOrDimmingWindowState == null && reallyVisible && win.isDimming()
5256                && stackId == DOCKED_STACK_ID) {
5257            mTopDockedOpaqueOrDimmingWindowState = win;
5258        }
5259    }
5260
5261    private boolean isFullscreen(WindowManager.LayoutParams attrs) {
5262        return attrs.x == 0 && attrs.y == 0
5263                && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
5264                && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
5265    }
5266
5267    /** {@inheritDoc} */
5268    @Override
5269    public int finishPostLayoutPolicyLw() {
5270        if (mWinShowWhenLocked != null && mTopFullscreenOpaqueWindowState != null &&
5271                mWinShowWhenLocked.getAppToken() != mTopFullscreenOpaqueWindowState.getAppToken()
5272                && isKeyguardLocked()) {
5273            // A dialog is dismissing the keyguard. Put the wallpaper behind it and hide the
5274            // fullscreen window.
5275            // TODO: Make sure FLAG_SHOW_WALLPAPER is restored when dialog is dismissed. Or not.
5276            mWinShowWhenLocked.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5277            mTopFullscreenOpaqueWindowState.hideLw(false);
5278            mTopFullscreenOpaqueWindowState = mWinShowWhenLocked;
5279        }
5280
5281        int changes = 0;
5282        boolean topIsFullscreen = false;
5283
5284        final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
5285                ? mTopFullscreenOpaqueWindowState.getAttrs()
5286                : null;
5287
5288        // If we are not currently showing a dream then remember the current
5289        // lockscreen state.  We will use this to determine whether the dream
5290        // started while the lockscreen was showing and remember this state
5291        // while the dream is showing.
5292        if (!mShowingDream) {
5293            mDreamingLockscreen = mShowingLockscreen;
5294            if (mDreamingSleepTokenNeeded) {
5295                mDreamingSleepTokenNeeded = false;
5296                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
5297            }
5298        } else {
5299            if (!mDreamingSleepTokenNeeded) {
5300                mDreamingSleepTokenNeeded = true;
5301                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget();
5302            }
5303        }
5304
5305        if (mStatusBar != null) {
5306            if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
5307                    + " forcefkg=" + mForceStatusBarFromKeyguard
5308                    + " top=" + mTopFullscreenOpaqueWindowState);
5309            boolean shouldBeTransparent = mForceStatusBarTransparent
5310                    && !mForceStatusBar
5311                    && !mForceStatusBarFromKeyguard;
5312            if (!shouldBeTransparent) {
5313                mStatusBarController.setShowTransparent(false /* transparent */);
5314            } else if (!mStatusBar.isVisibleLw()) {
5315                mStatusBarController.setShowTransparent(true /* transparent */);
5316            }
5317
5318            WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs();
5319            boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT
5320                    && statusBarAttrs.width == MATCH_PARENT;
5321            if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
5322                    || statusBarExpanded) {
5323                if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
5324                if (mStatusBarController.setBarShowingLw(true)) {
5325                    changes |= FINISH_LAYOUT_REDO_LAYOUT;
5326                }
5327                // Maintain fullscreen layout until incoming animation is complete.
5328                topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
5329                // Transient status bar on the lockscreen is not allowed
5330                if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) {
5331                    mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
5332                            mLastSystemUiFlags, mLastSystemUiFlags);
5333                }
5334                if (statusBarExpanded && mNavigationBar != null) {
5335                    if (mNavigationBarController.setBarShowingLw(true)) {
5336                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5337                    }
5338                }
5339            } else if (mTopFullscreenOpaqueWindowState != null) {
5340                final int fl = PolicyControl.getWindowFlags(null, lp);
5341                if (localLOGV) {
5342                    Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
5343                            + " shown position: "
5344                            + mTopFullscreenOpaqueWindowState.getShownPositionLw());
5345                    Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
5346                            + " lp.flags=0x" + Integer.toHexString(fl));
5347                }
5348                topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
5349                        || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
5350                // The subtle difference between the window for mTopFullscreenOpaqueWindowState
5351                // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
5352                // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
5353                // case though.
5354                if (mStatusBarController.isTransientShowing()) {
5355                    if (mStatusBarController.setBarShowingLw(true)) {
5356                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5357                    }
5358                } else if (topIsFullscreen
5359                        && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)
5360                        && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) {
5361                    if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
5362                    if (mStatusBarController.setBarShowingLw(false)) {
5363                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5364                    } else {
5365                        if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
5366                    }
5367                } else {
5368                    if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
5369                    if (mStatusBarController.setBarShowingLw(true)) {
5370                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5371                    }
5372                }
5373            }
5374        }
5375
5376        if (mTopIsFullscreen != topIsFullscreen) {
5377            if (!topIsFullscreen) {
5378                // Force another layout when status bar becomes fully shown.
5379                changes |= FINISH_LAYOUT_REDO_LAYOUT;
5380            }
5381            mTopIsFullscreen = topIsFullscreen;
5382        }
5383
5384        // Hide the key guard if a visible window explicitly specifies that it wants to be
5385        // displayed when the screen is locked.
5386        if (mKeyguardDelegate != null && mStatusBar != null) {
5387            if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
5388                    + mHideLockScreen);
5389            if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardSecure) {
5390                mKeyguardHidden = true;
5391                if (setKeyguardOccludedLw(true)) {
5392                    changes |= FINISH_LAYOUT_REDO_LAYOUT
5393                            | FINISH_LAYOUT_REDO_CONFIG
5394                            | FINISH_LAYOUT_REDO_WALLPAPER;
5395                }
5396                if (mKeyguardDelegate.isShowing()) {
5397                    mHandler.post(new Runnable() {
5398                        @Override
5399                        public void run() {
5400                            mKeyguardDelegate.keyguardDone(false, false);
5401                        }
5402                    });
5403                }
5404            } else if (mHideLockScreen) {
5405                mKeyguardHidden = true;
5406                mWinDismissingKeyguard = null;
5407                if (setKeyguardOccludedLw(true)) {
5408                    changes |= FINISH_LAYOUT_REDO_LAYOUT
5409                            | FINISH_LAYOUT_REDO_CONFIG
5410                            | FINISH_LAYOUT_REDO_WALLPAPER;
5411                }
5412            } else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) {
5413                mKeyguardHidden = false;
5414                boolean dismissKeyguard = false;
5415                final boolean trusted = mKeyguardDelegate.isTrusted();
5416                if (mDismissKeyguard == DISMISS_KEYGUARD_START) {
5417                    final boolean willDismiss = trusted && mKeyguardOccluded
5418                            && mKeyguardDelegate != null && mKeyguardDelegate.isShowing();
5419                    if (willDismiss) {
5420                        mCurrentlyDismissingKeyguard = true;
5421                    }
5422                    dismissKeyguard = true;
5423                }
5424
5425                // If we are currently dismissing Keyguard, there is no need to unocclude it.
5426                if (!mCurrentlyDismissingKeyguard) {
5427                    if (setKeyguardOccludedLw(false)) {
5428                        changes |= FINISH_LAYOUT_REDO_LAYOUT
5429                                | FINISH_LAYOUT_REDO_CONFIG
5430                                | FINISH_LAYOUT_REDO_WALLPAPER;
5431                    }
5432                }
5433
5434                if (dismissKeyguard) {
5435                    // Only launch the next keyguard unlock window once per window.
5436                    mHandler.post(() -> mKeyguardDelegate.dismiss(
5437                            trusted /* allowWhileOccluded */));
5438                }
5439            } else {
5440                mWinDismissingKeyguard = null;
5441                mSecureDismissingKeyguard = false;
5442                mKeyguardHidden = false;
5443                if (setKeyguardOccludedLw(false)) {
5444                    changes |= FINISH_LAYOUT_REDO_LAYOUT
5445                            | FINISH_LAYOUT_REDO_CONFIG
5446                            | FINISH_LAYOUT_REDO_WALLPAPER;
5447                }
5448            }
5449        }
5450
5451        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5452            // If the navigation bar has been hidden or shown, we need to do another
5453            // layout pass to update that window.
5454            changes |= FINISH_LAYOUT_REDO_LAYOUT;
5455        }
5456
5457        // update since mAllowLockscreenWhenOn might have changed
5458        updateLockScreenTimeout();
5459        return changes;
5460    }
5461
5462    /**
5463     * Updates the occluded state of the Keyguard.
5464     *
5465     * @return Whether the flags have changed and we have to redo the layout.
5466     */
5467    private boolean setKeyguardOccludedLw(boolean isOccluded) {
5468        boolean wasOccluded = mKeyguardOccluded;
5469        boolean showing = mKeyguardDelegate.isShowing();
5470        if (wasOccluded && !isOccluded && showing) {
5471            mKeyguardOccluded = false;
5472            mKeyguardDelegate.setOccluded(false, true /* animate */);
5473            mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
5474            if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
5475                mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5476            }
5477            Animation anim = AnimationUtils.loadAnimation(mContext,
5478                    com.android.internal.R.anim.wallpaper_open_exit);
5479            mWindowManagerFuncs.overridePlayingAppAnimationsLw(anim);
5480            return true;
5481        } else if (!wasOccluded && isOccluded && showing) {
5482            mKeyguardOccluded = true;
5483            mKeyguardDelegate.setOccluded(true, false /* animate */);
5484            mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
5485            mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
5486            return true;
5487        } else {
5488            return false;
5489        }
5490    }
5491
5492    private void onKeyguardShowingStateChanged(boolean showing) {
5493        if (!showing) {
5494            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
5495                mCurrentlyDismissingKeyguard = false;
5496            }
5497        }
5498    }
5499
5500    private boolean isStatusBarKeyguard() {
5501        return mStatusBar != null
5502                && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
5503    }
5504
5505    @Override
5506    public boolean allowAppAnimationsLw() {
5507        if (isStatusBarKeyguard() || mShowingDream) {
5508            // If keyguard or dreams is currently visible, no reason to animate behind it.
5509            return false;
5510        }
5511        return true;
5512    }
5513
5514    @Override
5515    public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
5516        mFocusedWindow = newFocus;
5517        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5518            // If the navigation bar has been hidden or shown, we need to do another
5519            // layout pass to update that window.
5520            return FINISH_LAYOUT_REDO_LAYOUT;
5521        }
5522        return 0;
5523    }
5524
5525    /** {@inheritDoc} */
5526    @Override
5527    public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
5528        // lid changed state
5529        final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
5530        if (newLidState == mLidState) {
5531            return;
5532        }
5533
5534        mLidState = newLidState;
5535        applyLidSwitchState();
5536        updateRotation(true);
5537
5538        if (lidOpen) {
5539            wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
5540                    "android.policy:LID");
5541        } else if (!mLidControlsSleep) {
5542            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
5543        }
5544    }
5545
5546    @Override
5547    public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
5548        int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
5549        if (mCameraLensCoverState == lensCoverState) {
5550            return;
5551        }
5552        if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
5553                lensCoverState == CAMERA_LENS_UNCOVERED) {
5554            Intent intent;
5555            final boolean keyguardActive = mKeyguardDelegate == null ? false :
5556                    mKeyguardDelegate.isShowing();
5557            if (keyguardActive) {
5558                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
5559            } else {
5560                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
5561            }
5562            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
5563                    "android.policy:CAMERA_COVER");
5564            startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
5565        }
5566        mCameraLensCoverState = lensCoverState;
5567    }
5568
5569    void setHdmiPlugged(boolean plugged) {
5570        if (mHdmiPlugged != plugged) {
5571            mHdmiPlugged = plugged;
5572            updateRotation(true, true);
5573            Intent intent = new Intent(ACTION_HDMI_PLUGGED);
5574            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
5575            intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
5576            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
5577        }
5578    }
5579
5580    void initializeHdmiState() {
5581        boolean plugged = false;
5582        // watch for HDMI plug messages if the hdmi switch exists
5583        if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
5584            mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
5585
5586            final String filename = "/sys/class/switch/hdmi/state";
5587            FileReader reader = null;
5588            try {
5589                reader = new FileReader(filename);
5590                char[] buf = new char[15];
5591                int n = reader.read(buf);
5592                if (n > 1) {
5593                    plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
5594                }
5595            } catch (IOException ex) {
5596                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5597            } catch (NumberFormatException ex) {
5598                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5599            } finally {
5600                if (reader != null) {
5601                    try {
5602                        reader.close();
5603                    } catch (IOException ex) {
5604                    }
5605                }
5606            }
5607        }
5608        // This dance forces the code in setHdmiPlugged to run.
5609        // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
5610        mHdmiPlugged = !plugged;
5611        setHdmiPlugged(!mHdmiPlugged);
5612    }
5613
5614    final Object mScreenshotLock = new Object();
5615    ServiceConnection mScreenshotConnection = null;
5616
5617    final Runnable mScreenshotTimeout = new Runnable() {
5618        @Override public void run() {
5619            synchronized (mScreenshotLock) {
5620                if (mScreenshotConnection != null) {
5621                    mContext.unbindService(mScreenshotConnection);
5622                    mScreenshotConnection = null;
5623                    notifyScreenshotError();
5624                }
5625            }
5626        }
5627    };
5628
5629    // Assume this is called from the Handler thread.
5630    private void takeScreenshot(final int screenshotType) {
5631        synchronized (mScreenshotLock) {
5632            if (mScreenshotConnection != null) {
5633                return;
5634            }
5635            final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
5636                    SYSUI_SCREENSHOT_SERVICE);
5637            final Intent serviceIntent = new Intent();
5638            serviceIntent.setComponent(serviceComponent);
5639            ServiceConnection conn = new ServiceConnection() {
5640                @Override
5641                public void onServiceConnected(ComponentName name, IBinder service) {
5642                    synchronized (mScreenshotLock) {
5643                        if (mScreenshotConnection != this) {
5644                            return;
5645                        }
5646                        Messenger messenger = new Messenger(service);
5647                        Message msg = Message.obtain(null, screenshotType);
5648                        final ServiceConnection myConn = this;
5649                        Handler h = new Handler(mHandler.getLooper()) {
5650                            @Override
5651                            public void handleMessage(Message msg) {
5652                                synchronized (mScreenshotLock) {
5653                                    if (mScreenshotConnection == myConn) {
5654                                        mContext.unbindService(mScreenshotConnection);
5655                                        mScreenshotConnection = null;
5656                                        mHandler.removeCallbacks(mScreenshotTimeout);
5657                                    }
5658                                }
5659                            }
5660                        };
5661                        msg.replyTo = new Messenger(h);
5662                        msg.arg1 = msg.arg2 = 0;
5663                        if (mStatusBar != null && mStatusBar.isVisibleLw())
5664                            msg.arg1 = 1;
5665                        if (mNavigationBar != null && mNavigationBar.isVisibleLw())
5666                            msg.arg2 = 1;
5667                        try {
5668                            messenger.send(msg);
5669                        } catch (RemoteException e) {
5670                        }
5671                    }
5672                }
5673
5674                @Override
5675                public void onServiceDisconnected(ComponentName name) {
5676                    synchronized (mScreenshotLock) {
5677                        if (mScreenshotConnection != null) {
5678                            mContext.unbindService(mScreenshotConnection);
5679                            mScreenshotConnection = null;
5680                            mHandler.removeCallbacks(mScreenshotTimeout);
5681                            notifyScreenshotError();
5682                        }
5683                    }
5684                }
5685            };
5686            if (mContext.bindServiceAsUser(serviceIntent, conn,
5687                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
5688                    UserHandle.CURRENT)) {
5689                mScreenshotConnection = conn;
5690                mHandler.postDelayed(mScreenshotTimeout, 10000);
5691            }
5692        }
5693    }
5694
5695    /**
5696     * Notifies the screenshot service to show an error.
5697     */
5698    private void notifyScreenshotError() {
5699        // If the service process is killed, then ask it to clean up after itself
5700        final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
5701                SYSUI_SCREENSHOT_ERROR_RECEIVER);
5702        Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
5703        errorIntent.setComponent(errorComponent);
5704        errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
5705                Intent.FLAG_RECEIVER_FOREGROUND);
5706        mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT);
5707    }
5708
5709    /** {@inheritDoc} */
5710    @Override
5711    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
5712        if (!mSystemBooted) {
5713            // If we have not yet booted, don't let key events do anything.
5714            return 0;
5715        }
5716
5717        final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
5718        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
5719        final boolean canceled = event.isCanceled();
5720        final int keyCode = event.getKeyCode();
5721
5722        final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
5723
5724        // If screen is off then we treat the case where the keyguard is open but hidden
5725        // the same as if it were open and in front.
5726        // This will prevent any keys other than the power button from waking the screen
5727        // when the keyguard is hidden by another activity.
5728        final boolean keyguardActive = (mKeyguardDelegate == null ? false :
5729                                            (interactive ?
5730                                                isKeyguardShowingAndNotOccluded() :
5731                                                mKeyguardDelegate.isShowing()));
5732
5733        if (DEBUG_INPUT) {
5734            Log.d(TAG, "interceptKeyTq keycode=" + keyCode
5735                    + " interactive=" + interactive + " keyguardActive=" + keyguardActive
5736                    + " policyFlags=" + Integer.toHexString(policyFlags));
5737        }
5738
5739        // Basic policy based on interactive state.
5740        int result;
5741        boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
5742                || event.isWakeKey();
5743        if (interactive || (isInjected && !isWakeKey)) {
5744            // When the device is interactive or the key is injected pass the
5745            // key to the application.
5746            result = ACTION_PASS_TO_USER;
5747            isWakeKey = false;
5748
5749            if (interactive) {
5750                // If the screen is awake, but the button pressed was the one that woke the device
5751                // then don't pass it to the application
5752                if (keyCode == mPendingWakeKey && !down) {
5753                    result = 0;
5754                }
5755                // Reset the pending key
5756                mPendingWakeKey = PENDING_KEY_NULL;
5757            }
5758        } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
5759            // If we're currently dozing with the screen on and the keyguard showing, pass the key
5760            // to the application but preserve its wake key status to make sure we still move
5761            // from dozing to fully interactive if we would normally go from off to fully
5762            // interactive.
5763            result = ACTION_PASS_TO_USER;
5764            // Since we're dispatching the input, reset the pending key
5765            mPendingWakeKey = PENDING_KEY_NULL;
5766        } else {
5767            // When the screen is off and the key is not injected, determine whether
5768            // to wake the device but don't pass the key to the application.
5769            result = 0;
5770            if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
5771                isWakeKey = false;
5772            }
5773            // Cache the wake key on down event so we can also avoid sending the up event to the app
5774            if (isWakeKey && down) {
5775                mPendingWakeKey = keyCode;
5776            }
5777        }
5778
5779        // If the key would be handled globally, just return the result, don't worry about special
5780        // key processing.
5781        if (isValidGlobalKey(keyCode)
5782                && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
5783            if (isWakeKey) {
5784                wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5785            }
5786            return result;
5787        }
5788
5789        boolean useHapticFeedback = down
5790                && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
5791                && event.getRepeatCount() == 0;
5792
5793        // Handle special keys.
5794        switch (keyCode) {
5795            case KeyEvent.KEYCODE_BACK: {
5796                if (down) {
5797                    interceptBackKeyDown();
5798                } else {
5799                    boolean handled = interceptBackKeyUp(event);
5800
5801                    // Don't pass back press to app if we've already handled it via long press
5802                    if (handled) {
5803                        result &= ~ACTION_PASS_TO_USER;
5804                    }
5805                }
5806                break;
5807            }
5808
5809            case KeyEvent.KEYCODE_VOLUME_DOWN:
5810            case KeyEvent.KEYCODE_VOLUME_UP:
5811            case KeyEvent.KEYCODE_VOLUME_MUTE: {
5812                if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
5813                    if (down) {
5814                        if (interactive && !mScreenshotChordVolumeDownKeyTriggered
5815                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5816                            mScreenshotChordVolumeDownKeyTriggered = true;
5817                            mScreenshotChordVolumeDownKeyTime = event.getDownTime();
5818                            mScreenshotChordVolumeDownKeyConsumed = false;
5819                            cancelPendingPowerKeyAction();
5820                            interceptScreenshotChord();
5821                        }
5822                    } else {
5823                        mScreenshotChordVolumeDownKeyTriggered = false;
5824                        cancelPendingScreenshotChordAction();
5825                    }
5826                } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
5827                    if (down) {
5828                        if (interactive && !mScreenshotChordVolumeUpKeyTriggered
5829                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5830                            mScreenshotChordVolumeUpKeyTriggered = true;
5831                            cancelPendingPowerKeyAction();
5832                            cancelPendingScreenshotChordAction();
5833                        }
5834                    } else {
5835                        mScreenshotChordVolumeUpKeyTriggered = false;
5836                        cancelPendingScreenshotChordAction();
5837                    }
5838                }
5839                if (down) {
5840                    TelecomManager telecomManager = getTelecommService();
5841                    if (telecomManager != null) {
5842                        if (telecomManager.isRinging()) {
5843                            // If an incoming call is ringing, either VOLUME key means
5844                            // "silence ringer".  We handle these keys here, rather than
5845                            // in the InCallScreen, to make sure we'll respond to them
5846                            // even if the InCallScreen hasn't come to the foreground yet.
5847                            // Look for the DOWN event here, to agree with the "fallback"
5848                            // behavior in the InCallScreen.
5849                            Log.i(TAG, "interceptKeyBeforeQueueing:"
5850                                  + " VOLUME key-down while ringing: Silence ringer!");
5851
5852                            // Silence the ringer.  (It's safe to call this
5853                            // even if the ringer has already been silenced.)
5854                            telecomManager.silenceRinger();
5855
5856                            // And *don't* pass this key thru to the current activity
5857                            // (which is probably the InCallScreen.)
5858                            result &= ~ACTION_PASS_TO_USER;
5859                            break;
5860                        }
5861                        if (telecomManager.isInCall()
5862                                && (result & ACTION_PASS_TO_USER) == 0) {
5863                            // If we are in call but we decided not to pass the key to
5864                            // the application, just pass it to the session service.
5865
5866                            MediaSessionLegacyHelper.getHelper(mContext)
5867                                    .sendVolumeKeyEvent(event, false);
5868                            break;
5869                        }
5870                    }
5871                }
5872                if (mUseTvRouting) {
5873                    // On TVs, defer special key handlings to
5874                    // {@link interceptKeyBeforeDispatching()}.
5875                    result |= ACTION_PASS_TO_USER;
5876                } else if ((result & ACTION_PASS_TO_USER) == 0) {
5877                    // If we aren't passing to the user and no one else
5878                    // handled it send it to the session manager to
5879                    // figure out.
5880                    MediaSessionLegacyHelper.getHelper(mContext)
5881                            .sendVolumeKeyEvent(event, true);
5882                }
5883                break;
5884            }
5885
5886            case KeyEvent.KEYCODE_ENDCALL: {
5887                result &= ~ACTION_PASS_TO_USER;
5888                if (down) {
5889                    TelecomManager telecomManager = getTelecommService();
5890                    boolean hungUp = false;
5891                    if (telecomManager != null) {
5892                        hungUp = telecomManager.endCall();
5893                    }
5894                    if (interactive && !hungUp) {
5895                        mEndCallKeyHandled = false;
5896                        mHandler.postDelayed(mEndCallLongPress,
5897                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
5898                    } else {
5899                        mEndCallKeyHandled = true;
5900                    }
5901                } else {
5902                    if (!mEndCallKeyHandled) {
5903                        mHandler.removeCallbacks(mEndCallLongPress);
5904                        if (!canceled) {
5905                            if ((mEndcallBehavior
5906                                    & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
5907                                if (goHome()) {
5908                                    break;
5909                                }
5910                            }
5911                            if ((mEndcallBehavior
5912                                    & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
5913                                mPowerManager.goToSleep(event.getEventTime(),
5914                                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
5915                                isWakeKey = false;
5916                            }
5917                        }
5918                    }
5919                }
5920                break;
5921            }
5922
5923            case KeyEvent.KEYCODE_POWER: {
5924                result &= ~ACTION_PASS_TO_USER;
5925                isWakeKey = false; // wake-up will be handled separately
5926                if (down) {
5927                    interceptPowerKeyDown(event, interactive);
5928                } else {
5929                    interceptPowerKeyUp(event, interactive, canceled);
5930                }
5931                break;
5932            }
5933
5934            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
5935                // fall through
5936            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
5937                // fall through
5938            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
5939                // fall through
5940            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
5941                result &= ~ACTION_PASS_TO_USER;
5942                interceptSystemNavigationKey(event);
5943                break;
5944            }
5945
5946            case KeyEvent.KEYCODE_SLEEP: {
5947                result &= ~ACTION_PASS_TO_USER;
5948                isWakeKey = false;
5949                if (!mPowerManager.isInteractive()) {
5950                    useHapticFeedback = false; // suppress feedback if already non-interactive
5951                }
5952                if (down) {
5953                    sleepPress(event.getEventTime());
5954                } else {
5955                    sleepRelease(event.getEventTime());
5956                }
5957                break;
5958            }
5959
5960            case KeyEvent.KEYCODE_SOFT_SLEEP: {
5961                result &= ~ACTION_PASS_TO_USER;
5962                isWakeKey = false;
5963                if (!down) {
5964                    mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
5965                }
5966                break;
5967            }
5968
5969            case KeyEvent.KEYCODE_WAKEUP: {
5970                result &= ~ACTION_PASS_TO_USER;
5971                isWakeKey = true;
5972                break;
5973            }
5974
5975            case KeyEvent.KEYCODE_MEDIA_PLAY:
5976            case KeyEvent.KEYCODE_MEDIA_PAUSE:
5977            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
5978            case KeyEvent.KEYCODE_HEADSETHOOK:
5979            case KeyEvent.KEYCODE_MUTE:
5980            case KeyEvent.KEYCODE_MEDIA_STOP:
5981            case KeyEvent.KEYCODE_MEDIA_NEXT:
5982            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
5983            case KeyEvent.KEYCODE_MEDIA_REWIND:
5984            case KeyEvent.KEYCODE_MEDIA_RECORD:
5985            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
5986            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
5987                if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
5988                    // If the global session is active pass all media keys to it
5989                    // instead of the active window.
5990                    result &= ~ACTION_PASS_TO_USER;
5991                }
5992                if ((result & ACTION_PASS_TO_USER) == 0) {
5993                    // Only do this if we would otherwise not pass it to the user. In that
5994                    // case, the PhoneWindow class will do the same thing, except it will
5995                    // only do it if the showing app doesn't process the key on its own.
5996                    // Note that we need to make a copy of the key event here because the
5997                    // original key event will be recycled when we return.
5998                    mBroadcastWakeLock.acquire();
5999                    Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
6000                            new KeyEvent(event));
6001                    msg.setAsynchronous(true);
6002                    msg.sendToTarget();
6003                }
6004                break;
6005            }
6006
6007            case KeyEvent.KEYCODE_CALL: {
6008                if (down) {
6009                    TelecomManager telecomManager = getTelecommService();
6010                    if (telecomManager != null) {
6011                        if (telecomManager.isRinging()) {
6012                            Log.i(TAG, "interceptKeyBeforeQueueing:"
6013                                  + " CALL key-down while ringing: Answer the call!");
6014                            telecomManager.acceptRingingCall();
6015
6016                            // And *don't* pass this key thru to the current activity
6017                            // (which is presumably the InCallScreen.)
6018                            result &= ~ACTION_PASS_TO_USER;
6019                        }
6020                    }
6021                }
6022                break;
6023            }
6024            case KeyEvent.KEYCODE_VOICE_ASSIST: {
6025                // Only do this if we would otherwise not pass it to the user. In that case,
6026                // interceptKeyBeforeDispatching would apply a similar but different policy in
6027                // order to invoke voice assist actions. Note that we need to make a copy of the
6028                // key event here because the original key event will be recycled when we return.
6029                if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
6030                    mBroadcastWakeLock.acquire();
6031                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
6032                            keyguardActive ? 1 : 0, 0);
6033                    msg.setAsynchronous(true);
6034                    msg.sendToTarget();
6035                }
6036                break;
6037            }
6038            case KeyEvent.KEYCODE_WINDOW: {
6039                if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
6040                    if (mTvPictureInPictureVisible) {
6041                        // Consumes the key only if picture-in-picture is visible
6042                        // to show picture-in-picture control menu.
6043                        // This gives a chance to the foreground activity
6044                        // to customize PIP key behavior.
6045                        if (!down) {
6046                            showTvPictureInPictureMenu(event);
6047                        }
6048                        result &= ~ACTION_PASS_TO_USER;
6049                    }
6050                }
6051                break;
6052            }
6053        }
6054
6055        if (useHapticFeedback) {
6056            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
6057        }
6058
6059        if (isWakeKey) {
6060            wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
6061        }
6062
6063        return result;
6064    }
6065
6066    /**
6067     * Handle statusbar expansion events.
6068     * @param event
6069     */
6070    private void interceptSystemNavigationKey(KeyEvent event) {
6071        if (event.getAction() == KeyEvent.ACTION_UP && areSystemNavigationKeysEnabled()) {
6072            IStatusBarService sbar = getStatusBarService();
6073            if (sbar != null) {
6074                try {
6075                    sbar.handleSystemNavigationKey(event.getKeyCode());
6076                } catch (RemoteException e1) {
6077                    // oops, no statusbar. Ignore event.
6078                }
6079            }
6080        }
6081    }
6082
6083    /**
6084     * Returns true if the key can have global actions attached to it.
6085     * We reserve all power management keys for the system since they require
6086     * very careful handling.
6087     */
6088    private static boolean isValidGlobalKey(int keyCode) {
6089        switch (keyCode) {
6090            case KeyEvent.KEYCODE_POWER:
6091            case KeyEvent.KEYCODE_WAKEUP:
6092            case KeyEvent.KEYCODE_SLEEP:
6093                return false;
6094            default:
6095                return true;
6096        }
6097    }
6098
6099    /**
6100     * When the screen is off we ignore some keys that might otherwise typically
6101     * be considered wake keys.  We filter them out here.
6102     *
6103     * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
6104     * is always considered a wake key.
6105     */
6106    private boolean isWakeKeyWhenScreenOff(int keyCode) {
6107        switch (keyCode) {
6108            // ignore volume keys unless docked
6109            case KeyEvent.KEYCODE_VOLUME_UP:
6110            case KeyEvent.KEYCODE_VOLUME_DOWN:
6111            case KeyEvent.KEYCODE_VOLUME_MUTE:
6112                return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
6113
6114            // ignore media and camera keys
6115            case KeyEvent.KEYCODE_MUTE:
6116            case KeyEvent.KEYCODE_HEADSETHOOK:
6117            case KeyEvent.KEYCODE_MEDIA_PLAY:
6118            case KeyEvent.KEYCODE_MEDIA_PAUSE:
6119            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6120            case KeyEvent.KEYCODE_MEDIA_STOP:
6121            case KeyEvent.KEYCODE_MEDIA_NEXT:
6122            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6123            case KeyEvent.KEYCODE_MEDIA_REWIND:
6124            case KeyEvent.KEYCODE_MEDIA_RECORD:
6125            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6126            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
6127            case KeyEvent.KEYCODE_CAMERA:
6128                return false;
6129        }
6130        return true;
6131    }
6132
6133
6134    /** {@inheritDoc} */
6135    @Override
6136    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
6137        if ((policyFlags & FLAG_WAKE) != 0) {
6138            if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
6139                    "android.policy:MOTION")) {
6140                return 0;
6141            }
6142        }
6143
6144        if (shouldDispatchInputWhenNonInteractive(null)) {
6145            return ACTION_PASS_TO_USER;
6146        }
6147
6148        // If we have not passed the action up and we are in theater mode without dreaming,
6149        // there will be no dream to intercept the touch and wake into ambient.  The device should
6150        // wake up in this case.
6151        if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
6152            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
6153                    "android.policy:MOTION");
6154        }
6155
6156        return 0;
6157    }
6158
6159    private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
6160        final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
6161
6162        if (displayOff && !mHasFeatureWatch) {
6163            return false;
6164        }
6165
6166        // Send events to keyguard while the screen is on and it's showing.
6167        if (isKeyguardShowingAndNotOccluded() && !displayOff) {
6168            return true;
6169        }
6170
6171        // Watches handle BACK specially
6172        if (mHasFeatureWatch
6173                && event != null
6174                && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
6175                        || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
6176            return false;
6177        }
6178
6179        // Send events to a dozing dream even if the screen is off since the dream
6180        // is in control of the state of the screen.
6181        IDreamManager dreamManager = getDreamManager();
6182
6183        try {
6184            if (dreamManager != null && dreamManager.isDreaming()) {
6185                return true;
6186            }
6187        } catch (RemoteException e) {
6188            Slog.e(TAG, "RemoteException when checking if dreaming", e);
6189        }
6190
6191        // Otherwise, consume events since the user can't see what is being
6192        // interacted with.
6193        return false;
6194    }
6195
6196    private void dispatchDirectAudioEvent(KeyEvent event) {
6197        if (event.getAction() != KeyEvent.ACTION_DOWN) {
6198            return;
6199        }
6200        int keyCode = event.getKeyCode();
6201        int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
6202                | AudioManager.FLAG_FROM_KEY;
6203        String pkgName = mContext.getOpPackageName();
6204        switch (keyCode) {
6205            case KeyEvent.KEYCODE_VOLUME_UP:
6206                try {
6207                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
6208                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6209                } catch (RemoteException e) {
6210                    Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
6211                }
6212                break;
6213            case KeyEvent.KEYCODE_VOLUME_DOWN:
6214                try {
6215                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
6216                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6217                } catch (RemoteException e) {
6218                    Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
6219                }
6220                break;
6221            case KeyEvent.KEYCODE_VOLUME_MUTE:
6222                try {
6223                    if (event.getRepeatCount() == 0) {
6224                        getAudioService().adjustSuggestedStreamVolume(
6225                                AudioManager.ADJUST_TOGGLE_MUTE,
6226                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6227                    }
6228                } catch (RemoteException e) {
6229                    Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
6230                }
6231                break;
6232        }
6233    }
6234
6235    void dispatchMediaKeyWithWakeLock(KeyEvent event) {
6236        if (DEBUG_INPUT) {
6237            Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
6238        }
6239
6240        if (mHavePendingMediaKeyRepeatWithWakeLock) {
6241            if (DEBUG_INPUT) {
6242                Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
6243            }
6244
6245            mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
6246            mHavePendingMediaKeyRepeatWithWakeLock = false;
6247            mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
6248        }
6249
6250        dispatchMediaKeyWithWakeLockToAudioService(event);
6251
6252        if (event.getAction() == KeyEvent.ACTION_DOWN
6253                && event.getRepeatCount() == 0) {
6254            mHavePendingMediaKeyRepeatWithWakeLock = true;
6255
6256            Message msg = mHandler.obtainMessage(
6257                    MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
6258            msg.setAsynchronous(true);
6259            mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
6260        } else {
6261            mBroadcastWakeLock.release();
6262        }
6263    }
6264
6265    void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
6266        mHavePendingMediaKeyRepeatWithWakeLock = false;
6267
6268        KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
6269                SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6270        if (DEBUG_INPUT) {
6271            Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
6272        }
6273
6274        dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
6275        mBroadcastWakeLock.release();
6276    }
6277
6278    void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
6279        if (ActivityManagerNative.isSystemReady()) {
6280            MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
6281        }
6282    }
6283
6284    void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
6285        IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
6286                ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
6287        if (dic != null) {
6288            try {
6289                dic.exitIdle("voice-search");
6290            } catch (RemoteException e) {
6291            }
6292        }
6293        Intent voiceIntent =
6294            new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
6295        voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
6296        startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
6297        mBroadcastWakeLock.release();
6298    }
6299
6300    BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
6301        @Override
6302        public void onReceive(Context context, Intent intent) {
6303            if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
6304                mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6305                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
6306            } else {
6307                try {
6308                    IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
6309                            ServiceManager.getService(Context.UI_MODE_SERVICE));
6310                    mUiMode = uiModeService.getCurrentModeType();
6311                } catch (RemoteException e) {
6312                }
6313            }
6314            updateRotation(true);
6315            synchronized (mLock) {
6316                updateOrientationListenerLp();
6317            }
6318        }
6319    };
6320
6321    BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
6322        @Override
6323        public void onReceive(Context context, Intent intent) {
6324            if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
6325                if (mKeyguardDelegate != null) {
6326                    mKeyguardDelegate.onDreamingStarted();
6327                }
6328            } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
6329                if (mKeyguardDelegate != null) {
6330                    mKeyguardDelegate.onDreamingStopped();
6331                }
6332            }
6333        }
6334    };
6335
6336    BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
6337        @Override
6338        public void onReceive(Context context, Intent intent) {
6339            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
6340                // tickle the settings observer: this first ensures that we're
6341                // observing the relevant settings for the newly-active user,
6342                // and then updates our own bookkeeping based on the now-
6343                // current user.
6344                mSettingsObserver.onChange(false);
6345
6346                // force a re-application of focused window sysui visibility.
6347                // the window may never have been shown for this user
6348                // e.g. the keyguard when going through the new-user setup flow
6349                synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6350                    mLastSystemUiFlags = 0;
6351                    updateSystemUiVisibilityLw();
6352                }
6353            }
6354        }
6355    };
6356
6357    private final Runnable mHiddenNavPanic = new Runnable() {
6358        @Override
6359        public void run() {
6360            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6361                if (!isUserSetupComplete()) {
6362                    // Swipe-up for navigation bar is disabled during setup
6363                    return;
6364                }
6365                mPendingPanicGestureUptime = SystemClock.uptimeMillis();
6366                if (!isNavBarEmpty(mLastSystemUiFlags)) {
6367                    mNavigationBarController.showTransient();
6368                }
6369            }
6370        }
6371    };
6372
6373    private void requestTransientBars(WindowState swipeTarget) {
6374        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6375            if (!isUserSetupComplete()) {
6376                // Swipe-up for navigation bar is disabled during setup
6377                return;
6378            }
6379            boolean sb = mStatusBarController.checkShowTransientBarLw();
6380            boolean nb = mNavigationBarController.checkShowTransientBarLw()
6381                    && !isNavBarEmpty(mLastSystemUiFlags);
6382            if (sb || nb) {
6383                // Don't show status bar when swiping on already visible navigation bar
6384                if (!nb && swipeTarget == mNavigationBar) {
6385                    if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
6386                    return;
6387                }
6388                if (sb) mStatusBarController.showTransient();
6389                if (nb) mNavigationBarController.showTransient();
6390                mImmersiveModeConfirmation.confirmCurrentPrompt();
6391                updateSystemUiVisibilityLw();
6392            }
6393        }
6394    }
6395
6396    // Called on the PowerManager's Notifier thread.
6397    @Override
6398    public void startedGoingToSleep(int why) {
6399        if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
6400        mCameraGestureTriggeredDuringGoingToSleep = false;
6401        mGoingToSleep = true;
6402        if (mKeyguardDelegate != null) {
6403            mKeyguardDelegate.onStartedGoingToSleep(why);
6404        }
6405    }
6406
6407    // Called on the PowerManager's Notifier thread.
6408    @Override
6409    public void finishedGoingToSleep(int why) {
6410        EventLog.writeEvent(70000, 0);
6411        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
6412        MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
6413
6414        mGoingToSleep = false;
6415
6416        // We must get this work done here because the power manager will drop
6417        // the wake lock and let the system suspend once this function returns.
6418        synchronized (mLock) {
6419            mAwake = false;
6420            updateWakeGestureListenerLp();
6421            updateOrientationListenerLp();
6422            updateLockScreenTimeout();
6423        }
6424        if (mKeyguardDelegate != null) {
6425            mKeyguardDelegate.onFinishedGoingToSleep(why,
6426                    mCameraGestureTriggeredDuringGoingToSleep);
6427        }
6428        mCameraGestureTriggeredDuringGoingToSleep = false;
6429    }
6430
6431    // Called on the PowerManager's Notifier thread.
6432    @Override
6433    public void startedWakingUp() {
6434        EventLog.writeEvent(70000, 1);
6435        if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
6436
6437        // Since goToSleep performs these functions synchronously, we must
6438        // do the same here.  We cannot post this work to a handler because
6439        // that might cause it to become reordered with respect to what
6440        // may happen in a future call to goToSleep.
6441        synchronized (mLock) {
6442            mAwake = true;
6443
6444            updateWakeGestureListenerLp();
6445            updateOrientationListenerLp();
6446            updateLockScreenTimeout();
6447        }
6448
6449        if (mKeyguardDelegate != null) {
6450            mKeyguardDelegate.onStartedWakingUp();
6451        }
6452    }
6453
6454    // Called on the PowerManager's Notifier thread.
6455    @Override
6456    public void finishedWakingUp() {
6457        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
6458    }
6459
6460    private void wakeUpFromPowerKey(long eventTime) {
6461        wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
6462    }
6463
6464    private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
6465        final boolean theaterModeEnabled = isTheaterModeEnabled();
6466        if (!wakeInTheaterMode && theaterModeEnabled) {
6467            return false;
6468        }
6469
6470        if (theaterModeEnabled) {
6471            Settings.Global.putInt(mContext.getContentResolver(),
6472                    Settings.Global.THEATER_MODE_ON, 0);
6473        }
6474
6475        mPowerManager.wakeUp(wakeTime, reason);
6476        return true;
6477    }
6478
6479    private void finishKeyguardDrawn() {
6480        synchronized (mLock) {
6481            if (!mScreenOnEarly || mKeyguardDrawComplete) {
6482                return; // We are not awake yet or we have already informed of this event.
6483            }
6484
6485            mKeyguardDrawComplete = true;
6486            if (mKeyguardDelegate != null) {
6487                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6488            }
6489            mWindowManagerDrawComplete = false;
6490        }
6491
6492        // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
6493        // as well as enabling the orientation change logic/sensor.
6494        mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
6495                WAITING_FOR_DRAWN_TIMEOUT);
6496    }
6497
6498    // Called on the DisplayManager's DisplayPowerController thread.
6499    @Override
6500    public void screenTurnedOff() {
6501        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
6502
6503        updateScreenOffSleepToken(true);
6504        synchronized (mLock) {
6505            mScreenOnEarly = false;
6506            mScreenOnFully = false;
6507            mKeyguardDrawComplete = false;
6508            mWindowManagerDrawComplete = false;
6509            mScreenOnListener = null;
6510            updateOrientationListenerLp();
6511
6512            if (mKeyguardDelegate != null) {
6513                mKeyguardDelegate.onScreenTurnedOff();
6514            }
6515        }
6516    }
6517
6518    // Called on the DisplayManager's DisplayPowerController thread.
6519    @Override
6520    public void screenTurningOn(final ScreenOnListener screenOnListener) {
6521        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
6522
6523        updateScreenOffSleepToken(false);
6524        synchronized (mLock) {
6525            mScreenOnEarly = true;
6526            mScreenOnFully = false;
6527            mKeyguardDrawComplete = false;
6528            mWindowManagerDrawComplete = false;
6529            mScreenOnListener = screenOnListener;
6530
6531            if (mKeyguardDelegate != null) {
6532                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6533                mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
6534                mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
6535            } else {
6536                if (DEBUG_WAKEUP) Slog.d(TAG,
6537                        "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
6538                finishKeyguardDrawn();
6539            }
6540        }
6541    }
6542
6543    // Called on the DisplayManager's DisplayPowerController thread.
6544    @Override
6545    public void screenTurnedOn() {
6546        synchronized (mLock) {
6547            if (mKeyguardDelegate != null) {
6548                mKeyguardDelegate.onScreenTurnedOn();
6549            }
6550        }
6551    }
6552
6553    private void finishWindowsDrawn() {
6554        synchronized (mLock) {
6555            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
6556                return; // Screen is not turned on or we did already handle this case earlier.
6557            }
6558
6559            mWindowManagerDrawComplete = true;
6560        }
6561
6562        finishScreenTurningOn();
6563    }
6564
6565    private void finishScreenTurningOn() {
6566        synchronized (mLock) {
6567            // We have just finished drawing screen content. Since the orientation listener
6568            // gets only installed when all windows are drawn, we try to install it again.
6569            updateOrientationListenerLp();
6570        }
6571        final ScreenOnListener listener;
6572        final boolean enableScreen;
6573        synchronized (mLock) {
6574            if (DEBUG_WAKEUP) Slog.d(TAG,
6575                    "finishScreenTurningOn: mAwake=" + mAwake
6576                            + ", mScreenOnEarly=" + mScreenOnEarly
6577                            + ", mScreenOnFully=" + mScreenOnFully
6578                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
6579                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
6580
6581            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
6582                    || (mAwake && !mKeyguardDrawComplete)) {
6583                return; // spurious or not ready yet
6584            }
6585
6586            if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
6587            listener = mScreenOnListener;
6588            mScreenOnListener = null;
6589            mScreenOnFully = true;
6590
6591            // Remember the first time we draw the keyguard so we know when we're done with
6592            // the main part of booting and can enable the screen and hide boot messages.
6593            if (!mKeyguardDrawnOnce && mAwake) {
6594                mKeyguardDrawnOnce = true;
6595                enableScreen = true;
6596                if (mBootMessageNeedsHiding) {
6597                    mBootMessageNeedsHiding = false;
6598                    hideBootMessages();
6599                }
6600            } else {
6601                enableScreen = false;
6602            }
6603        }
6604
6605        if (listener != null) {
6606            listener.onScreenOn();
6607        }
6608
6609        if (enableScreen) {
6610            try {
6611                mWindowManager.enableScreenIfNeeded();
6612            } catch (RemoteException unhandled) {
6613            }
6614        }
6615    }
6616
6617    private void handleHideBootMessage() {
6618        synchronized (mLock) {
6619            if (!mKeyguardDrawnOnce) {
6620                mBootMessageNeedsHiding = true;
6621                return; // keyguard hasn't drawn the first time yet, not done booting
6622            }
6623        }
6624
6625        if (mBootMsgDialog != null) {
6626            if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
6627            mBootMsgDialog.dismiss();
6628            mBootMsgDialog = null;
6629        }
6630    }
6631
6632    @Override
6633    public boolean isScreenOn() {
6634        return mScreenOnFully;
6635    }
6636
6637    /** {@inheritDoc} */
6638    @Override
6639    public void enableKeyguard(boolean enabled) {
6640        if (mKeyguardDelegate != null) {
6641            mKeyguardDelegate.setKeyguardEnabled(enabled);
6642        }
6643    }
6644
6645    /** {@inheritDoc} */
6646    @Override
6647    public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
6648        if (mKeyguardDelegate != null) {
6649            mKeyguardDelegate.verifyUnlock(callback);
6650        }
6651    }
6652
6653    private boolean isKeyguardShowingAndNotOccluded() {
6654        if (mKeyguardDelegate == null) return false;
6655        return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
6656    }
6657
6658    /** {@inheritDoc} */
6659    @Override
6660    public boolean isKeyguardLocked() {
6661        return keyguardOn();
6662    }
6663
6664    /** {@inheritDoc} */
6665    @Override
6666    public boolean isKeyguardSecure(int userId) {
6667        if (mKeyguardDelegate == null) return false;
6668        return mKeyguardDelegate.isSecure(userId);
6669    }
6670
6671    /** {@inheritDoc} */
6672    @Override
6673    public boolean isKeyguardShowingOrOccluded() {
6674        return mKeyguardDelegate == null ? false : mKeyguardDelegate.isShowing();
6675    }
6676
6677    /** {@inheritDoc} */
6678    @Override
6679    public boolean inKeyguardRestrictedKeyInputMode() {
6680        if (mKeyguardDelegate == null) return false;
6681        return mKeyguardDelegate.isInputRestricted();
6682    }
6683
6684    @Override
6685    public void dismissKeyguardLw() {
6686        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
6687            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
6688            mHandler.post(new Runnable() {
6689                @Override
6690                public void run() {
6691                    // ask the keyguard to prompt the user to authenticate if necessary
6692                    mKeyguardDelegate.dismiss(false /* allowWhileOccluded */);
6693                }
6694            });
6695        }
6696    }
6697
6698    @Override
6699    public void notifyActivityDrawnForKeyguardLw() {
6700        if (mKeyguardDelegate != null) {
6701            mHandler.post(new Runnable() {
6702                @Override
6703                public void run() {
6704                    mKeyguardDelegate.onActivityDrawn();
6705                }
6706            });
6707        }
6708    }
6709
6710    @Override
6711    public boolean isKeyguardDrawnLw() {
6712        synchronized (mLock) {
6713            return mKeyguardDrawnOnce;
6714        }
6715    }
6716
6717    @Override
6718    public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
6719        if (mKeyguardDelegate != null) {
6720            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
6721            mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
6722        }
6723    }
6724
6725    @Override
6726    public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6727            Rect outInsets) {
6728        outInsets.setEmpty();
6729
6730        // Navigation bar and status bar.
6731        getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
6732        if (mStatusBar != null) {
6733            outInsets.top = mStatusBarHeight;
6734        }
6735    }
6736
6737    @Override
6738    public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6739            Rect outInsets) {
6740        outInsets.setEmpty();
6741
6742        // Only navigation bar
6743        if (mNavigationBar != null) {
6744            int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
6745            if (position == NAV_BAR_BOTTOM) {
6746                outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
6747            } else if (position == NAV_BAR_RIGHT) {
6748                outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
6749            } else if (position == NAV_BAR_LEFT) {
6750                outInsets.left = getNavigationBarWidth(displayRotation, mUiMode);
6751            }
6752        }
6753    }
6754
6755    @Override
6756    public boolean isNavBarForcedShownLw(WindowState windowState) {
6757        return mForceShowSystemBars;
6758    }
6759
6760    @Override
6761    public boolean isDockSideAllowed(int dockSide) {
6762
6763        // We do not allow all dock sides at which the navigation bar touches the docked stack.
6764        if (!mNavigationBarCanMove) {
6765            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT;
6766        } else {
6767            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT;
6768        }
6769    }
6770
6771    void sendCloseSystemWindows() {
6772        PhoneWindow.sendCloseSystemWindows(mContext, null);
6773    }
6774
6775    void sendCloseSystemWindows(String reason) {
6776        PhoneWindow.sendCloseSystemWindows(mContext, reason);
6777    }
6778
6779    @Override
6780    public int rotationForOrientationLw(int orientation, int lastRotation) {
6781        if (false) {
6782            Slog.v(TAG, "rotationForOrientationLw(orient="
6783                        + orientation + ", last=" + lastRotation
6784                        + "); user=" + mUserRotation + " "
6785                        + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
6786                            ? "USER_ROTATION_LOCKED" : "")
6787                        );
6788        }
6789
6790        if (mForceDefaultOrientation) {
6791            return Surface.ROTATION_0;
6792        }
6793
6794        synchronized (mLock) {
6795            int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
6796            if (sensorRotation < 0) {
6797                sensorRotation = lastRotation;
6798            }
6799
6800            final int preferredRotation;
6801            if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
6802                // Ignore sensor when lid switch is open and rotation is forced.
6803                preferredRotation = mLidOpenRotation;
6804            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
6805                    && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
6806                // Ignore sensor when in car dock unless explicitly enabled.
6807                // This case can override the behavior of NOSENSOR, and can also
6808                // enable 180 degree rotation while docked.
6809                preferredRotation = mCarDockEnablesAccelerometer
6810                        ? sensorRotation : mCarDockRotation;
6811            } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
6812                    || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
6813                    || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
6814                    && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
6815                // Ignore sensor when in desk dock unless explicitly enabled.
6816                // This case can override the behavior of NOSENSOR, and can also
6817                // enable 180 degree rotation while docked.
6818                preferredRotation = mDeskDockEnablesAccelerometer
6819                        ? sensorRotation : mDeskDockRotation;
6820            } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
6821                // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
6822                // Note that the dock orientation overrides the HDMI orientation.
6823                preferredRotation = mDemoHdmiRotation;
6824            } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
6825                    && mUndockedHdmiRotation >= 0) {
6826                // Ignore sensor when plugged into HDMI and an undocked orientation has
6827                // been specified in the configuration (only for legacy devices without
6828                // full multi-display support).
6829                // Note that the dock orientation overrides the HDMI orientation.
6830                preferredRotation = mUndockedHdmiRotation;
6831            } else if (mDemoRotationLock) {
6832                // Ignore sensor when demo rotation lock is enabled.
6833                // Note that the dock orientation and HDMI rotation lock override this.
6834                preferredRotation = mDemoRotation;
6835            } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
6836                // Application just wants to remain locked in the last rotation.
6837                preferredRotation = lastRotation;
6838            } else if (!mSupportAutoRotation) {
6839                // If we don't support auto-rotation then bail out here and ignore
6840                // the sensor and any rotation lock settings.
6841                preferredRotation = -1;
6842            } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
6843                            && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
6844                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
6845                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
6846                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
6847                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
6848                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
6849                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6850                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
6851                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
6852                // Otherwise, use sensor only if requested by the application or enabled
6853                // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
6854                if (mAllowAllRotations < 0) {
6855                    // Can't read this during init() because the context doesn't
6856                    // have display metrics at that time so we cannot determine
6857                    // tablet vs. phone then.
6858                    mAllowAllRotations = mContext.getResources().getBoolean(
6859                            com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
6860                }
6861                if (sensorRotation != Surface.ROTATION_180
6862                        || mAllowAllRotations == 1
6863                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6864                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
6865                    preferredRotation = sensorRotation;
6866                } else {
6867                    preferredRotation = lastRotation;
6868                }
6869            } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
6870                    && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
6871                // Apply rotation lock.  Does not apply to NOSENSOR.
6872                // The idea is that the user rotation expresses a weak preference for the direction
6873                // of gravity and as NOSENSOR is never affected by gravity, then neither should
6874                // NOSENSOR be affected by rotation lock (although it will be affected by docks).
6875                preferredRotation = mUserRotation;
6876            } else {
6877                // No overriding preference.
6878                // We will do exactly what the application asked us to do.
6879                preferredRotation = -1;
6880            }
6881
6882            switch (orientation) {
6883                case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6884                    // Return portrait unless overridden.
6885                    if (isAnyPortrait(preferredRotation)) {
6886                        return preferredRotation;
6887                    }
6888                    return mPortraitRotation;
6889
6890                case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6891                    // Return landscape unless overridden.
6892                    if (isLandscapeOrSeascape(preferredRotation)) {
6893                        return preferredRotation;
6894                    }
6895                    return mLandscapeRotation;
6896
6897                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6898                    // Return reverse portrait unless overridden.
6899                    if (isAnyPortrait(preferredRotation)) {
6900                        return preferredRotation;
6901                    }
6902                    return mUpsideDownRotation;
6903
6904                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6905                    // Return seascape unless overridden.
6906                    if (isLandscapeOrSeascape(preferredRotation)) {
6907                        return preferredRotation;
6908                    }
6909                    return mSeascapeRotation;
6910
6911                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6912                case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
6913                    // Return either landscape rotation.
6914                    if (isLandscapeOrSeascape(preferredRotation)) {
6915                        return preferredRotation;
6916                    }
6917                    if (isLandscapeOrSeascape(lastRotation)) {
6918                        return lastRotation;
6919                    }
6920                    return mLandscapeRotation;
6921
6922                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6923                case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
6924                    // Return either portrait rotation.
6925                    if (isAnyPortrait(preferredRotation)) {
6926                        return preferredRotation;
6927                    }
6928                    if (isAnyPortrait(lastRotation)) {
6929                        return lastRotation;
6930                    }
6931                    return mPortraitRotation;
6932
6933                default:
6934                    // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
6935                    // just return the preferred orientation we already calculated.
6936                    if (preferredRotation >= 0) {
6937                        return preferredRotation;
6938                    }
6939                    return Surface.ROTATION_0;
6940            }
6941        }
6942    }
6943
6944    @Override
6945    public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
6946        switch (orientation) {
6947            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6948            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6949            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6950                return isAnyPortrait(rotation);
6951
6952            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6953            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6954            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6955                return isLandscapeOrSeascape(rotation);
6956
6957            default:
6958                return true;
6959        }
6960    }
6961
6962    @Override
6963    public void setRotationLw(int rotation) {
6964        mOrientationListener.setCurrentRotation(rotation);
6965    }
6966
6967    private boolean isLandscapeOrSeascape(int rotation) {
6968        return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
6969    }
6970
6971    private boolean isAnyPortrait(int rotation) {
6972        return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
6973    }
6974
6975    @Override
6976    public int getUserRotationMode() {
6977        return Settings.System.getIntForUser(mContext.getContentResolver(),
6978                Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
6979                        WindowManagerPolicy.USER_ROTATION_FREE :
6980                                WindowManagerPolicy.USER_ROTATION_LOCKED;
6981    }
6982
6983    // User rotation: to be used when all else fails in assigning an orientation to the device
6984    @Override
6985    public void setUserRotationMode(int mode, int rot) {
6986        ContentResolver res = mContext.getContentResolver();
6987
6988        // mUserRotationMode and mUserRotation will be assigned by the content observer
6989        if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
6990            Settings.System.putIntForUser(res,
6991                    Settings.System.USER_ROTATION,
6992                    rot,
6993                    UserHandle.USER_CURRENT);
6994            Settings.System.putIntForUser(res,
6995                    Settings.System.ACCELEROMETER_ROTATION,
6996                    0,
6997                    UserHandle.USER_CURRENT);
6998        } else {
6999            Settings.System.putIntForUser(res,
7000                    Settings.System.ACCELEROMETER_ROTATION,
7001                    1,
7002                    UserHandle.USER_CURRENT);
7003        }
7004    }
7005
7006    @Override
7007    public void setSafeMode(boolean safeMode) {
7008        mSafeMode = safeMode;
7009        performHapticFeedbackLw(null, safeMode
7010                ? HapticFeedbackConstants.SAFE_MODE_ENABLED
7011                : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
7012    }
7013
7014    static long[] getLongIntArray(Resources r, int resid) {
7015        int[] ar = r.getIntArray(resid);
7016        if (ar == null) {
7017            return null;
7018        }
7019        long[] out = new long[ar.length];
7020        for (int i=0; i<ar.length; i++) {
7021            out[i] = ar[i];
7022        }
7023        return out;
7024    }
7025
7026    /** {@inheritDoc} */
7027    @Override
7028    public void systemReady() {
7029        mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
7030                this::onKeyguardShowingStateChanged);
7031        mKeyguardDelegate.onSystemReady();
7032
7033        readCameraLensCoverState();
7034        updateUiMode();
7035        boolean bindKeyguardNow;
7036        synchronized (mLock) {
7037            updateOrientationListenerLp();
7038            mSystemReady = true;
7039            mHandler.post(new Runnable() {
7040                @Override
7041                public void run() {
7042                    updateSettings();
7043                }
7044            });
7045
7046            bindKeyguardNow = mDeferBindKeyguard;
7047            if (bindKeyguardNow) {
7048                // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now.
7049                mDeferBindKeyguard = false;
7050            }
7051        }
7052
7053        if (bindKeyguardNow) {
7054            mKeyguardDelegate.bindService(mContext);
7055            mKeyguardDelegate.onBootCompleted();
7056        }
7057        mSystemGestures.systemReady();
7058        mImmersiveModeConfirmation.systemReady();
7059    }
7060
7061    /** {@inheritDoc} */
7062    @Override
7063    public void systemBooted() {
7064        boolean bindKeyguardNow = false;
7065        synchronized (mLock) {
7066            // Time to bind Keyguard; take care to only bind it once, either here if ready or
7067            // in systemReady if not.
7068            if (mKeyguardDelegate != null) {
7069                bindKeyguardNow = true;
7070            } else {
7071                // Because mKeyguardDelegate is null, we know that the synchronized block in
7072                // systemReady didn't run yet and setting this will actually have an effect.
7073                mDeferBindKeyguard = true;
7074            }
7075        }
7076        if (bindKeyguardNow) {
7077            mKeyguardDelegate.bindService(mContext);
7078            mKeyguardDelegate.onBootCompleted();
7079        }
7080        synchronized (mLock) {
7081            mSystemBooted = true;
7082        }
7083        startedWakingUp();
7084        screenTurningOn(null);
7085        screenTurnedOn();
7086    }
7087
7088    ProgressDialog mBootMsgDialog = null;
7089
7090    /** {@inheritDoc} */
7091    @Override
7092    public void showBootMessage(final CharSequence msg, final boolean always) {
7093        mHandler.post(new Runnable() {
7094            @Override public void run() {
7095                if (mBootMsgDialog == null) {
7096                    int theme;
7097                    if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) {
7098                        theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
7099                    } else {
7100                        theme = 0;
7101                    }
7102
7103                    mBootMsgDialog = new ProgressDialog(mContext, theme) {
7104                        // This dialog will consume all events coming in to
7105                        // it, to avoid it trying to do things too early in boot.
7106                        @Override public boolean dispatchKeyEvent(KeyEvent event) {
7107                            return true;
7108                        }
7109                        @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7110                            return true;
7111                        }
7112                        @Override public boolean dispatchTouchEvent(MotionEvent ev) {
7113                            return true;
7114                        }
7115                        @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
7116                            return true;
7117                        }
7118                        @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
7119                            return true;
7120                        }
7121                        @Override public boolean dispatchPopulateAccessibilityEvent(
7122                                AccessibilityEvent event) {
7123                            return true;
7124                        }
7125                    };
7126                    if (mContext.getPackageManager().isUpgrade()) {
7127                        mBootMsgDialog.setTitle(R.string.android_upgrading_title);
7128                    } else {
7129                        mBootMsgDialog.setTitle(R.string.android_start_title);
7130                    }
7131                    mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
7132                    mBootMsgDialog.setIndeterminate(true);
7133                    mBootMsgDialog.getWindow().setType(
7134                            WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
7135                    mBootMsgDialog.getWindow().addFlags(
7136                            WindowManager.LayoutParams.FLAG_DIM_BEHIND
7137                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
7138                    mBootMsgDialog.getWindow().setDimAmount(1);
7139                    WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
7140                    lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
7141                    mBootMsgDialog.getWindow().setAttributes(lp);
7142                    mBootMsgDialog.setCancelable(false);
7143                    mBootMsgDialog.show();
7144                }
7145                mBootMsgDialog.setMessage(msg);
7146            }
7147        });
7148    }
7149
7150    /** {@inheritDoc} */
7151    @Override
7152    public void hideBootMessages() {
7153        mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
7154    }
7155
7156    /** {@inheritDoc} */
7157    @Override
7158    public void userActivity() {
7159        // ***************************************
7160        // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
7161        // ***************************************
7162        // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
7163        // WITH ITS LOCKS HELD.
7164        //
7165        // This code must be VERY careful about the locks
7166        // it acquires.
7167        // In fact, the current code acquires way too many,
7168        // and probably has lurking deadlocks.
7169
7170        synchronized (mScreenLockTimeout) {
7171            if (mLockScreenTimerActive) {
7172                // reset the timer
7173                mHandler.removeCallbacks(mScreenLockTimeout);
7174                mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7175            }
7176        }
7177    }
7178
7179    class ScreenLockTimeout implements Runnable {
7180        Bundle options;
7181
7182        @Override
7183        public void run() {
7184            synchronized (this) {
7185                if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
7186                if (mKeyguardDelegate != null) {
7187                    mKeyguardDelegate.doKeyguardTimeout(options);
7188                }
7189                mLockScreenTimerActive = false;
7190                options = null;
7191            }
7192        }
7193
7194        public void setLockOptions(Bundle options) {
7195            this.options = options;
7196        }
7197    }
7198
7199    ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
7200
7201    @Override
7202    public void lockNow(Bundle options) {
7203        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
7204        mHandler.removeCallbacks(mScreenLockTimeout);
7205        if (options != null) {
7206            // In case multiple calls are made to lockNow, we don't wipe out the options
7207            // until the runnable actually executes.
7208            mScreenLockTimeout.setLockOptions(options);
7209        }
7210        mHandler.post(mScreenLockTimeout);
7211    }
7212
7213    private void updateLockScreenTimeout() {
7214        synchronized (mScreenLockTimeout) {
7215            boolean enable = (mAllowLockscreenWhenOn && mAwake &&
7216                    mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
7217            if (mLockScreenTimerActive != enable) {
7218                if (enable) {
7219                    if (localLOGV) Log.v(TAG, "setting lockscreen timer");
7220                    mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
7221                    mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7222                } else {
7223                    if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
7224                    mHandler.removeCallbacks(mScreenLockTimeout);
7225                }
7226                mLockScreenTimerActive = enable;
7227            }
7228        }
7229    }
7230
7231    private void updateDreamingSleepToken(boolean acquire) {
7232        if (acquire) {
7233            if (mDreamingSleepToken == null) {
7234                mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream");
7235            }
7236        } else {
7237            if (mDreamingSleepToken != null) {
7238                mDreamingSleepToken.release();
7239                mDreamingSleepToken = null;
7240            }
7241        }
7242    }
7243
7244    private void updateScreenOffSleepToken(boolean acquire) {
7245        if (acquire) {
7246            if (mScreenOffSleepToken == null) {
7247                mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff");
7248            }
7249        } else {
7250            if (mScreenOffSleepToken != null) {
7251                mScreenOffSleepToken.release();
7252                mScreenOffSleepToken = null;
7253            }
7254        }
7255    }
7256
7257    /** {@inheritDoc} */
7258    @Override
7259    public void enableScreenAfterBoot() {
7260        readLidState();
7261        applyLidSwitchState();
7262        updateRotation(true);
7263    }
7264
7265    private void applyLidSwitchState() {
7266        if (mLidState == LID_CLOSED && mLidControlsSleep) {
7267            mPowerManager.goToSleep(SystemClock.uptimeMillis(),
7268                    PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
7269                    PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
7270        } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
7271            mWindowManagerFuncs.lockDeviceNow();
7272        }
7273
7274        synchronized (mLock) {
7275            updateWakeGestureListenerLp();
7276        }
7277    }
7278
7279    void updateUiMode() {
7280        if (mUiModeManager == null) {
7281            mUiModeManager = IUiModeManager.Stub.asInterface(
7282                    ServiceManager.getService(Context.UI_MODE_SERVICE));
7283        }
7284        try {
7285            mUiMode = mUiModeManager.getCurrentModeType();
7286        } catch (RemoteException e) {
7287        }
7288    }
7289
7290    void updateRotation(boolean alwaysSendConfiguration) {
7291        try {
7292            //set orientation on WindowManager
7293            mWindowManager.updateRotation(alwaysSendConfiguration, false);
7294        } catch (RemoteException e) {
7295            // Ignore
7296        }
7297    }
7298
7299    void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
7300        try {
7301            //set orientation on WindowManager
7302            mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
7303        } catch (RemoteException e) {
7304            // Ignore
7305        }
7306    }
7307
7308    /**
7309     * Return an Intent to launch the currently active dock app as home.  Returns
7310     * null if the standard home should be launched, which is the case if any of the following is
7311     * true:
7312     * <ul>
7313     *  <li>The device is not in either car mode or desk mode
7314     *  <li>The device is in car mode but mEnableCarDockHomeCapture is false
7315     *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
7316     *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
7317     *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
7318     * </ul>
7319     * @return A dock intent.
7320     */
7321    Intent createHomeDockIntent() {
7322        Intent intent = null;
7323
7324        // What home does is based on the mode, not the dock state.  That
7325        // is, when in car mode you should be taken to car home regardless
7326        // of whether we are actually in a car dock.
7327        if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
7328            if (mEnableCarDockHomeCapture) {
7329                intent = mCarDockIntent;
7330            }
7331        } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
7332            if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
7333                intent = mDeskDockIntent;
7334            }
7335        } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
7336                && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7337                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
7338                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
7339            // Always launch dock home from home when watch is docked, if it exists.
7340            intent = mDeskDockIntent;
7341        }
7342
7343        if (intent == null) {
7344            return null;
7345        }
7346
7347        ActivityInfo ai = null;
7348        ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
7349                intent,
7350                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
7351                mCurrentUserId);
7352        if (info != null) {
7353            ai = info.activityInfo;
7354        }
7355        if (ai != null
7356                && ai.metaData != null
7357                && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
7358            intent = new Intent(intent);
7359            intent.setClassName(ai.packageName, ai.name);
7360            return intent;
7361        }
7362
7363        return null;
7364    }
7365
7366    void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
7367        if (awakenFromDreams) {
7368            awakenDreams();
7369        }
7370
7371        Intent dock = createHomeDockIntent();
7372        if (dock != null) {
7373            try {
7374                if (fromHomeKey) {
7375                    dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7376                }
7377                startActivityAsUser(dock, UserHandle.CURRENT);
7378                return;
7379            } catch (ActivityNotFoundException e) {
7380            }
7381        }
7382
7383        Intent intent;
7384
7385        if (fromHomeKey) {
7386            intent = new Intent(mHomeIntent);
7387            intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7388        } else {
7389            intent = mHomeIntent;
7390        }
7391
7392        startActivityAsUser(intent, UserHandle.CURRENT);
7393    }
7394
7395    /**
7396     * goes to the home screen
7397     * @return whether it did anything
7398     */
7399    boolean goHome() {
7400        if (!isUserSetupComplete()) {
7401            Slog.i(TAG, "Not going home because user setup is in progress.");
7402            return false;
7403        }
7404        if (false) {
7405            // This code always brings home to the front.
7406            try {
7407                ActivityManagerNative.getDefault().stopAppSwitches();
7408            } catch (RemoteException e) {
7409            }
7410            sendCloseSystemWindows();
7411            startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
7412        } else {
7413            // This code brings home to the front or, if it is already
7414            // at the front, puts the device to sleep.
7415            try {
7416                if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
7417                    /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
7418                    Log.d(TAG, "UTS-TEST-MODE");
7419                } else {
7420                    ActivityManagerNative.getDefault().stopAppSwitches();
7421                    sendCloseSystemWindows();
7422                    Intent dock = createHomeDockIntent();
7423                    if (dock != null) {
7424                        int result = ActivityManagerNative.getDefault()
7425                                .startActivityAsUser(null, null, dock,
7426                                        dock.resolveTypeIfNeeded(mContext.getContentResolver()),
7427                                        null, null, 0,
7428                                        ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7429                                        null, null, UserHandle.USER_CURRENT);
7430                        if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7431                            return false;
7432                        }
7433                    }
7434                }
7435                int result = ActivityManagerNative.getDefault()
7436                        .startActivityAsUser(null, null, mHomeIntent,
7437                                mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
7438                                null, null, 0,
7439                                ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7440                                null, null, UserHandle.USER_CURRENT);
7441                if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7442                    return false;
7443                }
7444            } catch (RemoteException ex) {
7445                // bummer, the activity manager, which is in this process, is dead
7446            }
7447        }
7448        return true;
7449    }
7450
7451    @Override
7452    public void setCurrentOrientationLw(int newOrientation) {
7453        synchronized (mLock) {
7454            if (newOrientation != mCurrentAppOrientation) {
7455                mCurrentAppOrientation = newOrientation;
7456                updateOrientationListenerLp();
7457            }
7458        }
7459    }
7460
7461    private void performAuditoryFeedbackForAccessibilityIfNeed() {
7462        if (!isGlobalAccessibilityGestureEnabled()) {
7463            return;
7464        }
7465        AudioManager audioManager = (AudioManager) mContext.getSystemService(
7466                Context.AUDIO_SERVICE);
7467        if (audioManager.isSilentMode()) {
7468            return;
7469        }
7470        Ringtone ringTone = RingtoneManager.getRingtone(mContext,
7471                Settings.System.DEFAULT_NOTIFICATION_URI);
7472        ringTone.setStreamType(AudioManager.STREAM_MUSIC);
7473        ringTone.play();
7474    }
7475
7476    private boolean isTheaterModeEnabled() {
7477        return Settings.Global.getInt(mContext.getContentResolver(),
7478                Settings.Global.THEATER_MODE_ON, 0) == 1;
7479    }
7480
7481    private boolean isGlobalAccessibilityGestureEnabled() {
7482        return Settings.Global.getInt(mContext.getContentResolver(),
7483                Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1;
7484    }
7485
7486    private boolean areSystemNavigationKeysEnabled() {
7487        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
7488                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
7489    }
7490
7491    @Override
7492    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
7493        if (!mVibrator.hasVibrator()) {
7494            return false;
7495        }
7496        final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
7497                Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
7498        if (hapticsDisabled && !always) {
7499            return false;
7500        }
7501        long[] pattern = null;
7502        switch (effectId) {
7503            case HapticFeedbackConstants.LONG_PRESS:
7504                pattern = mLongPressVibePattern;
7505                break;
7506            case HapticFeedbackConstants.VIRTUAL_KEY:
7507                pattern = mVirtualKeyVibePattern;
7508                break;
7509            case HapticFeedbackConstants.KEYBOARD_TAP:
7510                pattern = mKeyboardTapVibePattern;
7511                break;
7512            case HapticFeedbackConstants.CLOCK_TICK:
7513                pattern = mClockTickVibePattern;
7514                break;
7515            case HapticFeedbackConstants.CALENDAR_DATE:
7516                pattern = mCalendarDateVibePattern;
7517                break;
7518            case HapticFeedbackConstants.SAFE_MODE_DISABLED:
7519                pattern = mSafeModeDisabledVibePattern;
7520                break;
7521            case HapticFeedbackConstants.SAFE_MODE_ENABLED:
7522                pattern = mSafeModeEnabledVibePattern;
7523                break;
7524            case HapticFeedbackConstants.CONTEXT_CLICK:
7525                pattern = mContextClickVibePattern;
7526                break;
7527            default:
7528                return false;
7529        }
7530        int owningUid;
7531        String owningPackage;
7532        if (win != null) {
7533            owningUid = win.getOwningUid();
7534            owningPackage = win.getOwningPackage();
7535        } else {
7536            owningUid = android.os.Process.myUid();
7537            owningPackage = mContext.getOpPackageName();
7538        }
7539        if (pattern.length == 1) {
7540            // One-shot vibration
7541            mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES);
7542        } else {
7543            // Pattern vibration
7544            mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES);
7545        }
7546        return true;
7547    }
7548
7549    @Override
7550    public void keepScreenOnStartedLw() {
7551    }
7552
7553    @Override
7554    public void keepScreenOnStoppedLw() {
7555        if (isKeyguardShowingAndNotOccluded()) {
7556            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
7557        }
7558    }
7559
7560    private int updateSystemUiVisibilityLw() {
7561        // If there is no window focused, there will be nobody to handle the events
7562        // anyway, so just hang on in whatever state we're in until things settle down.
7563        WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
7564                : mTopFullscreenOpaqueWindowState;
7565        if (winCandidate == null) {
7566            return 0;
7567        }
7568        if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
7569            // The immersive mode confirmation should never affect the system bar visibility,
7570            // otherwise it will unhide the navigation bar and hide itself.
7571            winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState;
7572            if (winCandidate == null) {
7573                return 0;
7574            }
7575        }
7576        final WindowState win = winCandidate;
7577        if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) {
7578            // We are updating at a point where the keyguard has gotten
7579            // focus, but we were last in a state where the top window is
7580            // hiding it.  This is probably because the keyguard as been
7581            // shown while the top window was displayed, so we want to ignore
7582            // it here because this is just a very transient change and it
7583            // will quickly lose focus once it correctly gets hidden.
7584            return 0;
7585        }
7586
7587        int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
7588                & ~mResettingSystemUiFlags
7589                & ~mForceClearedSystemUiFlags;
7590        if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
7591            tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
7592        }
7593
7594        final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
7595                mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
7596        final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
7597                mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
7598        mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);
7599        mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);
7600        final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
7601        final int diff = visibility ^ mLastSystemUiFlags;
7602        final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
7603        final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
7604        final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
7605        if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
7606                && mFocusedApp == win.getAppToken()
7607                && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
7608                && mLastDockedStackBounds.equals(mDockedStackBounds)) {
7609            return 0;
7610        }
7611        mLastSystemUiFlags = visibility;
7612        mLastFullscreenStackSysUiFlags = fullscreenVisibility;
7613        mLastDockedStackSysUiFlags = dockedVisibility;
7614        mLastFocusNeedsMenu = needsMenu;
7615        mFocusedApp = win.getAppToken();
7616        final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
7617        final Rect dockedStackBounds = new Rect(mDockedStackBounds);
7618        mHandler.post(new Runnable() {
7619                @Override
7620                public void run() {
7621                    StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
7622                    if (statusbar != null) {
7623                        statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
7624                                dockedVisibility, 0xffffffff, fullscreenStackBounds,
7625                                dockedStackBounds, win.toString());
7626                        statusbar.topAppWindowChanged(needsMenu);
7627                    }
7628                }
7629            });
7630        return diff;
7631    }
7632
7633    private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
7634        WindowState statusColorWin = isStatusBarKeyguard() && !mHideLockScreen
7635                ? mStatusBar
7636                : opaqueOrDimming;
7637
7638        if (statusColorWin != null) {
7639            if (statusColorWin == opaque) {
7640                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7641                // its light flag.
7642                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7643                vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
7644                        & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7645            } else if (statusColorWin != null && statusColorWin.isDimming()) {
7646                // Otherwise if it's dimming, clear the light flag.
7647                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7648            }
7649        }
7650        return vis;
7651    }
7652
7653    private boolean drawsSystemBarBackground(WindowState win) {
7654        return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
7655    }
7656
7657    private boolean forcesDrawStatusBarBackground(WindowState win) {
7658        return win == null || (win.getAttrs().privateFlags
7659                & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
7660    }
7661
7662    private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
7663        final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
7664        final boolean freeformStackVisible =
7665                mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
7666        final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
7667
7668        // We need to force system bars when the docked stack is visible, when the freeform stack
7669        // is visible but also when we are resizing for the transitions when docked stack
7670        // visibility changes.
7671        mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
7672        final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
7673
7674        // apply translucent bar vis flags
7675        WindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen
7676                ? mStatusBar
7677                : mTopFullscreenOpaqueWindowState;
7678        vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7679        vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7680        final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
7681                mTopDockedOpaqueWindowState, 0, 0);
7682
7683        final boolean fullscreenDrawsStatusBarBackground =
7684                (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
7685                        && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
7686                || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
7687        final boolean dockedDrawsStatusBarBackground =
7688                (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
7689                        && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
7690                || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
7691
7692        // prevent status bar interaction from clearing certain flags
7693        int type = win.getAttrs().type;
7694        boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
7695        if (statusBarHasFocus && !isStatusBarKeyguard()) {
7696            int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
7697                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
7698                    | View.SYSTEM_UI_FLAG_IMMERSIVE
7699                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
7700                    | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7701            if (mHideLockScreen) {
7702                flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
7703            }
7704            vis = (vis & ~flags) | (oldVis & flags);
7705        }
7706
7707        if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
7708            vis |= View.STATUS_BAR_TRANSPARENT;
7709            vis &= ~View.STATUS_BAR_TRANSLUCENT;
7710        } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
7711                || forceOpaqueStatusBar) {
7712            vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
7713        }
7714
7715        vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
7716
7717        // update status bar
7718        boolean immersiveSticky =
7719                (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7720        final boolean hideStatusBarWM =
7721                mTopFullscreenOpaqueWindowState != null
7722                && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
7723                        & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
7724        final boolean hideStatusBarSysui =
7725                (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
7726        final boolean hideNavBarSysui =
7727                (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
7728
7729        final boolean transientStatusBarAllowed = mStatusBar != null
7730                && (statusBarHasFocus || (!mForceShowSystemBars
7731                        && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
7732
7733        final boolean transientNavBarAllowed = mNavigationBar != null
7734                && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
7735
7736        final long now = SystemClock.uptimeMillis();
7737        final boolean pendingPanic = mPendingPanicGestureUptime != 0
7738                && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
7739        if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
7740            // The user performed the panic gesture recently, we're about to hide the bars,
7741            // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
7742            mPendingPanicGestureUptime = 0;
7743            mStatusBarController.showTransient();
7744            if (!isNavBarEmpty(vis)) {
7745                mNavigationBarController.showTransient();
7746            }
7747        }
7748
7749        final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
7750                && !transientStatusBarAllowed && hideStatusBarSysui;
7751        final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
7752                && !transientNavBarAllowed;
7753        if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
7754            // clear the clearable flags instead
7755            clearClearableFlagsLw();
7756            vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
7757        }
7758
7759        final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
7760        immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7761        final boolean navAllowedHidden = immersive || immersiveSticky;
7762
7763        if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType())
7764                > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) {
7765            // We can't hide the navbar from this window otherwise the input consumer would not get
7766            // the input events.
7767            vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
7768        }
7769
7770        vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
7771
7772        // update navigation bar
7773        boolean oldImmersiveMode = isImmersiveMode(oldVis);
7774        boolean newImmersiveMode = isImmersiveMode(vis);
7775        if (win != null && oldImmersiveMode != newImmersiveMode) {
7776            final String pkg = win.getOwningPackage();
7777            mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
7778                    isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility()));
7779        }
7780
7781        vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
7782
7783        return vis;
7784    }
7785
7786    /**
7787     * @return the current visibility flags with the nav-bar opacity related flags toggled based
7788     *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
7789     */
7790    private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
7791            boolean freeformStackVisible, boolean isDockedDividerResizing) {
7792        if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
7793            if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
7794                visibility = setNavBarOpaqueFlag(visibility);
7795            }
7796        } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
7797            if (isDockedDividerResizing) {
7798                visibility = setNavBarOpaqueFlag(visibility);
7799            } else if (freeformStackVisible) {
7800                visibility = setNavBarTranslucentFlag(visibility);
7801            } else {
7802                visibility = setNavBarOpaqueFlag(visibility);
7803            }
7804        }
7805
7806        if (!areTranslucentBarsAllowed()) {
7807            visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
7808        }
7809        return visibility;
7810    }
7811
7812    private int setNavBarOpaqueFlag(int visibility) {
7813        return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
7814    }
7815
7816    private int setNavBarTranslucentFlag(int visibility) {
7817        visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
7818        return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
7819    }
7820
7821    private void clearClearableFlagsLw() {
7822        int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
7823        if (newVal != mResettingSystemUiFlags) {
7824            mResettingSystemUiFlags = newVal;
7825            mWindowManagerFuncs.reevaluateStatusBarVisibility();
7826        }
7827    }
7828
7829    private boolean isImmersiveMode(int vis) {
7830        final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
7831        return mNavigationBar != null
7832                && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
7833                && (vis & flags) != 0
7834                && canHideNavigationBar();
7835    }
7836
7837    private static boolean isNavBarEmpty(int systemUiFlags) {
7838        final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
7839                | View.STATUS_BAR_DISABLE_BACK
7840                | View.STATUS_BAR_DISABLE_RECENT);
7841
7842        return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
7843    }
7844
7845    /**
7846     * @return whether the navigation or status bar can be made translucent
7847     *
7848     * This should return true unless touch exploration is not enabled or
7849     * R.boolean.config_enableTranslucentDecor is false.
7850     */
7851    private boolean areTranslucentBarsAllowed() {
7852        return mTranslucentDecorEnabled;
7853    }
7854
7855    // Use this instead of checking config_showNavigationBar so that it can be consistently
7856    // overridden by qemu.hw.mainkeys in the emulator.
7857    @Override
7858    public boolean hasNavigationBar() {
7859        return mHasNavigationBar;
7860    }
7861
7862    @Override
7863    public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
7864        mLastInputMethodWindow = ime;
7865        mLastInputMethodTargetWindow = target;
7866    }
7867
7868    @Override
7869    public int getInputMethodWindowVisibleHeightLw() {
7870        return mDockBottom - mCurBottom;
7871    }
7872
7873    @Override
7874    public void setCurrentUserLw(int newUserId) {
7875        mCurrentUserId = newUserId;
7876        if (mKeyguardDelegate != null) {
7877            mKeyguardDelegate.setCurrentUser(newUserId);
7878        }
7879        StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
7880        if (statusBar != null) {
7881            statusBar.setCurrentUser(newUserId);
7882        }
7883        setLastInputMethodWindowLw(null, null);
7884    }
7885
7886    @Override
7887    public boolean canMagnifyWindow(int windowType) {
7888        switch (windowType) {
7889            case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
7890            case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
7891            case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
7892            case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
7893                return false;
7894            }
7895        }
7896        return true;
7897    }
7898
7899    @Override
7900    public boolean isTopLevelWindow(int windowType) {
7901        if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
7902                && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
7903            return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
7904        }
7905        return true;
7906    }
7907
7908    @Override
7909    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
7910        // For the upside down rotation we don't rotate seamlessly as the navigation
7911        // bar moves position.
7912        // Note most apps (using orientation:sensor or user as opposed to fullSensor)
7913        // will not enter the reverse portrait orientation, so actually the
7914        // orientation won't change at all.
7915        if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
7916            return false;
7917        }
7918        int delta = newRotation - oldRotation;
7919        if (delta < 0) delta += 4;
7920        // Likewise we don't rotate seamlessly for 180 degree rotations
7921        // in this case the surfaces never resize, and our logic to
7922        // revert the transformations on size change will fail. We could
7923        // fix this in the future with the "tagged" frames idea.
7924        if (delta == Surface.ROTATION_180) {
7925            return false;
7926        }
7927
7928        final WindowState w = mTopFullscreenOpaqueWindowState;
7929        if (w != mFocusedWindow) {
7930            return false;
7931        }
7932
7933        // We only enable seamless rotation if the top window has requested
7934        // it and is in the fullscreen opaque state. Seamless rotation
7935        // requires freezing various Surface states and won't work well
7936        // with animations, so we disable it in the animation case for now.
7937        if (w != null && !w.isAnimatingLw() &&
7938                ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) ||
7939                        (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) {
7940            return true;
7941        }
7942        return false;
7943    }
7944
7945    @Override
7946    public void dump(String prefix, PrintWriter pw, String[] args) {
7947        pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
7948                pw.print(" mSystemReady="); pw.print(mSystemReady);
7949                pw.print(" mSystemBooted="); pw.println(mSystemBooted);
7950        pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
7951                pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
7952                pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
7953                pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
7954        if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
7955                || mForceClearedSystemUiFlags != 0) {
7956            pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
7957                    pw.print(Integer.toHexString(mLastSystemUiFlags));
7958                    pw.print(" mResettingSystemUiFlags=0x");
7959                    pw.print(Integer.toHexString(mResettingSystemUiFlags));
7960                    pw.print(" mForceClearedSystemUiFlags=0x");
7961                    pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
7962        }
7963        if (mLastFocusNeedsMenu) {
7964            pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
7965                    pw.println(mLastFocusNeedsMenu);
7966        }
7967        pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
7968                pw.println(mWakeGestureEnabledSetting);
7969
7970        pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
7971        pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
7972                pw.print(" mDockMode="); pw.print(mDockMode);
7973                pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
7974                pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
7975                pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
7976        pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
7977                pw.print(" mUserRotation="); pw.print(mUserRotation);
7978                pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
7979        pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
7980        pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
7981                pw.print(mCarDockEnablesAccelerometer);
7982                pw.print(" mDeskDockEnablesAccelerometer=");
7983                pw.println(mDeskDockEnablesAccelerometer);
7984        pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
7985                pw.print(mLidKeyboardAccessibility);
7986                pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
7987                pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
7988                pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
7989        pw.print(prefix);
7990                pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
7991        pw.print(prefix);
7992                pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
7993                pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
7994        pw.print(prefix);
7995                pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
7996                pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
7997        pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
7998        pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
7999        pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
8000                pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
8001        pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
8002                pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
8003        pw.print(prefix); pw.print("mOrientationSensorEnabled=");
8004                pw.println(mOrientationSensorEnabled);
8005        pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
8006                pw.print(","); pw.print(mOverscanScreenTop);
8007                pw.print(") "); pw.print(mOverscanScreenWidth);
8008                pw.print("x"); pw.println(mOverscanScreenHeight);
8009        if (mOverscanLeft != 0 || mOverscanTop != 0
8010                || mOverscanRight != 0 || mOverscanBottom != 0) {
8011            pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
8012                    pw.print(" top="); pw.print(mOverscanTop);
8013                    pw.print(" right="); pw.print(mOverscanRight);
8014                    pw.print(" bottom="); pw.println(mOverscanBottom);
8015        }
8016        pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
8017                pw.print(mRestrictedOverscanScreenLeft);
8018                pw.print(","); pw.print(mRestrictedOverscanScreenTop);
8019                pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
8020                pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
8021        pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
8022                pw.print(","); pw.print(mUnrestrictedScreenTop);
8023                pw.print(") "); pw.print(mUnrestrictedScreenWidth);
8024                pw.print("x"); pw.println(mUnrestrictedScreenHeight);
8025        pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
8026                pw.print(","); pw.print(mRestrictedScreenTop);
8027                pw.print(") "); pw.print(mRestrictedScreenWidth);
8028                pw.print("x"); pw.println(mRestrictedScreenHeight);
8029        pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
8030                pw.print(","); pw.print(mStableFullscreenTop);
8031                pw.print(")-("); pw.print(mStableFullscreenRight);
8032                pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
8033        pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
8034                pw.print(","); pw.print(mStableTop);
8035                pw.print(")-("); pw.print(mStableRight);
8036                pw.print(","); pw.print(mStableBottom); pw.println(")");
8037        pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
8038                pw.print(","); pw.print(mSystemTop);
8039                pw.print(")-("); pw.print(mSystemRight);
8040                pw.print(","); pw.print(mSystemBottom); pw.println(")");
8041        pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
8042                pw.print(","); pw.print(mCurTop);
8043                pw.print(")-("); pw.print(mCurRight);
8044                pw.print(","); pw.print(mCurBottom); pw.println(")");
8045        pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
8046                pw.print(","); pw.print(mContentTop);
8047                pw.print(")-("); pw.print(mContentRight);
8048                pw.print(","); pw.print(mContentBottom); pw.println(")");
8049        pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft);
8050                pw.print(","); pw.print(mVoiceContentTop);
8051                pw.print(")-("); pw.print(mVoiceContentRight);
8052                pw.print(","); pw.print(mVoiceContentBottom); pw.println(")");
8053        pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
8054                pw.print(","); pw.print(mDockTop);
8055                pw.print(")-("); pw.print(mDockRight);
8056                pw.print(","); pw.print(mDockBottom); pw.println(")");
8057        pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
8058                pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
8059        pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen);
8060                pw.print(" mShowingDream="); pw.print(mShowingDream);
8061                pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
8062                pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
8063        if (mLastInputMethodWindow != null) {
8064            pw.print(prefix); pw.print("mLastInputMethodWindow=");
8065                    pw.println(mLastInputMethodWindow);
8066        }
8067        if (mLastInputMethodTargetWindow != null) {
8068            pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
8069                    pw.println(mLastInputMethodTargetWindow);
8070        }
8071        if (mStatusBar != null) {
8072            pw.print(prefix); pw.print("mStatusBar=");
8073                    pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
8074                    pw.println(isStatusBarKeyguard());
8075        }
8076        if (mNavigationBar != null) {
8077            pw.print(prefix); pw.print("mNavigationBar=");
8078                    pw.println(mNavigationBar);
8079        }
8080        if (mFocusedWindow != null) {
8081            pw.print(prefix); pw.print("mFocusedWindow=");
8082                    pw.println(mFocusedWindow);
8083        }
8084        if (mFocusedApp != null) {
8085            pw.print(prefix); pw.print("mFocusedApp=");
8086                    pw.println(mFocusedApp);
8087        }
8088        if (mWinDismissingKeyguard != null) {
8089            pw.print(prefix); pw.print("mWinDismissingKeyguard=");
8090                    pw.println(mWinDismissingKeyguard);
8091        }
8092        if (mTopFullscreenOpaqueWindowState != null) {
8093            pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
8094                    pw.println(mTopFullscreenOpaqueWindowState);
8095        }
8096        if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
8097            pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
8098                    pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
8099        }
8100        if (mForcingShowNavBar) {
8101            pw.print(prefix); pw.print("mForcingShowNavBar=");
8102                    pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
8103                    pw.println(mForcingShowNavBarLayer);
8104        }
8105        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
8106                pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
8107        pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
8108                pw.print(" mForceStatusBarFromKeyguard=");
8109                pw.println(mForceStatusBarFromKeyguard);
8110        pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
8111                pw.print(" mCurrentlyDismissingKeyguard="); pw.println(mCurrentlyDismissingKeyguard);
8112                pw.print(" mWinDismissingKeyguard="); pw.print(mWinDismissingKeyguard);
8113                pw.print(" mHomePressed="); pw.println(mHomePressed);
8114        pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
8115                pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
8116                pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
8117        pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
8118                pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
8119                pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior);
8120                pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
8121        pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
8122                pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
8123        pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
8124                pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
8125        pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
8126                pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
8127        pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
8128
8129        mGlobalKeyManager.dump(prefix, pw);
8130        mStatusBarController.dump(pw, prefix);
8131        mNavigationBarController.dump(pw, prefix);
8132        PolicyControl.dump(prefix, pw);
8133
8134        if (mWakeGestureListener != null) {
8135            mWakeGestureListener.dump(pw, prefix);
8136        }
8137        if (mOrientationListener != null) {
8138            mOrientationListener.dump(pw, prefix);
8139        }
8140        if (mBurnInProtectionHelper != null) {
8141            mBurnInProtectionHelper.dump(prefix, pw);
8142        }
8143        if (mKeyguardDelegate != null) {
8144            mKeyguardDelegate.dump(prefix, pw);
8145        }
8146    }
8147}
8148