OSDN Git Service

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