OSDN Git Service

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