OSDN Git Service

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