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