OSDN Git Service

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