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