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