OSDN Git Service

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