OSDN Git Service

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