OSDN Git Service

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