OSDN Git Service

Should use getApplicationInfoAsUser instead
[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().getApplicationInfoAsUser(
2401                             attrs.packageName,
2402                             0 /* flags */,
2403                             UserHandle.getUserId(callingUid));
2404         } catch (PackageManager.NameNotFoundException e) {
2405             appInfo = null;
2406         }
2407
2408         if (appInfo == null || (type != TYPE_APPLICATION_OVERLAY && appInfo.targetSdkVersion >= O)) {
2409             /**
2410              * Apps targeting >= {@link Build.VERSION_CODES#O} are required to hold
2411              * {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW} (system signature apps)
2412              * permission to add alert windows that aren't
2413              * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY}.
2414              */
2415             return (mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
2416                     == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
2417         }
2418
2419         // check if user has enabled this operation. SecurityException will be thrown if this app
2420         // has not been allowed by the user
2421         final int mode = mAppOpsManager.checkOpNoThrow(outAppOp[0], callingUid, attrs.packageName);
2422         switch (mode) {
2423             case AppOpsManager.MODE_ALLOWED:
2424             case AppOpsManager.MODE_IGNORED:
2425                 // although we return ADD_OKAY for MODE_IGNORED, the added window will
2426                 // actually be hidden in WindowManagerService
2427                 return ADD_OKAY;
2428             case AppOpsManager.MODE_ERRORED:
2429                 // Don't crash legacy apps
2430                 if (appInfo.targetSdkVersion < M) {
2431                     return ADD_OKAY;
2432                 }
2433                 return ADD_PERMISSION_DENIED;
2434             default:
2435                 // in the default mode, we will make a decision here based on
2436                 // checkCallingPermission()
2437                 return (mContext.checkCallingOrSelfPermission(SYSTEM_ALERT_WINDOW)
2438                         == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
2439         }
2440     }
2441
2442     @Override
2443     public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) {
2444
2445         // If this switch statement is modified, modify the comment in the declarations of
2446         // the type in {@link WindowManager.LayoutParams} as well.
2447         switch (attrs.type) {
2448             default:
2449                 // These are the windows that by default are shown only to the user that created
2450                 // them. If this needs to be overridden, set
2451                 // {@link WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS} in
2452                 // {@link WindowManager.LayoutParams}. Note that permission
2453                 // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well.
2454                 if ((attrs.privateFlags & PRIVATE_FLAG_SHOW_FOR_ALL_USERS) == 0) {
2455                     return true;
2456                 }
2457                 break;
2458
2459             // These are the windows that by default are shown to all users. However, to
2460             // protect against spoofing, check permissions below.
2461             case TYPE_APPLICATION_STARTING:
2462             case TYPE_BOOT_PROGRESS:
2463             case TYPE_DISPLAY_OVERLAY:
2464             case TYPE_INPUT_CONSUMER:
2465             case TYPE_KEYGUARD_DIALOG:
2466             case TYPE_MAGNIFICATION_OVERLAY:
2467             case TYPE_NAVIGATION_BAR:
2468             case TYPE_NAVIGATION_BAR_PANEL:
2469             case TYPE_PHONE:
2470             case TYPE_POINTER:
2471             case TYPE_PRIORITY_PHONE:
2472             case TYPE_SEARCH_BAR:
2473             case TYPE_STATUS_BAR:
2474             case TYPE_STATUS_BAR_PANEL:
2475             case TYPE_STATUS_BAR_SUB_PANEL:
2476             case TYPE_SYSTEM_DIALOG:
2477             case TYPE_VOLUME_OVERLAY:
2478             case TYPE_PRESENTATION:
2479             case TYPE_PRIVATE_PRESENTATION:
2480             case TYPE_DOCK_DIVIDER:
2481                 break;
2482         }
2483
2484         // Check if third party app has set window to system window type.
2485         return mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW) != PERMISSION_GRANTED;
2486     }
2487
2488     @Override
2489     public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
2490         switch (attrs.type) {
2491             case TYPE_SYSTEM_OVERLAY:
2492             case TYPE_SECURE_SYSTEM_OVERLAY:
2493                 // These types of windows can't receive input events.
2494                 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2495                         | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
2496                 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
2497                 break;
2498             case TYPE_STATUS_BAR:
2499
2500                 // If the Keyguard is in a hidden state (occluded by another window), we force to
2501                 // remove the wallpaper and keyguard flag so that any change in-flight after setting
2502                 // the keyguard as occluded wouldn't set these flags again.
2503                 // See {@link #processKeyguardSetHiddenResultLw}.
2504                 if (mKeyguardOccluded) {
2505                     attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
2506                     attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2507                 }
2508                 break;
2509
2510             case TYPE_SCREENSHOT:
2511                 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
2512                 break;
2513
2514             case TYPE_TOAST:
2515                 // While apps should use the dedicated toast APIs to add such windows
2516                 // it possible legacy apps to add the window directly. Therefore, we
2517                 // make windows added directly by the app behave as a toast as much
2518                 // as possible in terms of timeout and animation.
2519                 if (attrs.hideTimeoutMilliseconds < 0
2520                         || attrs.hideTimeoutMilliseconds > TOAST_WINDOW_TIMEOUT) {
2521                     attrs.hideTimeoutMilliseconds = TOAST_WINDOW_TIMEOUT;
2522                 }
2523                 attrs.windowAnimations = com.android.internal.R.style.Animation_Toast;
2524                 break;
2525         }
2526
2527         if (attrs.type != TYPE_STATUS_BAR) {
2528             // The status bar is the only window allowed to exhibit keyguard behavior.
2529             attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2530         }
2531
2532         if (ActivityManager.isHighEndGfx()) {
2533             if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
2534                 attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
2535             }
2536             final boolean forceWindowDrawsStatusBarBackground =
2537                     (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND)
2538                             != 0;
2539             if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
2540                     || forceWindowDrawsStatusBarBackground
2541                             && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) {
2542                 attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2543             }
2544         }
2545     }
2546
2547     void readLidState() {
2548         mLidState = mWindowManagerFuncs.getLidState();
2549     }
2550
2551     private void readCameraLensCoverState() {
2552         mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState();
2553     }
2554
2555     private boolean isHidden(int accessibilityMode) {
2556         switch (accessibilityMode) {
2557             case 1:
2558                 return mLidState == LID_CLOSED;
2559             case 2:
2560                 return mLidState == LID_OPEN;
2561             default:
2562                 return false;
2563         }
2564     }
2565
2566     /** {@inheritDoc} */
2567     @Override
2568     public void adjustConfigurationLw(Configuration config, int keyboardPresence,
2569             int navigationPresence) {
2570         mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0;
2571
2572         readConfigurationDependentBehaviors();
2573         readLidState();
2574
2575         if (config.keyboard == Configuration.KEYBOARD_NOKEYS
2576                 || (keyboardPresence == PRESENCE_INTERNAL
2577                         && isHidden(mLidKeyboardAccessibility))) {
2578             config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
2579             if (!mHasSoftInput) {
2580                 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
2581             }
2582         }
2583
2584         if (config.navigation == Configuration.NAVIGATION_NONAV
2585                 || (navigationPresence == PRESENCE_INTERNAL
2586                         && isHidden(mLidNavigationAccessibility))) {
2587             config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
2588         }
2589     }
2590
2591     @Override
2592     public void onConfigurationChanged() {
2593         // TODO(multi-display): Define policy for secondary displays.
2594         final Resources res = mContext.getResources();
2595
2596         mStatusBarHeight =
2597                 res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
2598
2599         // Height of the navigation bar when presented horizontally at bottom
2600         mNavigationBarHeightForRotationDefault[mPortraitRotation] =
2601         mNavigationBarHeightForRotationDefault[mUpsideDownRotation] =
2602                 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
2603         mNavigationBarHeightForRotationDefault[mLandscapeRotation] =
2604         mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize(
2605                 com.android.internal.R.dimen.navigation_bar_height_landscape);
2606
2607         // Width of the navigation bar when presented vertically along one side
2608         mNavigationBarWidthForRotationDefault[mPortraitRotation] =
2609         mNavigationBarWidthForRotationDefault[mUpsideDownRotation] =
2610         mNavigationBarWidthForRotationDefault[mLandscapeRotation] =
2611         mNavigationBarWidthForRotationDefault[mSeascapeRotation] =
2612                 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
2613
2614         if (ALTERNATE_CAR_MODE_NAV_SIZE) {
2615             // Height of the navigation bar when presented horizontally at bottom
2616             mNavigationBarHeightForRotationInCarMode[mPortraitRotation] =
2617             mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] =
2618                     res.getDimensionPixelSize(
2619                             com.android.internal.R.dimen.navigation_bar_height_car_mode);
2620             mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] =
2621             mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize(
2622                     com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode);
2623
2624             // Width of the navigation bar when presented vertically along one side
2625             mNavigationBarWidthForRotationInCarMode[mPortraitRotation] =
2626             mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] =
2627             mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] =
2628             mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] =
2629                     res.getDimensionPixelSize(
2630                             com.android.internal.R.dimen.navigation_bar_width_car_mode);
2631         }
2632     }
2633
2634     @Override
2635     public int getMaxWallpaperLayer() {
2636         return getWindowLayerFromTypeLw(TYPE_STATUS_BAR);
2637     }
2638
2639     private int getNavigationBarWidth(int rotation, int uiMode) {
2640         if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2641             return mNavigationBarWidthForRotationInCarMode[rotation];
2642         } else {
2643             return mNavigationBarWidthForRotationDefault[rotation];
2644         }
2645     }
2646
2647     @Override
2648     public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
2649             int displayId) {
2650         // TODO(multi-display): Support navigation bar on secondary displays.
2651         if (displayId == Display.DEFAULT_DISPLAY && mHasNavigationBar) {
2652             // For a basic navigation bar, when we are in landscape mode we place
2653             // the navigation bar to the side.
2654             if (mNavigationBarCanMove && fullWidth > fullHeight) {
2655                 return fullWidth - getNavigationBarWidth(rotation, uiMode);
2656             }
2657         }
2658         return fullWidth;
2659     }
2660
2661     private int getNavigationBarHeight(int rotation, int uiMode) {
2662         if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2663             return mNavigationBarHeightForRotationInCarMode[rotation];
2664         } else {
2665             return mNavigationBarHeightForRotationDefault[rotation];
2666         }
2667     }
2668
2669     @Override
2670     public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
2671             int displayId) {
2672         // TODO(multi-display): Support navigation bar on secondary displays.
2673         if (displayId == Display.DEFAULT_DISPLAY && mHasNavigationBar) {
2674             // For a basic navigation bar, when we are in portrait mode we place
2675             // the navigation bar to the bottom.
2676             if (!mNavigationBarCanMove || fullWidth < fullHeight) {
2677                 return fullHeight - getNavigationBarHeight(rotation, uiMode);
2678             }
2679         }
2680         return fullHeight;
2681     }
2682
2683     @Override
2684     public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
2685             int displayId) {
2686         return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode, displayId);
2687     }
2688
2689     @Override
2690     public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
2691             int displayId) {
2692         // There is a separate status bar at the top of the display.  We don't count that as part
2693         // of the fixed decor, since it can hide; however, for purposes of configurations,
2694         // we do want to exclude it since applications can't generally use that part
2695         // of the screen.
2696         // TODO(multi-display): Support status bars on secondary displays.
2697         if (displayId == Display.DEFAULT_DISPLAY) {
2698             return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayId)
2699                     - mStatusBarHeight;
2700         }
2701         return fullHeight;
2702     }
2703
2704     @Override
2705     public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) {
2706         return attrs.type == TYPE_STATUS_BAR;
2707     }
2708
2709     @Override
2710     public boolean canBeHiddenByKeyguardLw(WindowState win) {
2711         switch (win.getAttrs().type) {
2712             case TYPE_STATUS_BAR:
2713             case TYPE_NAVIGATION_BAR:
2714             case TYPE_WALLPAPER:
2715             case TYPE_DREAM:
2716                 return false;
2717             default:
2718                 // Hide only windows below the keyguard host window.
2719                 return getWindowLayerLw(win) < getWindowLayerFromTypeLw(TYPE_STATUS_BAR);
2720         }
2721     }
2722
2723     private boolean shouldBeHiddenByKeyguard(WindowState win, WindowState imeTarget) {
2724
2725         // Keyguard visibility of window from activities are determined over activity visibility.
2726         if (win.getAppToken() != null) {
2727             return false;
2728         }
2729
2730         final LayoutParams attrs = win.getAttrs();
2731         final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleLw() &&
2732                 ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0
2733                         || !canBeHiddenByKeyguardLw(imeTarget));
2734
2735         // Show IME over the keyguard if the target allows it
2736         boolean allowWhenLocked = (win.isInputMethodWindow() || imeTarget == this)
2737                 && showImeOverKeyguard;;
2738
2739         if (isKeyguardLocked() && isKeyguardOccluded()) {
2740             // Show SHOW_WHEN_LOCKED windows if Keyguard is occluded.
2741             allowWhenLocked |= (attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
2742                     // Show error dialogs over apps that are shown on lockscreen
2743                     || (attrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
2744         }
2745
2746         boolean keyguardLocked = isKeyguardLocked();
2747         boolean hideDockDivider = attrs.type == TYPE_DOCK_DIVIDER
2748                 && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
2749         return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == Display.DEFAULT_DISPLAY)
2750                 || hideDockDivider;
2751     }
2752
2753     /** {@inheritDoc} */
2754     @Override
2755     public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme,
2756             CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon,
2757             int logo, int windowFlags, Configuration overrideConfig, int displayId) {
2758         if (!SHOW_SPLASH_SCREENS) {
2759             return null;
2760         }
2761         if (packageName == null) {
2762             return null;
2763         }
2764
2765         WindowManager wm = null;
2766         View view = null;
2767
2768         try {
2769             Context context = mContext;
2770             if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen " + packageName
2771                     + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
2772                     + Integer.toHexString(theme));
2773
2774             // Obtain proper context to launch on the right display.
2775             final Context displayContext = getDisplayContext(context, displayId);
2776             if (displayContext == null) {
2777                 // Can't show splash screen on requested display, so skip showing at all.
2778                 return null;
2779             }
2780             context = displayContext;
2781
2782             if (theme != context.getThemeResId() || labelRes != 0) {
2783                 try {
2784                     context = context.createPackageContext(packageName, 0);
2785                     context.setTheme(theme);
2786                 } catch (PackageManager.NameNotFoundException e) {
2787                     // Ignore
2788                 }
2789             }
2790
2791             if (overrideConfig != null && !overrideConfig.equals(EMPTY)) {
2792                 if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: creating context based"
2793                         + " on overrideConfig" + overrideConfig + " for splash screen");
2794                 final Context overrideContext = context.createConfigurationContext(overrideConfig);
2795                 overrideContext.setTheme(theme);
2796                 final TypedArray typedArray = overrideContext.obtainStyledAttributes(
2797                         com.android.internal.R.styleable.Window);
2798                 final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
2799                 if (resId != 0 && overrideContext.getDrawable(resId) != null) {
2800                     // We want to use the windowBackground for the override context if it is
2801                     // available, otherwise we use the default one to make sure a themed starting
2802                     // window is displayed for the app.
2803                     if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: apply overrideConfig"
2804                             + overrideConfig + " to starting window resId=" + resId);
2805                     context = overrideContext;
2806                 }
2807             }
2808
2809             final PhoneWindow win = new PhoneWindow(context);
2810             win.setIsStartingWindow(true);
2811
2812             CharSequence label = context.getResources().getText(labelRes, null);
2813             // Only change the accessibility title if the label is localized
2814             if (label != null) {
2815                 win.setTitle(label, true);
2816             } else {
2817                 win.setTitle(nonLocalizedLabel, false);
2818             }
2819
2820             win.setType(
2821                 WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
2822
2823             synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
2824                 // Assumes it's safe to show starting windows of launched apps while
2825                 // the keyguard is being hidden. This is okay because starting windows never show
2826                 // secret information.
2827                 if (mKeyguardOccluded) {
2828                     windowFlags |= FLAG_SHOW_WHEN_LOCKED;
2829                 }
2830             }
2831
2832             // Force the window flags: this is a fake window, so it is not really
2833             // touchable or focusable by the user.  We also add in the ALT_FOCUSABLE_IM
2834             // flag because we do know that the next window will take input
2835             // focus, so we want to get the IME window up on top of us right away.
2836             win.setFlags(
2837                 windowFlags|
2838                 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2839                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2840                 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
2841                 windowFlags|
2842                 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2843                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2844                 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
2845
2846             win.setDefaultIcon(icon);
2847             win.setDefaultLogo(logo);
2848
2849             win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
2850                     WindowManager.LayoutParams.MATCH_PARENT);
2851
2852             final WindowManager.LayoutParams params = win.getAttributes();
2853             params.token = appToken;
2854             params.packageName = packageName;
2855             params.windowAnimations = win.getWindowStyle().getResourceId(
2856                     com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
2857             params.privateFlags |=
2858                     WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
2859             params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
2860
2861             if (!compatInfo.supportsScreen()) {
2862                 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
2863             }
2864
2865             params.setTitle("Splash Screen " + packageName);
2866             wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
2867             view = win.getDecorView();
2868
2869             if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "Adding splash screen window for "
2870                 + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null));
2871
2872             wm.addView(view, params);
2873
2874             // Only return the view if it was successfully added to the
2875             // window manager... which we can tell by it having a parent.
2876             return view.getParent() != null ? new SplashScreenSurface(view, appToken) : null;
2877         } catch (WindowManager.BadTokenException e) {
2878             // ignore
2879             Log.w(TAG, appToken + " already running, starting window not displayed. " +
2880                     e.getMessage());
2881         } catch (RuntimeException e) {
2882             // don't crash if something else bad happens, for example a
2883             // failure loading resources because we are loading from an app
2884             // on external storage that has been unmounted.
2885             Log.w(TAG, appToken + " failed creating starting window", e);
2886         } finally {
2887             if (view != null && view.getParent() == null) {
2888                 Log.w(TAG, "view not successfully added to wm, removing view");
2889                 wm.removeViewImmediate(view);
2890             }
2891         }
2892
2893         return null;
2894     }
2895
2896     /** Obtain proper context for showing splash screen on the provided display. */
2897     private Context getDisplayContext(Context context, int displayId) {
2898         if (displayId == Display.DEFAULT_DISPLAY) {
2899             // The default context fits.
2900             return context;
2901         }
2902
2903         final DisplayManager dm = (DisplayManager) context.getSystemService(DISPLAY_SERVICE);
2904         final Display targetDisplay = dm.getDisplay(displayId);
2905         if (targetDisplay == null) {
2906             // Failed to obtain the non-default display where splash screen should be shown,
2907             // lets not show at all.
2908             return null;
2909         }
2910
2911         return context.createDisplayContext(targetDisplay);
2912     }
2913
2914     /**
2915      * Preflight adding a window to the system.
2916      *
2917      * Currently enforces that three window types are singletons:
2918      * <ul>
2919      * <li>STATUS_BAR_TYPE</li>
2920      * <li>KEYGUARD_TYPE</li>
2921      * </ul>
2922      *
2923      * @param win The window to be added
2924      * @param attrs Information about the window to be added
2925      *
2926      * @return If ok, WindowManagerImpl.ADD_OKAY.  If too many singletons,
2927      * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
2928      */
2929     @Override
2930     public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
2931         switch (attrs.type) {
2932             case TYPE_STATUS_BAR:
2933                 mContext.enforceCallingOrSelfPermission(
2934                         android.Manifest.permission.STATUS_BAR_SERVICE,
2935                         "PhoneWindowManager");
2936                 if (mStatusBar != null) {
2937                     if (mStatusBar.isAlive()) {
2938                         return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2939                     }
2940                 }
2941                 mStatusBar = win;
2942                 mStatusBarController.setWindow(win);
2943                 break;
2944             case TYPE_NAVIGATION_BAR:
2945                 mContext.enforceCallingOrSelfPermission(
2946                         android.Manifest.permission.STATUS_BAR_SERVICE,
2947                         "PhoneWindowManager");
2948                 if (mNavigationBar != null) {
2949                     if (mNavigationBar.isAlive()) {
2950                         return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2951                     }
2952                 }
2953                 mNavigationBar = win;
2954                 mNavigationBarController.setWindow(win);
2955                 mNavigationBarController.setOnBarVisibilityChangedListener(
2956                         mNavBarVisibilityListener);
2957                 if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
2958                 break;
2959             case TYPE_NAVIGATION_BAR_PANEL:
2960             case TYPE_STATUS_BAR_PANEL:
2961             case TYPE_STATUS_BAR_SUB_PANEL:
2962             case TYPE_VOICE_INTERACTION_STARTING:
2963                 mContext.enforceCallingOrSelfPermission(
2964                         android.Manifest.permission.STATUS_BAR_SERVICE,
2965                         "PhoneWindowManager");
2966                 break;
2967         }
2968         return ADD_OKAY;
2969     }
2970
2971     /** {@inheritDoc} */
2972     @Override
2973     public void removeWindowLw(WindowState win) {
2974         if (mStatusBar == win) {
2975             mStatusBar = null;
2976             mStatusBarController.setWindow(null);
2977         } else if (mNavigationBar == win) {
2978             mNavigationBar = null;
2979             mNavigationBarController.setWindow(null);
2980         }
2981     }
2982
2983     static final boolean PRINT_ANIM = false;
2984
2985     /** {@inheritDoc} */
2986     @Override
2987     public int selectAnimationLw(WindowState win, int transit) {
2988         if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
2989               + ": transit=" + transit);
2990         if (win == mStatusBar) {
2991             boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
2992             if (transit == TRANSIT_EXIT
2993                     || transit == TRANSIT_HIDE) {
2994                 return isKeyguard ? -1 : R.anim.dock_top_exit;
2995             } else if (transit == TRANSIT_ENTER
2996                     || transit == TRANSIT_SHOW) {
2997                 return isKeyguard ? -1 : R.anim.dock_top_enter;
2998             }
2999         } else if (win == mNavigationBar) {
3000             if (win.getAttrs().windowAnimations != 0) {
3001                 return 0;
3002             }
3003             // This can be on either the bottom or the right or the left.
3004             if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
3005                 if (transit == TRANSIT_EXIT
3006                         || transit == TRANSIT_HIDE) {
3007                     if (isKeyguardShowingAndNotOccluded()) {
3008                         return R.anim.dock_bottom_exit_keyguard;
3009                     } else {
3010                         return R.anim.dock_bottom_exit;
3011                     }
3012                 } else if (transit == TRANSIT_ENTER
3013                         || transit == TRANSIT_SHOW) {
3014                     return R.anim.dock_bottom_enter;
3015                 }
3016             } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
3017                 if (transit == TRANSIT_EXIT
3018                         || transit == TRANSIT_HIDE) {
3019                     return R.anim.dock_right_exit;
3020                 } else if (transit == TRANSIT_ENTER
3021                         || transit == TRANSIT_SHOW) {
3022                     return R.anim.dock_right_enter;
3023                 }
3024             } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
3025                 if (transit == TRANSIT_EXIT
3026                         || transit == TRANSIT_HIDE) {
3027                     return R.anim.dock_left_exit;
3028                 } else if (transit == TRANSIT_ENTER
3029                         || transit == TRANSIT_SHOW) {
3030                     return R.anim.dock_left_enter;
3031                 }
3032             }
3033         } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) {
3034             return selectDockedDividerAnimationLw(win, transit);
3035         }
3036
3037         if (transit == TRANSIT_PREVIEW_DONE) {
3038             if (win.hasAppShownWindows()) {
3039                 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
3040                 return com.android.internal.R.anim.app_starting_exit;
3041             }
3042         } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
3043                 && transit == TRANSIT_ENTER) {
3044             // Special case: we are animating in a dream, while the keyguard
3045             // is shown.  We don't want an animation on the dream, because
3046             // we need it shown immediately with the keyguard animating away
3047             // to reveal it.
3048             return -1;
3049         }
3050
3051         return 0;
3052     }
3053
3054     private int selectDockedDividerAnimationLw(WindowState win, int transit) {
3055         int insets = mWindowManagerFuncs.getDockedDividerInsetsLw();
3056
3057         // If the divider is behind the navigation bar, don't animate.
3058         final Rect frame = win.getFrameLw();
3059         final boolean behindNavBar = mNavigationBar != null
3060                 && ((mNavigationBarPosition == NAV_BAR_BOTTOM
3061                         && frame.top + insets >= mNavigationBar.getFrameLw().top)
3062                 || (mNavigationBarPosition == NAV_BAR_RIGHT
3063                         && frame.left + insets >= mNavigationBar.getFrameLw().left)
3064                 || (mNavigationBarPosition == NAV_BAR_LEFT
3065                         && frame.right - insets <= mNavigationBar.getFrameLw().right));
3066         final boolean landscape = frame.height() > frame.width();
3067         final boolean offscreenLandscape = landscape && (frame.right - insets <= 0
3068                 || frame.left + insets >= win.getDisplayFrameLw().right);
3069         final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0
3070                 || frame.bottom + insets >= win.getDisplayFrameLw().bottom);
3071         final boolean offscreen = offscreenLandscape || offscreenPortrait;
3072         if (behindNavBar || offscreen) {
3073             return 0;
3074         }
3075         if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
3076             return R.anim.fade_in;
3077         } else if (transit == TRANSIT_EXIT) {
3078             return R.anim.fade_out;
3079         } else {
3080             return 0;
3081         }
3082     }
3083
3084     @Override
3085     public void selectRotationAnimationLw(int anim[]) {
3086         if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
3087                 + mTopFullscreenOpaqueWindowState + " rotationAnimation="
3088                 + (mTopFullscreenOpaqueWindowState == null ?
3089                         "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation));
3090         if (mTopFullscreenOpaqueWindowState != null) {
3091             int animationHint = mTopFullscreenOpaqueWindowState.getRotationAnimationHint();
3092             if (animationHint < 0 && mTopIsFullscreen) {
3093                 animationHint = mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation;
3094             }
3095             switch (animationHint) {
3096                 case ROTATION_ANIMATION_CROSSFADE:
3097                 case ROTATION_ANIMATION_SEAMLESS: // Crossfade is fallback for seamless.
3098                     anim[0] = R.anim.rotation_animation_xfade_exit;
3099                     anim[1] = R.anim.rotation_animation_enter;
3100                     break;
3101                 case ROTATION_ANIMATION_JUMPCUT:
3102                     anim[0] = R.anim.rotation_animation_jump_exit;
3103                     anim[1] = R.anim.rotation_animation_enter;
3104                     break;
3105                 case ROTATION_ANIMATION_ROTATE:
3106                 default:
3107                     anim[0] = anim[1] = 0;
3108                     break;
3109             }
3110         } else {
3111             anim[0] = anim[1] = 0;
3112         }
3113     }
3114
3115     @Override
3116     public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId,
3117             boolean forceDefault) {
3118         switch (exitAnimId) {
3119             case R.anim.rotation_animation_xfade_exit:
3120             case R.anim.rotation_animation_jump_exit:
3121                 // These are the only cases that matter.
3122                 if (forceDefault) {
3123                     return false;
3124                 }
3125                 int anim[] = new int[2];
3126                 selectRotationAnimationLw(anim);
3127                 return (exitAnimId == anim[0] && enterAnimId == anim[1]);
3128             default:
3129                 return true;
3130         }
3131     }
3132
3133     @Override
3134     public Animation createHiddenByKeyguardExit(boolean onWallpaper,
3135             boolean goingToNotificationShade) {
3136         if (goingToNotificationShade) {
3137             return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
3138         }
3139
3140         AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ?
3141                     R.anim.lock_screen_behind_enter_wallpaper :
3142                     R.anim.lock_screen_behind_enter);
3143
3144         // TODO: Use XML interpolators when we have log interpolators available in XML.
3145         final List<Animation> animations = set.getAnimations();
3146         for (int i = animations.size() - 1; i >= 0; --i) {
3147             animations.get(i).setInterpolator(mLogDecelerateInterpolator);
3148         }
3149
3150         return set;
3151     }
3152
3153
3154     @Override
3155     public Animation createKeyguardWallpaperExit(boolean goingToNotificationShade) {
3156         if (goingToNotificationShade) {
3157             return null;
3158         } else {
3159             return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
3160         }
3161     }
3162
3163     private static void awakenDreams() {
3164         IDreamManager dreamManager = getDreamManager();
3165         if (dreamManager != null) {
3166             try {
3167                 dreamManager.awaken();
3168             } catch (RemoteException e) {
3169                 // fine, stay asleep then
3170             }
3171         }
3172     }
3173
3174     static IDreamManager getDreamManager() {
3175         return IDreamManager.Stub.asInterface(
3176                 ServiceManager.checkService(DreamService.DREAM_SERVICE));
3177     }
3178
3179     TelecomManager getTelecommService() {
3180         return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
3181     }
3182
3183     static IAudioService getAudioService() {
3184         IAudioService audioService = IAudioService.Stub.asInterface(
3185                 ServiceManager.checkService(Context.AUDIO_SERVICE));
3186         if (audioService == null) {
3187             Log.w(TAG, "Unable to find IAudioService interface.");
3188         }
3189         return audioService;
3190     }
3191
3192     boolean keyguardOn() {
3193         return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode();
3194     }
3195
3196     private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
3197             WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
3198             WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
3199         };
3200
3201     /** {@inheritDoc} */
3202     @Override
3203     public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
3204         final boolean keyguardOn = keyguardOn();
3205         final int keyCode = event.getKeyCode();
3206         final int repeatCount = event.getRepeatCount();
3207         final int metaState = event.getMetaState();
3208         final int flags = event.getFlags();
3209         final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
3210         final boolean canceled = event.isCanceled();
3211
3212         if (DEBUG_INPUT) {
3213             Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
3214                     + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
3215                     + " canceled=" + canceled);
3216         }
3217
3218         // If we think we might have a volume down & power key chord on the way
3219         // but we're not sure, then tell the dispatcher to wait a little while and
3220         // try again later before dispatching.
3221         if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
3222             if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
3223                 final long now = SystemClock.uptimeMillis();
3224                 final long timeoutTime = mScreenshotChordVolumeDownKeyTime
3225                         + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
3226                 if (now < timeoutTime) {
3227                     return timeoutTime - now;
3228                 }
3229             }
3230             if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3231                     && mScreenshotChordVolumeDownKeyConsumed) {
3232                 if (!down) {
3233                     mScreenshotChordVolumeDownKeyConsumed = false;
3234                 }
3235                 return -1;
3236             }
3237         }
3238
3239         // If an accessibility shortcut might be partially complete, hold off dispatching until we
3240         // know if it is complete or not
3241         if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable()
3242                 && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
3243             if (mScreenshotChordVolumeDownKeyTriggered ^ mA11yShortcutChordVolumeUpKeyTriggered) {
3244                 final long now = SystemClock.uptimeMillis();
3245                 final long timeoutTime = (mScreenshotChordVolumeDownKeyTriggered
3246                         ? mScreenshotChordVolumeDownKeyTime : mA11yShortcutChordVolumeUpKeyTime)
3247                         + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
3248                 if (now < timeoutTime) {
3249                     return timeoutTime - now;
3250                 }
3251             }
3252             if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && mScreenshotChordVolumeDownKeyConsumed) {
3253                 if (!down) {
3254                     mScreenshotChordVolumeDownKeyConsumed = false;
3255                 }
3256                 return -1;
3257             }
3258             if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mA11yShortcutChordVolumeUpKeyConsumed) {
3259                 if (!down) {
3260                     mA11yShortcutChordVolumeUpKeyConsumed = false;
3261                 }
3262                 return -1;
3263             }
3264         }
3265
3266         // Cancel any pending meta actions if we see any other keys being pressed between the down
3267         // of the meta key and its corresponding up.
3268         if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
3269             mPendingMetaAction = false;
3270         }
3271         // Any key that is not Alt or Meta cancels Caps Lock combo tracking.
3272         if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) {
3273             mPendingCapsLockToggle = false;
3274         }
3275
3276         // First we always handle the home key here, so applications
3277         // can never break it, although if keyguard is on, we do let
3278         // it handle it, because that gives us the correct 5 second
3279         // timeout.
3280         if (keyCode == KeyEvent.KEYCODE_HOME) {
3281
3282             // If we have released the home key, and didn't do anything else
3283             // while it was pressed, then it is time to go home!
3284             if (!down) {
3285                 cancelPreloadRecentApps();
3286
3287                 mHomePressed = false;
3288                 if (mHomeConsumed) {
3289                     mHomeConsumed = false;
3290                     return -1;
3291                 }
3292
3293                 if (canceled) {
3294                     Log.i(TAG, "Ignoring HOME; event canceled.");
3295                     return -1;
3296                 }
3297
3298                 // Delay handling home if a double-tap is possible.
3299                 if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
3300                     mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
3301                     mHomeDoubleTapPending = true;
3302                     mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
3303                             ViewConfiguration.getDoubleTapTimeout());
3304                     return -1;
3305                 }
3306
3307                 handleShortPressOnHome();
3308                 return -1;
3309             }
3310
3311             // If a system window has focus, then it doesn't make sense
3312             // right now to interact with applications.
3313             WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
3314             if (attrs != null) {
3315                 final int type = attrs.type;
3316                 if (type == TYPE_KEYGUARD_DIALOG
3317                         || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
3318                     // the "app" is keyguard, so give it the key
3319                     return 0;
3320                 }
3321                 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
3322                 for (int i=0; i<typeCount; i++) {
3323                     if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
3324                         // don't do anything, but also don't pass it to the app
3325                         return -1;
3326                     }
3327                 }
3328             }
3329
3330             // Remember that home is pressed and handle special actions.
3331             if (repeatCount == 0) {
3332                 mHomePressed = true;
3333                 if (mHomeDoubleTapPending) {
3334                     mHomeDoubleTapPending = false;
3335                     mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
3336                     handleDoubleTapOnHome();
3337                 } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI
3338                         || mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
3339                     preloadRecentApps();
3340                 }
3341             } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
3342                 if (!keyguardOn) {
3343                     handleLongPressOnHome(event.getDeviceId());
3344                 }
3345             }
3346             return -1;
3347         } else if (keyCode == KeyEvent.KEYCODE_MENU) {
3348             // Hijack modified menu keys for debugging features
3349             final int chordBug = KeyEvent.META_SHIFT_ON;
3350
3351             if (down && repeatCount == 0) {
3352                 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
3353                     Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
3354                     mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
3355                             null, null, null, 0, null, null);
3356                     return -1;
3357                 }
3358             }
3359         } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
3360             if (down) {
3361                 if (repeatCount == 0) {
3362                     mSearchKeyShortcutPending = true;
3363                     mConsumeSearchKeyUp = false;
3364                 }
3365             } else {
3366                 mSearchKeyShortcutPending = false;
3367                 if (mConsumeSearchKeyUp) {
3368                     mConsumeSearchKeyUp = false;
3369                     return -1;
3370                 }
3371             }
3372             return 0;
3373         } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
3374             if (!keyguardOn) {
3375                 if (down && repeatCount == 0) {
3376                     preloadRecentApps();
3377                 } else if (!down) {
3378                     toggleRecentApps();
3379                 }
3380             }
3381             return -1;
3382         } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) {
3383             if (down) {
3384                 IStatusBarService service = getStatusBarService();
3385                 if (service != null) {
3386                     try {
3387                         service.expandNotificationsPanel();
3388                     } catch (RemoteException e) {
3389                         // do nothing.
3390                     }
3391                 }
3392             }
3393         } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed()
3394                 && event.isCtrlPressed()) {
3395             if (down && repeatCount == 0) {
3396                 int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION
3397                         : TAKE_SCREENSHOT_FULLSCREEN;
3398                 mScreenshotRunnable.setScreenshotType(type);
3399                 mHandler.post(mScreenshotRunnable);
3400                 return -1;
3401             }
3402         } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
3403             if (down && repeatCount == 0 && !isKeyguardLocked()) {
3404                 toggleKeyboardShortcutsMenu(event.getDeviceId());
3405             }
3406         } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
3407             if (down) {
3408                 if (repeatCount == 0) {
3409                     mAssistKeyLongPressed = false;
3410                 } else if (repeatCount == 1) {
3411                     mAssistKeyLongPressed = true;
3412                     if (!keyguardOn) {
3413                          launchAssistLongPressAction();
3414                     }
3415                 }
3416             } else {
3417                 if (mAssistKeyLongPressed) {
3418                     mAssistKeyLongPressed = false;
3419                 } else {
3420                     if (!keyguardOn) {
3421                         launchAssistAction(null, event.getDeviceId());
3422                     }
3423                 }
3424             }
3425             return -1;
3426         } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
3427             if (!down) {
3428                 Intent voiceIntent;
3429                 if (!keyguardOn) {
3430                     voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
3431                 } else {
3432                     IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
3433                             ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
3434                     if (dic != null) {
3435                         try {
3436                             dic.exitIdle("voice-search");
3437                         } catch (RemoteException e) {
3438                         }
3439                     }
3440                     voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
3441                     voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
3442                 }
3443                 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
3444             }
3445         } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
3446             if (down && repeatCount == 0) {
3447                 mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
3448                 mHandler.post(mScreenshotRunnable);
3449             }
3450             return -1;
3451         } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP
3452                 || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) {
3453             if (down) {
3454                 int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
3455
3456                 // Disable autobrightness if it's on
3457                 int auto = Settings.System.getIntForUser(
3458                         mContext.getContentResolver(),
3459                         Settings.System.SCREEN_BRIGHTNESS_MODE,
3460                         Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3461                         UserHandle.USER_CURRENT_OR_SELF);
3462                 if (auto != 0) {
3463                     Settings.System.putIntForUser(mContext.getContentResolver(),
3464                             Settings.System.SCREEN_BRIGHTNESS_MODE,
3465                             Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3466                             UserHandle.USER_CURRENT_OR_SELF);
3467                 }
3468
3469                 int min = mPowerManager.getMinimumScreenBrightnessSetting();
3470                 int max = mPowerManager.getMaximumScreenBrightnessSetting();
3471                 int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction;
3472                 int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
3473                         Settings.System.SCREEN_BRIGHTNESS,
3474                         mPowerManager.getDefaultScreenBrightnessSetting(),
3475                         UserHandle.USER_CURRENT_OR_SELF);
3476                 brightness += step;
3477                 // Make sure we don't go beyond the limits.
3478                 brightness = Math.min(max, brightness);
3479                 brightness = Math.max(min, brightness);
3480
3481                 Settings.System.putIntForUser(mContext.getContentResolver(),
3482                         Settings.System.SCREEN_BRIGHTNESS, brightness,
3483                         UserHandle.USER_CURRENT_OR_SELF);
3484                 startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
3485                         UserHandle.CURRENT_OR_SELF);
3486             }
3487             return -1;
3488         } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
3489                 || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3490                 || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
3491             if (mUseTvRouting) {
3492                 // On TVs volume keys never go to the foreground app.
3493                 dispatchDirectAudioEvent(event);
3494                 return -1;
3495             }
3496         } else if (keyCode == KeyEvent.KEYCODE_TAB && event.isMetaPressed()) {
3497             // Pass through keyboard navigation keys.
3498             return 0;
3499         } else if (mHasFeatureLeanback && interceptBugreportGestureTv(keyCode, down)) {
3500             return -1;
3501         }
3502
3503         // Toggle Caps Lock on META-ALT.
3504         boolean actionTriggered = false;
3505         if (KeyEvent.isModifierKey(keyCode)) {
3506             if (!mPendingCapsLockToggle) {
3507                 // Start tracking meta state for combo.
3508                 mInitialMetaState = mMetaState;
3509                 mPendingCapsLockToggle = true;
3510             } else if (event.getAction() == KeyEvent.ACTION_UP) {
3511                 int altOnMask = mMetaState & KeyEvent.META_ALT_MASK;
3512                 int metaOnMask = mMetaState & KeyEvent.META_META_MASK;
3513
3514                 // Check for Caps Lock toggle
3515                 if ((metaOnMask != 0) && (altOnMask != 0)) {
3516                     // Check if nothing else is pressed
3517                     if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) {
3518                         // Handle Caps Lock Toggle
3519                         mInputManagerInternal.toggleCapsLock(event.getDeviceId());
3520                         actionTriggered = true;
3521                     }
3522                 }
3523
3524                 // Always stop tracking when key goes up.
3525                 mPendingCapsLockToggle = false;
3526             }
3527         }
3528         // Store current meta state to be able to evaluate it later.
3529         mMetaState = metaState;
3530
3531         if (actionTriggered) {
3532             return -1;
3533         }
3534
3535         if (KeyEvent.isMetaKey(keyCode)) {
3536             if (down) {
3537                 mPendingMetaAction = true;
3538             } else if (mPendingMetaAction) {
3539                 launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId());
3540             }
3541             return -1;
3542         }
3543
3544         // Shortcuts are invoked through Search+key, so intercept those here
3545         // Any printing key that is chorded with Search should be consumed
3546         // even if no shortcut was invoked.  This prevents text from being
3547         // inadvertently inserted when using a keyboard that has built-in macro
3548         // shortcut keys (that emit Search+x) and some of them are not registered.
3549         if (mSearchKeyShortcutPending) {
3550             final KeyCharacterMap kcm = event.getKeyCharacterMap();
3551             if (kcm.isPrintingKey(keyCode)) {
3552                 mConsumeSearchKeyUp = true;
3553                 mSearchKeyShortcutPending = false;
3554                 if (down && repeatCount == 0 && !keyguardOn) {
3555                     Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
3556                     if (shortcutIntent != null) {
3557                         shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3558                         try {
3559                             startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3560                             dismissKeyboardShortcutsMenu();
3561                         } catch (ActivityNotFoundException ex) {
3562                             Slog.w(TAG, "Dropping shortcut key combination because "
3563                                     + "the activity to which it is registered was not found: "
3564                                     + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);
3565                         }
3566                     } else {
3567                         Slog.i(TAG, "Dropping unregistered shortcut key combination: "
3568                                 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));
3569                     }
3570                 }
3571                 return -1;
3572             }
3573         }
3574
3575         // Invoke shortcuts using Meta.
3576         if (down && repeatCount == 0 && !keyguardOn
3577                 && (metaState & KeyEvent.META_META_ON) != 0) {
3578             final KeyCharacterMap kcm = event.getKeyCharacterMap();
3579             if (kcm.isPrintingKey(keyCode)) {
3580                 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
3581                         metaState & ~(KeyEvent.META_META_ON
3582                                 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
3583                 if (shortcutIntent != null) {
3584                     shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3585                     try {
3586                         startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3587                         dismissKeyboardShortcutsMenu();
3588                     } catch (ActivityNotFoundException ex) {
3589                         Slog.w(TAG, "Dropping shortcut key combination because "
3590                                 + "the activity to which it is registered was not found: "
3591                                 + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
3592                     }
3593                     return -1;
3594                 }
3595             }
3596         }
3597
3598         // Handle application launch keys.
3599         if (down && repeatCount == 0 && !keyguardOn) {
3600             String category = sApplicationLaunchKeyCategories.get(keyCode);
3601             if (category != null) {
3602                 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
3603                 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3604                 try {
3605                     startActivityAsUser(intent, UserHandle.CURRENT);
3606                     dismissKeyboardShortcutsMenu();
3607                 } catch (ActivityNotFoundException ex) {
3608                     Slog.w(TAG, "Dropping application launch key because "
3609                             + "the activity to which it is registered was not found: "
3610                             + "keyCode=" + keyCode + ", category=" + category, ex);
3611                 }
3612                 return -1;
3613             }
3614         }
3615
3616         // Display task switcher for ALT-TAB.
3617         if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
3618             if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
3619                 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
3620                 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
3621                     mRecentAppsHeldModifiers = shiftlessModifiers;
3622                     showRecentApps(true, false);
3623                     return -1;
3624                 }
3625             }
3626         } else if (!down && mRecentAppsHeldModifiers != 0
3627                 && (metaState & mRecentAppsHeldModifiers) == 0) {
3628             mRecentAppsHeldModifiers = 0;
3629             hideRecentApps(true, false);
3630         }
3631
3632         // Handle input method switching.
3633         if (down && repeatCount == 0
3634                 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3635                         || (keyCode == KeyEvent.KEYCODE_SPACE
3636                                 && (metaState & KeyEvent.META_META_MASK) != 0))) {
3637             final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0;
3638             mWindowManagerFuncs.switchInputMethod(forwardDirection);
3639             return -1;
3640         }
3641         if (mLanguageSwitchKeyPressed && !down
3642                 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3643                         || keyCode == KeyEvent.KEYCODE_SPACE)) {
3644             mLanguageSwitchKeyPressed = false;
3645             return -1;
3646         }
3647
3648         if (isValidGlobalKey(keyCode)
3649                 && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
3650             return -1;
3651         }
3652
3653         if (down) {
3654             long shortcutCode = keyCode;
3655             if (event.isCtrlPressed()) {
3656                 shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
3657             }
3658
3659             if (event.isAltPressed()) {
3660                 shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
3661             }
3662
3663             if (event.isShiftPressed()) {
3664                 shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
3665             }
3666
3667             if (event.isMetaPressed()) {
3668                 shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE;
3669             }
3670
3671             IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode);
3672             if (shortcutService != null) {
3673                 try {
3674                     if (isUserSetupComplete()) {
3675                         shortcutService.notifyShortcutKeyPressed(shortcutCode);
3676                     }
3677                 } catch (RemoteException e) {
3678                     mShortcutKeyServices.delete(shortcutCode);
3679                 }
3680                 return -1;
3681             }
3682         }
3683
3684         // Reserve all the META modifier combos for system behavior
3685         if ((metaState & KeyEvent.META_META_ON) != 0) {
3686             return -1;
3687         }
3688
3689         // Let the application handle the key.
3690         return 0;
3691     }
3692
3693     /**
3694      * TV only: recognizes a remote control gesture for capturing a bug report.
3695      */
3696     private boolean interceptBugreportGestureTv(int keyCode, boolean down) {
3697         // The bugreport capture chord is a long press on DPAD CENTER and BACK simultaneously.
3698         if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
3699             mBugreportTvKey1Pressed = down;
3700         } else if (keyCode == KeyEvent.KEYCODE_BACK) {
3701             mBugreportTvKey2Pressed = down;
3702         }
3703
3704         if (mBugreportTvKey1Pressed && mBugreportTvKey2Pressed) {
3705             if (!mBugreportTvScheduled) {
3706                 mBugreportTvScheduled = true;
3707                 Message msg = Message.obtain(mHandler, MSG_BUGREPORT_TV);
3708                 msg.setAsynchronous(true);
3709                 mHandler.sendMessageDelayed(msg, BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS);
3710             }
3711         } else if (mBugreportTvScheduled) {
3712             mHandler.removeMessages(MSG_BUGREPORT_TV);
3713             mBugreportTvScheduled = false;
3714         }
3715
3716         return mBugreportTvScheduled;
3717     }
3718
3719     private void takeBugreport() {
3720         if ("1".equals(SystemProperties.get("ro.debuggable"))
3721                 || Settings.Global.getInt(mContext.getContentResolver(),
3722                         Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) == 1) {
3723             try {
3724                 ActivityManager.getService()
3725                         .requestBugReport(ActivityManager.BUGREPORT_OPTION_INTERACTIVE);
3726             } catch (RemoteException e) {
3727                 Slog.e(TAG, "Error taking bugreport", e);
3728             }
3729         }
3730     }
3731
3732     /** {@inheritDoc} */
3733     @Override
3734     public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
3735         // Note: This method is only called if the initial down was unhandled.
3736         if (DEBUG_INPUT) {
3737             Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
3738                     + ", flags=" + event.getFlags()
3739                     + ", keyCode=" + event.getKeyCode()
3740                     + ", scanCode=" + event.getScanCode()
3741                     + ", metaState=" + event.getMetaState()
3742                     + ", repeatCount=" + event.getRepeatCount()
3743                     + ", policyFlags=" + policyFlags);
3744         }
3745
3746         KeyEvent fallbackEvent = null;
3747         if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3748             final KeyCharacterMap kcm = event.getKeyCharacterMap();
3749             final int keyCode = event.getKeyCode();
3750             final int metaState = event.getMetaState();
3751             final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
3752                     && event.getRepeatCount() == 0;
3753
3754             // Check for fallback actions specified by the key character map.
3755             final FallbackAction fallbackAction;
3756             if (initialDown) {
3757                 fallbackAction = kcm.getFallbackAction(keyCode, metaState);
3758             } else {
3759                 fallbackAction = mFallbackActions.get(keyCode);
3760             }
3761
3762             if (fallbackAction != null) {
3763                 if (DEBUG_INPUT) {
3764                     Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode
3765                             + " metaState=" + Integer.toHexString(fallbackAction.metaState));
3766                 }
3767
3768                 final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
3769                 fallbackEvent = KeyEvent.obtain(
3770                         event.getDownTime(), event.getEventTime(),
3771                         event.getAction(), fallbackAction.keyCode,
3772                         event.getRepeatCount(), fallbackAction.metaState,
3773                         event.getDeviceId(), event.getScanCode(),
3774                         flags, event.getSource(), null);
3775
3776                 if (!interceptFallback(win, fallbackEvent, policyFlags)) {
3777                     fallbackEvent.recycle();
3778                     fallbackEvent = null;
3779                 }
3780
3781                 if (initialDown) {
3782                     mFallbackActions.put(keyCode, fallbackAction);
3783                 } else if (event.getAction() == KeyEvent.ACTION_UP) {
3784                     mFallbackActions.remove(keyCode);
3785                     fallbackAction.recycle();
3786                 }
3787             }
3788         }
3789
3790         if (DEBUG_INPUT) {
3791             if (fallbackEvent == null) {
3792                 Slog.d(TAG, "No fallback.");
3793             } else {
3794                 Slog.d(TAG, "Performing fallback: " + fallbackEvent);
3795             }
3796         }
3797         return fallbackEvent;
3798     }
3799
3800     private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
3801         int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
3802         if ((actions & ACTION_PASS_TO_USER) != 0) {
3803             long delayMillis = interceptKeyBeforeDispatching(
3804                     win, fallbackEvent, policyFlags);
3805             if (delayMillis == 0) {
3806                 return true;
3807             }
3808         }
3809         return false;
3810     }
3811
3812     @Override
3813     public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
3814             throws RemoteException {
3815         synchronized (mLock) {
3816             IShortcutService service = mShortcutKeyServices.get(shortcutCode);
3817             if (service != null && service.asBinder().pingBinder()) {
3818                 throw new RemoteException("Key already exists.");
3819             }
3820
3821             mShortcutKeyServices.put(shortcutCode, shortcutService);
3822         }
3823     }
3824
3825     @Override
3826     public void onKeyguardOccludedChangedLw(boolean occluded) {
3827         if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
3828             mPendingKeyguardOccluded = occluded;
3829             mKeyguardOccludedChanged = true;
3830         } else {
3831             setKeyguardOccludedLw(occluded);
3832         }
3833     }
3834
3835     private int handleStartTransitionForKeyguardLw(int transit, @Nullable Animation anim) {
3836         if (mKeyguardOccludedChanged) {
3837             if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded="
3838                     + mPendingKeyguardOccluded);
3839             mKeyguardOccludedChanged = false;
3840             if (setKeyguardOccludedLw(mPendingKeyguardOccluded)) {
3841                 return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER;
3842             }
3843         }
3844         if (AppTransition.isKeyguardGoingAwayTransit(transit)) {
3845             if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation");
3846             final long startTime = anim != null
3847                     ? SystemClock.uptimeMillis() + anim.getStartOffset()
3848                     : SystemClock.uptimeMillis();
3849             final long duration = anim != null
3850                     ? anim.getDuration()
3851                     : 0;
3852             startKeyguardExitAnimation(startTime, duration);
3853         }
3854         return 0;
3855     }
3856
3857     private void launchAssistLongPressAction() {
3858         performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
3859         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
3860
3861         // launch the search activity
3862         Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
3863         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3864         try {
3865             // TODO: This only stops the factory-installed search manager.
3866             // Need to formalize an API to handle others
3867             SearchManager searchManager = getSearchManager();
3868             if (searchManager != null) {
3869                 searchManager.stopSearch();
3870             }
3871             startActivityAsUser(intent, UserHandle.CURRENT);
3872         } catch (ActivityNotFoundException e) {
3873             Slog.w(TAG, "No activity to handle assist long press action.", e);
3874         }
3875     }
3876
3877     private void launchAssistAction(String hint, int deviceId) {
3878         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
3879         if (!isUserSetupComplete()) {
3880             // Disable opening assist window during setup
3881             return;
3882         }
3883         Bundle args = null;
3884         if (deviceId > Integer.MIN_VALUE) {
3885             args = new Bundle();
3886             args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
3887         }
3888         if ((mContext.getResources().getConfiguration().uiMode
3889                 & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
3890             // On TV, use legacy handling until assistants are implemented in the proper way.
3891             ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
3892                     .launchLegacyAssist(hint, UserHandle.myUserId(), args);
3893         } else {
3894             if (hint != null) {
3895                 if (args == null) {
3896                     args = new Bundle();
3897                 }
3898                 args.putBoolean(hint, true);
3899             }
3900             StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3901             if (statusbar != null) {
3902                 statusbar.startAssist(args);
3903             }
3904         }
3905     }
3906
3907     private void startActivityAsUser(Intent intent, UserHandle handle) {
3908         if (isUserSetupComplete()) {
3909             mContext.startActivityAsUser(intent, handle);
3910         } else {
3911             Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent);
3912         }
3913     }
3914
3915     private SearchManager getSearchManager() {
3916         if (mSearchManager == null) {
3917             mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
3918         }
3919         return mSearchManager;
3920     }
3921
3922     private void preloadRecentApps() {
3923         mPreloadedRecentApps = true;
3924         StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3925         if (statusbar != null) {
3926             statusbar.preloadRecentApps();
3927         }
3928     }
3929
3930     private void cancelPreloadRecentApps() {
3931         if (mPreloadedRecentApps) {
3932             mPreloadedRecentApps = false;
3933             StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3934             if (statusbar != null) {
3935                 statusbar.cancelPreloadRecentApps();
3936             }
3937         }
3938     }
3939
3940     private void toggleRecentApps() {
3941         mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3942         StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3943         if (statusbar != null) {
3944             statusbar.toggleRecentApps();
3945         }
3946     }
3947
3948     @Override
3949     public void showRecentApps(boolean fromHome) {
3950         mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
3951         mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget();
3952     }
3953
3954     private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
3955         mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3956         StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3957         if (statusbar != null) {
3958             statusbar.showRecentApps(triggeredFromAltTab, fromHome);
3959         }
3960     }
3961
3962     private void toggleKeyboardShortcutsMenu(int deviceId) {
3963         StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3964         if (statusbar != null) {
3965             statusbar.toggleKeyboardShortcutsMenu(deviceId);
3966         }
3967     }
3968
3969     private void dismissKeyboardShortcutsMenu() {
3970         StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3971         if (statusbar != null) {
3972             statusbar.dismissKeyboardShortcutsMenu();
3973         }
3974     }
3975
3976     private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
3977         mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3978         StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3979         if (statusbar != null) {
3980             statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
3981         }
3982     }
3983
3984     void launchHomeFromHotKey() {
3985         launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/);
3986     }
3987
3988     /**
3989      * A home key -> launch home action was detected.  Take the appropriate action
3990      * given the situation with the keyguard.
3991      */
3992     void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) {
3993         if (respectKeyguard) {
3994             if (isKeyguardShowingAndNotOccluded()) {
3995                 // don't launch home if keyguard showing
3996                 return;
3997             }
3998
3999             if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) {
4000                 // when in keyguard restricted mode, must first verify unlock
4001                 // before launching home
4002                 mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
4003                     @Override
4004                     public void onKeyguardExitResult(boolean success) {
4005                         if (success) {
4006                             try {
4007                                 ActivityManager.getService().stopAppSwitches();
4008                             } catch (RemoteException e) {
4009                             }
4010                             sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
4011                             startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
4012                         }
4013                     }
4014                 });
4015                 return;
4016             }
4017         }
4018
4019         // no keyguard stuff to worry about, just launch home!
4020         try {
4021             ActivityManager.getService().stopAppSwitches();
4022         } catch (RemoteException e) {
4023         }
4024         if (mRecentsVisible) {
4025             // Hide Recents and notify it to launch Home
4026             if (awakenFromDreams) {
4027                 awakenDreams();
4028             }
4029             hideRecentApps(false, true);
4030         } else {
4031             // Otherwise, just launch Home
4032             sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
4033             startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
4034         }
4035     }
4036
4037     private final Runnable mClearHideNavigationFlag = new Runnable() {
4038         @Override
4039         public void run() {
4040             synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
4041                 // Clear flags.
4042                 mForceClearedSystemUiFlags &=
4043                         ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
4044             }
4045             mWindowManagerFuncs.reevaluateStatusBarVisibility();
4046         }
4047     };
4048
4049     /**
4050      * Input handler used while nav bar is hidden.  Captures any touch on the screen,
4051      * to determine when the nav bar should be shown and prevent applications from
4052      * receiving those touches.
4053      */
4054     final class HideNavInputEventReceiver extends InputEventReceiver {
4055         public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
4056             super(inputChannel, looper);
4057         }
4058
4059         @Override
4060         public void onInputEvent(InputEvent event) {
4061             boolean handled = false;
4062             try {
4063                 if (event instanceof MotionEvent
4064                         && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
4065                     final MotionEvent motionEvent = (MotionEvent)event;
4066                     if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
4067                         // When the user taps down, we re-show the nav bar.
4068                         boolean changed = false;
4069                         synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
4070                             if (mInputConsumer == null) {
4071                                 return;
4072                             }
4073                             // Any user activity always causes us to show the
4074                             // navigation controls, if they had been hidden.
4075                             // We also clear the low profile and only content
4076                             // flags so that tapping on the screen will atomically
4077                             // restore all currently hidden screen decorations.
4078                             int newVal = mResettingSystemUiFlags |
4079                                     View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
4080                                     View.SYSTEM_UI_FLAG_LOW_PROFILE |
4081                                     View.SYSTEM_UI_FLAG_FULLSCREEN;
4082                             if (mResettingSystemUiFlags != newVal) {
4083                                 mResettingSystemUiFlags = newVal;
4084                                 changed = true;
4085                             }
4086                             // We don't allow the system's nav bar to be hidden
4087                             // again for 1 second, to prevent applications from
4088                             // spamming us and keeping it from being shown.
4089                             newVal = mForceClearedSystemUiFlags |
4090                                     View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
4091                             if (mForceClearedSystemUiFlags != newVal) {
4092                                 mForceClearedSystemUiFlags = newVal;
4093                                 changed = true;
4094                                 mHandler.postDelayed(mClearHideNavigationFlag, 1000);
4095                             }
4096                         }
4097                         if (changed) {
4098                             mWindowManagerFuncs.reevaluateStatusBarVisibility();
4099                         }
4100                     }
4101                 }
4102             } finally {
4103                 finishInputEvent(event, handled);
4104             }
4105         }
4106     }
4107
4108     @Override
4109     public void setRecentsVisibilityLw(boolean visible) {
4110         mRecentsVisible = visible;
4111     }
4112
4113     @Override
4114     public void setTvPipVisibilityLw(boolean visible) {
4115         mTvPictureInPictureVisible = visible;
4116     }
4117
4118     @Override
4119     public int adjustSystemUiVisibilityLw(int visibility) {
4120         mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4121         mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4122
4123         // Reset any bits in mForceClearingStatusBarVisibility that
4124         // are now clear.
4125         mResettingSystemUiFlags &= visibility;
4126         // Clear any bits in the new visibility that are currently being
4127         // force cleared, before reporting it.
4128         return visibility & ~mResettingSystemUiFlags
4129                 & ~mForceClearedSystemUiFlags;
4130     }
4131
4132     @Override
4133     public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
4134             int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets,
4135             Rect outStableInsets, Rect outOutsets) {
4136         final int fl = PolicyControl.getWindowFlags(null, attrs);
4137         final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
4138         final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
4139
4140         final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
4141         if (useOutsets) {
4142             int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
4143             if (outset > 0) {
4144                 if (displayRotation == Surface.ROTATION_0) {
4145                     outOutsets.bottom += outset;
4146                 } else if (displayRotation == Surface.ROTATION_90) {
4147                     outOutsets.right += outset;
4148                 } else if (displayRotation == Surface.ROTATION_180) {
4149                     outOutsets.top += outset;
4150                 } else if (displayRotation == Surface.ROTATION_270) {
4151                     outOutsets.left += outset;
4152                 }
4153             }
4154         }
4155
4156         if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4157                 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4158             int availRight, availBottom;
4159             if (canHideNavigationBar() &&
4160                     (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
4161                 availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4162                 availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4163             } else {
4164                 availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
4165                 availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4166             }
4167             if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4168                 if ((fl & FLAG_FULLSCREEN) != 0) {
4169                     outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop,
4170                             availRight - mStableFullscreenRight,
4171                             availBottom - mStableFullscreenBottom);
4172                 } else {
4173                     outContentInsets.set(mStableLeft, mStableTop,
4174                             availRight - mStableRight, availBottom - mStableBottom);
4175                 }
4176             } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
4177                 outContentInsets.setEmpty();
4178             } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
4179                         | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
4180                 outContentInsets.set(mCurLeft, mCurTop,
4181                         availRight - mCurRight, availBottom - mCurBottom);
4182             } else {
4183                 outContentInsets.set(mCurLeft, mCurTop,
4184                         availRight - mCurRight, availBottom - mCurBottom);
4185             }
4186
4187             outStableInsets.set(mStableLeft, mStableTop,
4188                     availRight - mStableRight, availBottom - mStableBottom);
4189             if (taskBounds != null) {
4190                 calculateRelevantTaskInsets(taskBounds, outContentInsets,
4191                         displayWidth, displayHeight);
4192                 calculateRelevantTaskInsets(taskBounds, outStableInsets,
4193                         displayWidth, displayHeight);
4194             }
4195             return mForceShowSystemBars;
4196         }
4197         outContentInsets.setEmpty();
4198         outStableInsets.setEmpty();
4199         return mForceShowSystemBars;
4200     }
4201
4202     /**
4203      * For any given task bounds, the insets relevant for these bounds given the insets relevant
4204      * for the entire display.
4205      */
4206     private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth,
4207             int displayHeight) {
4208         mTmpRect.set(0, 0, displayWidth, displayHeight);
4209         mTmpRect.inset(inOutInsets);
4210         mTmpRect.intersect(taskBounds);
4211         int leftInset = mTmpRect.left - taskBounds.left;
4212         int topInset = mTmpRect.top - taskBounds.top;
4213         int rightInset = taskBounds.right - mTmpRect.right;
4214         int bottomInset = taskBounds.bottom - mTmpRect.bottom;
4215         inOutInsets.set(leftInset, topInset, rightInset, bottomInset);
4216     }
4217
4218     private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
4219         return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
4220                 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
4221     }
4222
4223     /** {@inheritDoc} */
4224     @Override
4225     public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
4226                               int displayRotation, int uiMode) {
4227         mDisplayRotation = displayRotation;
4228         final int overscanLeft, overscanTop, overscanRight, overscanBottom;
4229         if (isDefaultDisplay) {
4230             switch (displayRotation) {
4231                 case Surface.ROTATION_90:
4232                     overscanLeft = mOverscanTop;
4233                     overscanTop = mOverscanRight;
4234                     overscanRight = mOverscanBottom;
4235                     overscanBottom = mOverscanLeft;
4236                     break;
4237                 case Surface.ROTATION_180:
4238                     overscanLeft = mOverscanRight;
4239                     overscanTop = mOverscanBottom;
4240                     overscanRight = mOverscanLeft;
4241                     overscanBottom = mOverscanTop;
4242                     break;
4243                 case Surface.ROTATION_270:
4244                     overscanLeft = mOverscanBottom;
4245                     overscanTop = mOverscanLeft;
4246                     overscanRight = mOverscanTop;
4247                     overscanBottom = mOverscanRight;
4248                     break;
4249                 default:
4250                     overscanLeft = mOverscanLeft;
4251                     overscanTop = mOverscanTop;
4252                     overscanRight = mOverscanRight;
4253                     overscanBottom = mOverscanBottom;
4254                     break;
4255             }
4256         } else {
4257             overscanLeft = 0;
4258             overscanTop = 0;
4259             overscanRight = 0;
4260             overscanBottom = 0;
4261         }
4262         mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0;
4263         mOverscanScreenTop = mRestrictedOverscanScreenTop = 0;
4264         mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth;
4265         mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight;
4266         mSystemLeft = 0;
4267         mSystemTop = 0;
4268         mSystemRight = displayWidth;
4269         mSystemBottom = displayHeight;
4270         mUnrestrictedScreenLeft = overscanLeft;
4271         mUnrestrictedScreenTop = overscanTop;
4272         mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight;
4273         mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom;
4274         mRestrictedScreenLeft = mUnrestrictedScreenLeft;
4275         mRestrictedScreenTop = mUnrestrictedScreenTop;
4276         mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth;
4277         mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight;
4278         mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft
4279                 = mCurLeft = mUnrestrictedScreenLeft;
4280         mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop
4281                 = mCurTop = mUnrestrictedScreenTop;
4282         mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight
4283                 = mCurRight = displayWidth - overscanRight;
4284         mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom
4285                 = mCurBottom = displayHeight - overscanBottom;
4286         mDockLayer = 0x10000000;
4287         mStatusBarLayer = -1;
4288
4289         // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
4290         final Rect pf = mTmpParentFrame;
4291         final Rect df = mTmpDisplayFrame;
4292         final Rect of = mTmpOverscanFrame;
4293         final Rect vf = mTmpVisibleFrame;
4294         final Rect dcf = mTmpDecorFrame;
4295         pf.left = df.left = of.left = vf.left = mDockLeft;
4296         pf.top = df.top = of.top = vf.top = mDockTop;
4297         pf.right = df.right = of.right = vf.right = mDockRight;
4298         pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom;
4299         dcf.setEmpty();  // Decor frame N/A for system bars.
4300
4301         if (isDefaultDisplay) {
4302             // For purposes of putting out fake window up to steal focus, we will
4303             // drive nav being hidden only by whether it is requested.
4304             final int sysui = mLastSystemUiFlags;
4305             boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
4306             boolean navTranslucent = (sysui
4307                     & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
4308             boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
4309             boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
4310             boolean navAllowedHidden = immersive || immersiveSticky;
4311             navTranslucent &= !immersiveSticky;  // transient trumps translucent
4312             boolean isKeyguardShowing = isStatusBarKeyguard() && !mKeyguardOccluded;
4313             if (!isKeyguardShowing) {
4314                 navTranslucent &= areTranslucentBarsAllowed();
4315             }
4316             boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null
4317                     && mStatusBar.getAttrs().height == MATCH_PARENT
4318                     && mStatusBar.getAttrs().width == MATCH_PARENT;
4319
4320             // When the navigation bar isn't visible, we put up a fake
4321             // input window to catch all touch events.  This way we can
4322             // detect when the user presses anywhere to bring back the nav
4323             // bar and ensure the application doesn't see the event.
4324             if (navVisible || navAllowedHidden) {
4325                 if (mInputConsumer != null) {
4326                     mHandler.sendMessage(
4327                             mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
4328                     mInputConsumer = null;
4329                 }
4330             } else if (mInputConsumer == null) {
4331                 mInputConsumer = mWindowManagerFuncs.createInputConsumer(mHandler.getLooper(),
4332                         INPUT_CONSUMER_NAVIGATION,
4333                         (channel, looper) -> new HideNavInputEventReceiver(channel, looper));
4334                 // As long as mInputConsumer is active, hover events are not dispatched to the app
4335                 // and the pointer icon is likely to become stale. Hide it to avoid confusion.
4336                 InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL);
4337             }
4338
4339             // For purposes of positioning and showing the nav bar, if we have
4340             // decided that it can't be hidden (because of the screen aspect ratio),
4341             // then take that into account.
4342             navVisible |= !canHideNavigationBar();
4343
4344             boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight,
4345                     displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom, dcf, navVisible, navTranslucent,
4346                     navAllowedHidden, statusBarExpandedNotKeyguard);
4347             if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
4348                     mDockLeft, mDockTop, mDockRight, mDockBottom));
4349             updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing);
4350             if (updateSysUiVisibility) {
4351                 updateSystemUiVisibilityLw();
4352             }
4353         }
4354     }
4355
4356     private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui,
4357             boolean isKeyguardShowing) {
4358         // decide where the status bar goes ahead of time
4359         if (mStatusBar != null) {
4360             // apply any navigation bar insets
4361             pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4362             pf.top = df.top = of.top = mUnrestrictedScreenTop;
4363             pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4364             pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
4365                     + mUnrestrictedScreenTop;
4366             vf.left = mStableLeft;
4367             vf.top = mStableTop;
4368             vf.right = mStableRight;
4369             vf.bottom = mStableBottom;
4370
4371             mStatusBarLayer = mStatusBar.getSurfaceLayer();
4372
4373             // Let the status bar determine its size.
4374             mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
4375                     vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
4376                     dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */);
4377
4378             // For layout, the status bar is always at the top with our fixed height.
4379             mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
4380
4381             boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
4382             boolean statusBarTranslucent = (sysui
4383                     & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
4384             if (!isKeyguardShowing) {
4385                 statusBarTranslucent &= areTranslucentBarsAllowed();
4386             }
4387
4388             // If the status bar is hidden, we don't want to cause
4389             // windows behind it to scroll.
4390             if (mStatusBar.isVisibleLw() && !statusBarTransient) {
4391                 // Status bar may go away, so the screen area it occupies
4392                 // is available to apps but just covering them when the
4393                 // status bar is visible.
4394                 mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
4395
4396                 mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4397                 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4398                 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4399                 mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4400
4401                 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " +
4402                         String.format(
4403                                 "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
4404                                 mDockLeft, mDockTop, mDockRight, mDockBottom,
4405                                 mContentLeft, mContentTop, mContentRight, mContentBottom,
4406                                 mCurLeft, mCurTop, mCurRight, mCurBottom));
4407             }
4408             if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
4409                     && !statusBarTransient && !statusBarTranslucent
4410                     && !mStatusBarController.wasRecentlyTranslucent()) {
4411                 // If the opaque status bar is currently requested to be visible,
4412                 // and not in the process of animating on or off, then
4413                 // we can tell the app that it is covered by it.
4414                 mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
4415             }
4416             if (mStatusBarController.checkHiddenLw()) {
4417                 return true;
4418             }
4419         }
4420         return false;
4421     }
4422
4423     private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation,
4424             int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf,
4425             boolean navVisible, boolean navTranslucent, boolean navAllowedHidden,
4426             boolean statusBarExpandedNotKeyguard) {
4427         if (mNavigationBar != null) {
4428             boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
4429             // Force the navigation bar to its appropriate place and
4430             // size.  We need to do this directly, instead of relying on
4431             // it to bubble up from the nav bar, because this needs to
4432             // change atomically with screen rotations.
4433             mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight,
4434                     displayRotation);
4435             if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
4436                 // It's a system nav bar or a portrait screen; nav bar goes on bottom.
4437                 int top = displayHeight - overscanBottom
4438                         - getNavigationBarHeight(displayRotation, uiMode);
4439                 mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
4440                 mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
4441                 if (transientNavBarShowing) {
4442                     mNavigationBarController.setBarShowingLw(true);
4443                 } else if (navVisible) {
4444                     mNavigationBarController.setBarShowingLw(true);
4445                     mDockBottom = mTmpNavigationFrame.top;
4446                     mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
4447                     mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
4448                 } else {
4449                     // We currently want to hide the navigation UI - unless we expanded the status
4450                     // bar.
4451                     mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4452                 }
4453                 if (navVisible && !navTranslucent && !navAllowedHidden
4454                         && !mNavigationBar.isAnimatingLw()
4455                         && !mNavigationBarController.wasRecentlyTranslucent()) {
4456                     // If the opaque nav bar is currently requested to be visible,
4457                     // and not in the process of animating on or off, then
4458                     // we can tell the app that it is covered by it.
4459                     mSystemBottom = mTmpNavigationFrame.top;
4460                 }
4461             } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4462                 // Landscape screen; nav bar goes to the right.
4463                 int left = displayWidth - overscanRight
4464                         - getNavigationBarWidth(displayRotation, uiMode);
4465                 mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
4466                 mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
4467                 if (transientNavBarShowing) {
4468                     mNavigationBarController.setBarShowingLw(true);
4469                 } else if (navVisible) {
4470                     mNavigationBarController.setBarShowingLw(true);
4471                     mDockRight = mTmpNavigationFrame.left;
4472                     mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4473                     mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4474                 } else {
4475                     // We currently want to hide the navigation UI - unless we expanded the status
4476                     // bar.
4477                     mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4478                 }
4479                 if (navVisible && !navTranslucent && !navAllowedHidden
4480                         && !mNavigationBar.isAnimatingLw()
4481                         && !mNavigationBarController.wasRecentlyTranslucent()) {
4482                     // If the nav bar is currently requested to be visible,
4483                     // and not in the process of animating on or off, then
4484                     // we can tell the app that it is covered by it.
4485                     mSystemRight = mTmpNavigationFrame.left;
4486                 }
4487             } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4488                 // Seascape screen; nav bar goes to the left.
4489                 int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode);
4490                 mTmpNavigationFrame.set(overscanLeft, 0, right, displayHeight);
4491                 mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right;
4492                 if (transientNavBarShowing) {
4493                     mNavigationBarController.setBarShowingLw(true);
4494                 } else if (navVisible) {
4495                     mNavigationBarController.setBarShowingLw(true);
4496                     mDockLeft = mTmpNavigationFrame.right;
4497                     // TODO: not so sure about those:
4498                     mRestrictedScreenLeft = mRestrictedOverscanScreenLeft = mDockLeft;
4499                     mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4500                     mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4501                 } else {
4502                     // We currently want to hide the navigation UI - unless we expanded the status
4503                     // bar.
4504                     mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4505                 }
4506                 if (navVisible && !navTranslucent && !navAllowedHidden
4507                         && !mNavigationBar.isAnimatingLw()
4508                         && !mNavigationBarController.wasRecentlyTranslucent()) {
4509                     // If the nav bar is currently requested to be visible,
4510                     // and not in the process of animating on or off, then
4511                     // we can tell the app that it is covered by it.
4512                     mSystemLeft = mTmpNavigationFrame.right;
4513                 }
4514             }
4515             // Make sure the content and current rectangles are updated to
4516             // account for the restrictions from the navigation bar.
4517             mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4518             mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4519             mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4520             mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4521             mStatusBarLayer = mNavigationBar.getSurfaceLayer();
4522             // And compute the final frame.
4523             mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
4524                     mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
4525                     mTmpNavigationFrame, mTmpNavigationFrame);
4526             if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
4527             if (mNavigationBarController.checkHiddenLw()) {
4528                 return true;
4529             }
4530         }
4531         return false;
4532     }
4533
4534     private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
4535         if (mNavigationBarCanMove && displayWidth > displayHeight) {
4536             if (displayRotation == Surface.ROTATION_270) {
4537                 return NAV_BAR_LEFT;
4538             } else {
4539                 return NAV_BAR_RIGHT;
4540             }
4541         }
4542         return NAV_BAR_BOTTOM;
4543     }
4544
4545     /** {@inheritDoc} */
4546     @Override
4547     public int getSystemDecorLayerLw() {
4548         if (mStatusBar != null && mStatusBar.isVisibleLw()) {
4549             return mStatusBar.getSurfaceLayer();
4550         }
4551
4552         if (mNavigationBar != null && mNavigationBar.isVisibleLw()) {
4553             return mNavigationBar.getSurfaceLayer();
4554         }
4555
4556         return 0;
4557     }
4558
4559     @Override
4560     public void getContentRectLw(Rect r) {
4561         r.set(mContentLeft, mContentTop, mContentRight, mContentBottom);
4562     }
4563
4564     void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
4565             boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
4566         if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
4567             // Here's a special case: if this attached window is a panel that is
4568             // above the dock window, and the window it is attached to is below
4569             // the dock window, then the frames we computed for the window it is
4570             // attached to can not be used because the dock is effectively part
4571             // of the underlying window and the attached window is floating on top
4572             // of the whole thing.  So, we ignore the attached window and explicitly
4573             // compute the frames that would be appropriate without the dock.
4574             df.left = of.left = cf.left = vf.left = mDockLeft;
4575             df.top = of.top = cf.top = vf.top = mDockTop;
4576             df.right = of.right = cf.right = vf.right = mDockRight;
4577             df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom;
4578         } else {
4579             // The effective display frame of the attached window depends on
4580             // whether it is taking care of insetting its content.  If not,
4581             // we need to use the parent's content frame so that the entire
4582             // window is positioned within that content.  Otherwise we can use
4583             // the overscan frame and let the attached window take care of
4584             // positioning its content appropriately.
4585             if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4586                 // Set the content frame of the attached window to the parent's decor frame
4587                 // (same as content frame when IME isn't present) if specifically requested by
4588                 // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
4589                 // Otherwise, use the overscan frame.
4590                 cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
4591                         ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
4592             } else {
4593                 // If the window is resizing, then we want to base the content
4594                 // frame on our attached content frame to resize...  however,
4595                 // things can be tricky if the attached window is NOT in resize
4596                 // mode, in which case its content frame will be larger.
4597                 // Ungh.  So to deal with that, make sure the content frame
4598                 // we end up using is not covering the IM dock.
4599                 cf.set(attached.getContentFrameLw());
4600                 if (attached.isVoiceInteraction()) {
4601                     if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft;
4602                     if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop;
4603                     if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight;
4604                     if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom;
4605                 } else if (attached.getSurfaceLayer() < mDockLayer) {
4606                     if (cf.left < mContentLeft) cf.left = mContentLeft;
4607                     if (cf.top < mContentTop) cf.top = mContentTop;
4608                     if (cf.right > mContentRight) cf.right = mContentRight;
4609                     if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
4610                 }
4611             }
4612             df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
4613             of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
4614             vf.set(attached.getVisibleFrameLw());
4615         }
4616         // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
4617         // window should be positioned relative to its parent or the entire
4618         // screen.
4619         pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
4620                 ? attached.getFrameLw() : df);
4621     }
4622
4623     private void applyStableConstraints(int sysui, int fl, Rect r) {
4624         if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4625             // If app is requesting a stable layout, don't let the
4626             // content insets go below the stable values.
4627             if ((fl & FLAG_FULLSCREEN) != 0) {
4628                 if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft;
4629                 if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop;
4630                 if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight;
4631                 if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom;
4632             } else {
4633                 if (r.left < mStableLeft) r.left = mStableLeft;
4634                 if (r.top < mStableTop) r.top = mStableTop;
4635                 if (r.right > mStableRight) r.right = mStableRight;
4636                 if (r.bottom > mStableBottom) r.bottom = mStableBottom;
4637             }
4638         }
4639     }
4640
4641     private boolean canReceiveInput(WindowState win) {
4642         boolean notFocusable =
4643                 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
4644         boolean altFocusableIm =
4645                 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
4646         boolean notFocusableForIm = notFocusable ^ altFocusableIm;
4647         return !notFocusableForIm;
4648     }
4649
4650     /** {@inheritDoc} */
4651     @Override
4652     public void layoutWindowLw(WindowState win, WindowState attached) {
4653         // We've already done the navigation bar and status bar. If the status bar can receive
4654         // input, we need to layout it again to accomodate for the IME window.
4655         if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) {
4656             return;
4657         }
4658         final WindowManager.LayoutParams attrs = win.getAttrs();
4659         final boolean isDefaultDisplay = win.isDefaultDisplay();
4660         final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
4661                 (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
4662         if (needsToOffsetInputMethodTarget) {
4663             if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
4664             offsetInputMethodWindowLw(mLastInputMethodWindow);
4665         }
4666
4667         final int fl = PolicyControl.getWindowFlags(win, attrs);
4668         final int pfl = attrs.privateFlags;
4669         final int sim = attrs.softInputMode;
4670         final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
4671
4672         final Rect pf = mTmpParentFrame;
4673         final Rect df = mTmpDisplayFrame;
4674         final Rect of = mTmpOverscanFrame;
4675         final Rect cf = mTmpContentFrame;
4676         final Rect vf = mTmpVisibleFrame;
4677         final Rect dcf = mTmpDecorFrame;
4678         final Rect sf = mTmpStableFrame;
4679         Rect osf = null;
4680         dcf.setEmpty();
4681
4682         final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
4683                 && mNavigationBar != null && mNavigationBar.isVisibleLw());
4684
4685         final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
4686
4687         if (isDefaultDisplay) {
4688             sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom);
4689         } else {
4690             sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom);
4691         }
4692
4693         if (!isDefaultDisplay) {
4694             if (attached != null) {
4695                 // If this window is attached to another, our display
4696                 // frame is the same as the one we are attached to.
4697                 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4698             } else {
4699                 // Give the window full screen.
4700                 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4701                 pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4702                 pf.right = df.right = of.right = cf.right
4703                         = mOverscanScreenLeft + mOverscanScreenWidth;
4704                 pf.bottom = df.bottom = of.bottom = cf.bottom
4705                         = mOverscanScreenTop + mOverscanScreenHeight;
4706             }
4707         } else if (attrs.type == TYPE_INPUT_METHOD) {
4708             pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
4709             pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
4710             pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
4711             // IM dock windows layout below the nav bar...
4712             pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4713             // ...with content insets above the nav bar
4714             cf.bottom = vf.bottom = mStableBottom;
4715             if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
4716                 // The status bar forces the navigation bar while it's visible. Make sure the IME
4717                 // avoids the navigation bar in that case.
4718                 if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4719                     pf.right = df.right = of.right = cf.right = vf.right = mStableRight;
4720                 } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4721                     pf.left = df.left = of.left = cf.left = vf.left = mStableLeft;
4722                 }
4723             }
4724             // IM dock windows always go to the bottom of the screen.
4725             attrs.gravity = Gravity.BOTTOM;
4726             mDockLayer = win.getSurfaceLayer();
4727         } else if (attrs.type == TYPE_VOICE_INTERACTION) {
4728             pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4729             pf.top = df.top = of.top = mUnrestrictedScreenTop;
4730             pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4731             pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4732             if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4733                 cf.left = mDockLeft;
4734                 cf.top = mDockTop;
4735                 cf.right = mDockRight;
4736                 cf.bottom = mDockBottom;
4737             } else {
4738                 cf.left = mContentLeft;
4739                 cf.top = mContentTop;
4740                 cf.right = mContentRight;
4741                 cf.bottom = mContentBottom;
4742             }
4743             if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4744                 vf.left = mCurLeft;
4745                 vf.top = mCurTop;
4746                 vf.right = mCurRight;
4747                 vf.bottom = mCurBottom;
4748             } else {
4749                 vf.set(cf);
4750             }
4751         } else if (attrs.type == TYPE_WALLPAPER) {
4752            layoutWallpaper(win, pf, df, of, cf);
4753         } else if (win == mStatusBar) {
4754             pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4755             pf.top = df.top = of.top = mUnrestrictedScreenTop;
4756             pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4757             pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop;
4758             cf.left = vf.left = mStableLeft;
4759             cf.top = vf.top = mStableTop;
4760             cf.right = vf.right = mStableRight;
4761             vf.bottom = mStableBottom;
4762
4763             if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
4764                 cf.bottom = mContentBottom;
4765             } else {
4766                 cf.bottom = mDockBottom;
4767                 vf.bottom = mContentBottom;
4768             }
4769         } else {
4770
4771             // Default policy decor for the default display
4772             dcf.left = mSystemLeft;
4773             dcf.top = mSystemTop;
4774             dcf.right = mSystemRight;
4775             dcf.bottom = mSystemBottom;
4776             final boolean inheritTranslucentDecor = (attrs.privateFlags
4777                     & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0;
4778             final boolean isAppWindow =
4779                     attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW &&
4780                     attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
4781             final boolean topAtRest =
4782                     win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
4783             if (isAppWindow && !inheritTranslucentDecor && !topAtRest) {
4784                 if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
4785                         && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0
4786                         && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
4787                         && (fl & WindowManager.LayoutParams.
4788                                 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
4789                         && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) {
4790                     // Ensure policy decor includes status bar
4791                     dcf.top = mStableTop;
4792                 }
4793                 if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0
4794                         && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
4795                         && (fl & WindowManager.LayoutParams.
4796                                 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
4797                     // Ensure policy decor includes navigation bar
4798                     dcf.bottom = mStableBottom;
4799                     dcf.right = mStableRight;
4800                 }
4801             }
4802
4803             if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4804                     == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4805                 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
4806                             + "): IN_SCREEN, INSET_DECOR");
4807                 // This is the case for a normal activity window: we want it
4808                 // to cover all of the screen space, and it can take care of
4809                 // moving its contents to account for screen decorations that
4810                 // intrude into that space.
4811                 if (attached != null) {
4812                     // If this window is attached to another, our display
4813                     // frame is the same as the one we are attached to.
4814                     setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4815                 } else {
4816                     if (attrs.type == TYPE_STATUS_BAR_PANEL
4817                             || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
4818                         // Status bar panels are the only windows who can go on top of
4819                         // the status bar.  They are protected by the STATUS_BAR_SERVICE
4820                         // permission, so they have the same privileges as the status
4821                         // bar itself.
4822                         //
4823                         // However, they should still dodge the navigation bar if it exists.
4824
4825                         pf.left = df.left = of.left = hasNavBar
4826                                 ? mDockLeft : mUnrestrictedScreenLeft;
4827                         pf.top = df.top = of.top = mUnrestrictedScreenTop;
4828                         pf.right = df.right = of.right = hasNavBar
4829                                 ? mRestrictedScreenLeft+mRestrictedScreenWidth
4830                                 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4831                         pf.bottom = df.bottom = of.bottom = hasNavBar
4832                                 ? mRestrictedScreenTop+mRestrictedScreenHeight
4833                                 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4834
4835                         if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4836                                         "Laying out status bar window: (%d,%d - %d,%d)",
4837                                         pf.left, pf.top, pf.right, pf.bottom));
4838                     } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4839                             && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4840                             && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4841                         // Asking to layout into the overscan region, so give it that pure
4842                         // unrestricted area.
4843                         pf.left = df.left = of.left = mOverscanScreenLeft;
4844                         pf.top = df.top = of.top = mOverscanScreenTop;
4845                         pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth;
4846                         pf.bottom = df.bottom = of.bottom = mOverscanScreenTop
4847                                 + mOverscanScreenHeight;
4848                     } else if (canHideNavigationBar()
4849                             && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4850                             && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4851                             && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4852                         // Asking for layout as if the nav bar is hidden, lets the
4853                         // application extend into the unrestricted overscan screen area.  We
4854                         // only do this for application windows to ensure no window that
4855                         // can be above the nav bar can do this.
4856                         pf.left = df.left = mOverscanScreenLeft;
4857                         pf.top = df.top = mOverscanScreenTop;
4858                         pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
4859                         pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
4860                         // We need to tell the app about where the frame inside the overscan
4861                         // is, so it can inset its content by that amount -- it didn't ask
4862                         // to actually extend itself into the overscan region.
4863                         of.left = mUnrestrictedScreenLeft;
4864                         of.top = mUnrestrictedScreenTop;
4865                         of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4866                         of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4867                     } else {
4868                         pf.left = df.left = mRestrictedOverscanScreenLeft;
4869                         pf.top = df.top = mRestrictedOverscanScreenTop;
4870                         pf.right = df.right = mRestrictedOverscanScreenLeft
4871                                 + mRestrictedOverscanScreenWidth;
4872                         pf.bottom = df.bottom = mRestrictedOverscanScreenTop
4873                                 + mRestrictedOverscanScreenHeight;
4874                         // We need to tell the app about where the frame inside the overscan
4875                         // is, so it can inset its content by that amount -- it didn't ask
4876                         // to actually extend itself into the overscan region.
4877                         of.left = mUnrestrictedScreenLeft;
4878                         of.top = mUnrestrictedScreenTop;
4879                         of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4880                         of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4881                     }
4882
4883                     if ((fl & FLAG_FULLSCREEN) == 0) {
4884                         if (win.isVoiceInteraction()) {
4885                             cf.left = mVoiceContentLeft;
4886                             cf.top = mVoiceContentTop;
4887                             cf.right = mVoiceContentRight;
4888                             cf.bottom = mVoiceContentBottom;
4889                         } else {
4890                             if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4891                                 cf.left = mDockLeft;
4892                                 cf.top = mDockTop;
4893                                 cf.right = mDockRight;
4894                                 cf.bottom = mDockBottom;
4895                             } else {
4896                                 cf.left = mContentLeft;
4897                                 cf.top = mContentTop;
4898                                 cf.right = mContentRight;
4899                                 cf.bottom = mContentBottom;
4900                             }
4901                         }
4902                     } else {
4903                         // Full screen windows are always given a layout that is as if the
4904                         // status bar and other transient decors are gone.  This is to avoid
4905                         // bad states when moving from a window that is not hding the
4906                         // status bar to one that is.
4907                         cf.left = mRestrictedScreenLeft;
4908                         cf.top = mRestrictedScreenTop;
4909                         cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
4910                         cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4911                     }
4912                     applyStableConstraints(sysUiFl, fl, cf);
4913                     if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4914                         vf.left = mCurLeft;
4915                         vf.top = mCurTop;
4916                         vf.right = mCurRight;
4917                         vf.bottom = mCurBottom;
4918                     } else {
4919                         vf.set(cf);
4920                     }
4921                 }
4922             } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
4923                     & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
4924                             | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
4925                 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4926                         "): IN_SCREEN");
4927                 // A window that has requested to fill the entire screen just
4928                 // gets everything, period.
4929                 if (attrs.type == TYPE_STATUS_BAR_PANEL
4930                         || attrs.type == TYPE_STATUS_BAR_SUB_PANEL
4931                         || attrs.type == TYPE_VOLUME_OVERLAY) {
4932                     pf.left = df.left = of.left = cf.left = hasNavBar
4933                             ? mDockLeft : mUnrestrictedScreenLeft;
4934                     pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
4935                     pf.right = df.right = of.right = cf.right = hasNavBar
4936                                         ? mRestrictedScreenLeft+mRestrictedScreenWidth
4937                                         : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4938                     pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar
4939                                           ? mRestrictedScreenTop+mRestrictedScreenHeight
4940                                           : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4941                     if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4942                                     "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
4943                                     pf.left, pf.top, pf.right, pf.bottom));
4944                 } else if (attrs.type == TYPE_NAVIGATION_BAR
4945                         || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
4946                     // The navigation bar has Real Ultimate Power.
4947                     pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4948                     pf.top = df.top = of.top = mUnrestrictedScreenTop;
4949                     pf.right = df.right = of.right = mUnrestrictedScreenLeft
4950                             + mUnrestrictedScreenWidth;
4951                     pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop
4952                             + mUnrestrictedScreenHeight;
4953                     if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4954                                     "Laying out navigation bar window: (%d,%d - %d,%d)",
4955                                     pf.left, pf.top, pf.right, pf.bottom));
4956                 } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
4957                                 || attrs.type == TYPE_BOOT_PROGRESS
4958                                 || attrs.type == TYPE_SCREENSHOT)
4959                         && ((fl & FLAG_FULLSCREEN) != 0)) {
4960                     // Fullscreen secure system overlays get what they ask for. Screenshot region
4961                     // selection overlay should also expand to full screen.
4962                     pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4963                     pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4964                     pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
4965                             + mOverscanScreenWidth;
4966                     pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
4967                             + mOverscanScreenHeight;
4968                 } else if (attrs.type == TYPE_BOOT_PROGRESS) {
4969                     // Boot progress screen always covers entire display.
4970                     pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4971                     pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4972                     pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
4973                             + mOverscanScreenWidth;
4974                     pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
4975                             + mOverscanScreenHeight;
4976                 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4977                         && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4978                         && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4979                     // Asking to layout into the overscan region, so give it that pure
4980                     // unrestricted area.
4981                     pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4982                     pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4983                     pf.right = df.right = of.right = cf.right
4984                             = mOverscanScreenLeft + mOverscanScreenWidth;
4985                     pf.bottom = df.bottom = of.bottom = cf.bottom
4986                             = mOverscanScreenTop + mOverscanScreenHeight;
4987                 } else if (canHideNavigationBar()
4988                         && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4989                         && (attrs.type == TYPE_STATUS_BAR
4990                             || attrs.type == TYPE_TOAST
4991                             || attrs.type == TYPE_DOCK_DIVIDER
4992                             || attrs.type == TYPE_VOICE_INTERACTION_STARTING
4993                             || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4994                             && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
4995                     // Asking for layout as if the nav bar is hidden, lets the
4996                     // application extend into the unrestricted screen area.  We
4997                     // only do this for application windows (or toasts) to ensure no window that
4998                     // can be above the nav bar can do this.
4999                     // XXX This assumes that an app asking for this will also
5000                     // ask for layout in only content.  We can't currently figure out
5001                     // what the screen would be if only laying out to hide the nav bar.
5002                     pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
5003                     pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
5004                     pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft
5005                             + mUnrestrictedScreenWidth;
5006                     pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
5007                             + mUnrestrictedScreenHeight;
5008                 } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
5009                     pf.left = df.left = of.left = mRestrictedScreenLeft;
5010                     pf.top = df.top = of.top  = mRestrictedScreenTop;
5011                     pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
5012                     pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop
5013                             + mRestrictedScreenHeight;
5014                     if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5015                         cf.left = mDockLeft;
5016                         cf.top = mDockTop;
5017                         cf.right = mDockRight;
5018                         cf.bottom = mDockBottom;
5019                     } else {
5020                         cf.left = mContentLeft;
5021                         cf.top = mContentTop;
5022                         cf.right = mContentRight;
5023                         cf.bottom = mContentBottom;
5024                     }
5025                 } else {
5026                     pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
5027                     pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
5028                     pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
5029                             + mRestrictedScreenWidth;
5030                     pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
5031                             + mRestrictedScreenHeight;
5032                 }
5033
5034                 applyStableConstraints(sysUiFl, fl, cf);
5035
5036                 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5037                     vf.left = mCurLeft;
5038                     vf.top = mCurTop;
5039                     vf.right = mCurRight;
5040                     vf.bottom = mCurBottom;
5041                 } else {
5042                     vf.set(cf);
5043                 }
5044             } else if (attached != null) {
5045                 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5046                         "): attached to " + attached);
5047                 // A child window should be placed inside of the same visible
5048                 // frame that its parent had.
5049                 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf);
5050             } else {
5051                 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5052                         "): normal window");
5053                 // Otherwise, a normal window must be placed inside the content
5054                 // of all screen decorations.
5055                 if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) {
5056                     // Status bar panels and the volume dialog are the only windows who can go on
5057                     // top of the status bar.  They are protected by the STATUS_BAR_SERVICE
5058                     // permission, so they have the same privileges as the status
5059                     // bar itself.
5060                     pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
5061                     pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
5062                     pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
5063                             + mRestrictedScreenWidth;
5064                     pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
5065                             + mRestrictedScreenHeight;
5066                 } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) {
5067                     // These dialogs are stable to interim decor changes.
5068                     pf.left = df.left = of.left = cf.left = mStableLeft;
5069                     pf.top = df.top = of.top = cf.top = mStableTop;
5070                     pf.right = df.right = of.right = cf.right = mStableRight;
5071                     pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom;
5072                 } else {
5073                     pf.left = mContentLeft;
5074                     pf.top = mContentTop;
5075                     pf.right = mContentRight;
5076                     pf.bottom = mContentBottom;
5077                     if (win.isVoiceInteraction()) {
5078                         df.left = of.left = cf.left = mVoiceContentLeft;
5079                         df.top = of.top = cf.top = mVoiceContentTop;
5080                         df.right = of.right = cf.right = mVoiceContentRight;
5081                         df.bottom = of.bottom = cf.bottom = mVoiceContentBottom;
5082                     } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5083                         df.left = of.left = cf.left = mDockLeft;
5084                         df.top = of.top = cf.top = mDockTop;
5085                         df.right = of.right = cf.right = mDockRight;
5086                         df.bottom = of.bottom = cf.bottom = mDockBottom;
5087                     } else {
5088                         df.left = of.left = cf.left = mContentLeft;
5089                         df.top = of.top = cf.top = mContentTop;
5090                         df.right = of.right = cf.right = mContentRight;
5091                         df.bottom = of.bottom = cf.bottom = mContentBottom;
5092                     }
5093                     if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5094                         vf.left = mCurLeft;
5095                         vf.top = mCurTop;
5096                         vf.right = mCurRight;
5097                         vf.bottom = mCurBottom;
5098                     } else {
5099                         vf.set(cf);
5100                     }
5101                 }
5102             }
5103         }
5104
5105         // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
5106         // Also, we don't allow windows in multi-window mode to extend out of the screen.
5107         if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR
5108                 && !win.isInMultiWindowMode()) {
5109             df.left = df.top = -10000;
5110             df.right = df.bottom = 10000;
5111             if (attrs.type != TYPE_WALLPAPER) {
5112                 of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
5113                 of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
5114             }
5115         }
5116
5117         // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we
5118         // need to provide information to the clients that want to pretend that you can draw there.
5119         // We only want to apply outsets to certain types of windows. For example, we never want to
5120         // apply the outsets to floating dialogs, because they wouldn't make sense there.
5121         final boolean useOutsets = shouldUseOutsets(attrs, fl);
5122         if (isDefaultDisplay && useOutsets) {
5123             osf = mTmpOutsetFrame;
5124             osf.set(cf.left, cf.top, cf.right, cf.bottom);
5125             int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
5126             if (outset > 0) {
5127                 int rotation = mDisplayRotation;
5128                 if (rotation == Surface.ROTATION_0) {
5129                     osf.bottom += outset;
5130                 } else if (rotation == Surface.ROTATION_90) {
5131                     osf.right += outset;
5132                 } else if (rotation == Surface.ROTATION_180) {
5133                     osf.top -= outset;
5134                 } else if (rotation == Surface.ROTATION_270) {
5135                     osf.left -= outset;
5136                 }
5137                 if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset
5138                         + " with rotation " + rotation + ", result: " + osf);
5139             }
5140         }
5141
5142         if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
5143                 + ": sim=#" + Integer.toHexString(sim)
5144                 + " attach=" + attached + " type=" + attrs.type
5145                 + String.format(" flags=0x%08x", fl)
5146                 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
5147                 + " of=" + of.toShortString()
5148                 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
5149                 + " dcf=" + dcf.toShortString()
5150                 + " sf=" + sf.toShortString()
5151                 + " osf=" + (osf == null ? "null" : osf.toShortString()));
5152
5153         win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf);
5154
5155         // Dock windows carve out the bottom of the screen, so normal windows
5156         // can't appear underneath them.
5157         if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleLw()
5158                 && !win.getGivenInsetsPendingLw()) {
5159             setLastInputMethodWindowLw(null, null);
5160             offsetInputMethodWindowLw(win);
5161         }
5162         if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleLw()
5163                 && !win.getGivenInsetsPendingLw()) {
5164             offsetVoiceInputWindowLw(win);
5165         }
5166     }
5167
5168     private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) {
5169
5170         // The wallpaper also has Real Ultimate Power, but we want to tell
5171         // it about the overscan area.
5172         pf.left = df.left = mOverscanScreenLeft;
5173         pf.top = df.top = mOverscanScreenTop;
5174         pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
5175         pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
5176         of.left = cf.left = mUnrestrictedScreenLeft;
5177         of.top = cf.top = mUnrestrictedScreenTop;
5178         of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5179         of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5180     }
5181
5182     private void offsetInputMethodWindowLw(WindowState win) {
5183         int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5184         top += win.getGivenContentInsetsLw().top;
5185         if (mContentBottom > top) {
5186             mContentBottom = top;
5187         }
5188         if (mVoiceContentBottom > top) {
5189             mVoiceContentBottom = top;
5190         }
5191         top = win.getVisibleFrameLw().top;
5192         top += win.getGivenVisibleInsetsLw().top;
5193         if (mCurBottom > top) {
5194             mCurBottom = top;
5195         }
5196         if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
5197                 + mDockBottom + " mContentBottom="
5198                 + mContentBottom + " mCurBottom=" + mCurBottom);
5199     }
5200
5201     private void offsetVoiceInputWindowLw(WindowState win) {
5202         int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5203         top += win.getGivenContentInsetsLw().top;
5204         if (mVoiceContentBottom > top) {
5205             mVoiceContentBottom = top;
5206         }
5207     }
5208
5209     /** {@inheritDoc} */
5210     @Override
5211     public void finishLayoutLw() {
5212         return;
5213     }
5214
5215     /** {@inheritDoc} */
5216     @Override
5217     public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
5218         mTopFullscreenOpaqueWindowState = null;
5219         mTopFullscreenOpaqueOrDimmingWindowState = null;
5220         mTopDockedOpaqueWindowState = null;
5221         mTopDockedOpaqueOrDimmingWindowState = null;
5222         mForceStatusBar = false;
5223         mForceStatusBarFromKeyguard = false;
5224         mForceStatusBarTransparent = false;
5225         mForcingShowNavBar = false;
5226         mForcingShowNavBarLayer = -1;
5227
5228         mAllowLockscreenWhenOn = false;
5229         mShowingDream = false;
5230     }
5231
5232     /** {@inheritDoc} */
5233     @Override
5234     public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
5235             WindowState attached, WindowState imeTarget) {
5236         final boolean visible = !win.isGoneForLayoutLw();
5237         if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisible=" + visible);
5238         applyKeyguardPolicyLw(win, imeTarget);
5239         final int fl = PolicyControl.getWindowFlags(win, attrs);
5240         if (mTopFullscreenOpaqueWindowState == null && visible && attrs.type == TYPE_INPUT_METHOD) {
5241             mForcingShowNavBar = true;
5242             mForcingShowNavBarLayer = win.getSurfaceLayer();
5243         }
5244         if (attrs.type == TYPE_STATUS_BAR) {
5245             if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
5246                 mForceStatusBarFromKeyguard = true;
5247             }
5248             if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
5249                 mForceStatusBarTransparent = true;
5250             }
5251         }
5252
5253         // Don't allow snapshots to influence SystemUI visibility flags.
5254         // TODO: Revisit this once SystemUI flags for snapshots are handled correctly
5255         boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
5256                 && attrs.type < FIRST_SYSTEM_WINDOW
5257                 && (attrs.privateFlags & PRIVATE_FLAG_TASK_SNAPSHOT) == 0;
5258         final int stackId = win.getStackId();
5259         if (mTopFullscreenOpaqueWindowState == null && visible) {
5260             if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
5261                 mForceStatusBar = true;
5262             }
5263             if (attrs.type == TYPE_DREAM) {
5264                 // If the lockscreen was showing when the dream started then wait
5265                 // for the dream to draw before hiding the lockscreen.
5266                 if (!mDreamingLockscreen
5267                         || (win.isVisibleLw() && win.hasDrawnLw())) {
5268                     mShowingDream = true;
5269                     appWindow = true;
5270                 }
5271             }
5272
5273             // For app windows that are not attached, we decide if all windows in the app they
5274             // represent should be hidden or if we should hide the lockscreen. For attached app
5275             // windows we defer the decision to the window it is attached to.
5276             if (appWindow && attached == null) {
5277                 if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
5278                     if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
5279                     mTopFullscreenOpaqueWindowState = win;
5280                     if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5281                         mTopFullscreenOpaqueOrDimmingWindowState = win;
5282                     }
5283                     if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
5284                         mAllowLockscreenWhenOn = true;
5285                     }
5286                 }
5287             }
5288         }
5289
5290         // Voice interaction overrides both top fullscreen and top docked.
5291         if (visible && win.getAttrs().type == TYPE_VOICE_INTERACTION) {
5292             if (mTopFullscreenOpaqueWindowState == null) {
5293                 mTopFullscreenOpaqueWindowState = win;
5294                 if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5295                     mTopFullscreenOpaqueOrDimmingWindowState = win;
5296                 }
5297             }
5298             if (mTopDockedOpaqueWindowState == null) {
5299                 mTopDockedOpaqueWindowState = win;
5300                 if (mTopDockedOpaqueOrDimmingWindowState == null) {
5301                     mTopDockedOpaqueOrDimmingWindowState = win;
5302                 }
5303             }
5304         }
5305
5306         // Keep track of the window if it's dimming but not necessarily fullscreen.
5307         if (mTopFullscreenOpaqueOrDimmingWindowState == null && visible
5308                 && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
5309             mTopFullscreenOpaqueOrDimmingWindowState = win;
5310         }
5311
5312         // We need to keep track of the top "fullscreen" opaque window for the docked stack
5313         // separately, because both the "real fullscreen" opaque window and the one for the docked
5314         // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
5315         if (mTopDockedOpaqueWindowState == null && visible && appWindow && attached == null
5316                 && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
5317             mTopDockedOpaqueWindowState = win;
5318             if (mTopDockedOpaqueOrDimmingWindowState == null) {
5319                 mTopDockedOpaqueOrDimmingWindowState = win;
5320             }
5321         }
5322
5323         // Also keep track of any windows that are dimming but not necessarily fullscreen in the
5324         // docked stack.
5325         if (mTopDockedOpaqueOrDimmingWindowState == null && visible && win.isDimming()
5326                 && stackId == DOCKED_STACK_ID) {
5327             mTopDockedOpaqueOrDimmingWindowState = win;
5328         }
5329     }
5330
5331     private void applyKeyguardPolicyLw(WindowState win, WindowState imeTarget) {
5332         if (canBeHiddenByKeyguardLw(win)) {
5333             if (shouldBeHiddenByKeyguard(win, imeTarget)) {
5334                 win.hideLw(false /* doAnimation */);
5335             } else {
5336                 win.showLw(false /* doAnimation */);
5337             }
5338         }
5339     }
5340
5341     private boolean isFullscreen(WindowManager.LayoutParams attrs) {
5342         return attrs.x == 0 && attrs.y == 0
5343                 && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
5344                 && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
5345     }
5346
5347     /** {@inheritDoc} */
5348     @Override
5349     public int finishPostLayoutPolicyLw() {
5350         int changes = 0;
5351         boolean topIsFullscreen = false;
5352
5353         final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
5354                 ? mTopFullscreenOpaqueWindowState.getAttrs()
5355                 : null;
5356
5357         // If we are not currently showing a dream then remember the current
5358         // lockscreen state.  We will use this to determine whether the dream
5359         // started while the lockscreen was showing and remember this state
5360         // while the dream is showing.
5361         if (!mShowingDream) {
5362             mDreamingLockscreen = isKeyguardShowingAndNotOccluded();
5363             if (mDreamingSleepTokenNeeded) {
5364                 mDreamingSleepTokenNeeded = false;
5365                 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
5366             }
5367         } else {
5368             if (!mDreamingSleepTokenNeeded) {
5369                 mDreamingSleepTokenNeeded = true;
5370                 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget();
5371             }
5372         }
5373
5374         if (mStatusBar != null) {
5375             if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
5376                     + " forcefkg=" + mForceStatusBarFromKeyguard
5377                     + " top=" + mTopFullscreenOpaqueWindowState);
5378             boolean shouldBeTransparent = mForceStatusBarTransparent
5379                     && !mForceStatusBar
5380                     && !mForceStatusBarFromKeyguard;
5381             if (!shouldBeTransparent) {
5382                 mStatusBarController.setShowTransparent(false /* transparent */);
5383             } else if (!mStatusBar.isVisibleLw()) {
5384                 mStatusBarController.setShowTransparent(true /* transparent */);
5385             }
5386
5387             WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs();
5388             boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT
5389                     && statusBarAttrs.width == MATCH_PARENT;
5390             if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
5391                     || statusBarExpanded) {
5392                 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
5393                 if (mStatusBarController.setBarShowingLw(true)) {
5394                     changes |= FINISH_LAYOUT_REDO_LAYOUT;
5395                 }
5396                 // Maintain fullscreen layout until incoming animation is complete.
5397                 topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
5398                 // Transient status bar on the lockscreen is not allowed
5399                 if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) {
5400                     mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
5401                             mLastSystemUiFlags, mLastSystemUiFlags);
5402                 }
5403                 if (statusBarExpanded && mNavigationBar != null) {
5404                     if (mNavigationBarController.setBarShowingLw(true)) {
5405                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
5406                     }
5407                 }
5408             } else if (mTopFullscreenOpaqueWindowState != null) {
5409                 final int fl = PolicyControl.getWindowFlags(null, lp);
5410                 if (localLOGV) {
5411                     Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
5412                             + " shown position: "
5413                             + mTopFullscreenOpaqueWindowState.getShownPositionLw());
5414                     Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
5415                             + " lp.flags=0x" + Integer.toHexString(fl));
5416                 }
5417                 topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
5418                         || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
5419                 // The subtle difference between the window for mTopFullscreenOpaqueWindowState
5420                 // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
5421                 // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
5422                 // case though.
5423                 if (mStatusBarController.isTransientShowing()) {
5424                     if (mStatusBarController.setBarShowingLw(true)) {
5425                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
5426                     }
5427                 } else if (topIsFullscreen
5428                         && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)
5429                         && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) {
5430                     if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
5431                     if (mStatusBarController.setBarShowingLw(false)) {
5432                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
5433                     } else {
5434                         if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
5435                     }
5436                 } else {
5437                     if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
5438                     if (mStatusBarController.setBarShowingLw(true)) {
5439                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
5440                     }
5441                 }
5442             }
5443         }
5444
5445         if (mTopIsFullscreen != topIsFullscreen) {
5446             if (!topIsFullscreen) {
5447                 // Force another layout when status bar becomes fully shown.
5448                 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5449             }
5450             mTopIsFullscreen = topIsFullscreen;
5451         }
5452
5453         if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5454             // If the navigation bar has been hidden or shown, we need to do another
5455             // layout pass to update that window.
5456             changes |= FINISH_LAYOUT_REDO_LAYOUT;
5457         }
5458
5459         if (mShowingDream != mLastShowingDream) {
5460             mLastShowingDream = mShowingDream;
5461             mWindowManagerFuncs.notifyShowingDreamChanged();
5462         }
5463
5464         // update since mAllowLockscreenWhenOn might have changed
5465         updateLockScreenTimeout();
5466         return changes;
5467     }
5468
5469     /**
5470      * Updates the occluded state of the Keyguard.
5471      *
5472      * @return Whether the flags have changed and we have to redo the layout.
5473      */
5474     private boolean setKeyguardOccludedLw(boolean isOccluded) {
5475         if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded);
5476         boolean wasOccluded = mKeyguardOccluded;
5477         boolean showing = mKeyguardDelegate.isShowing();
5478         if (wasOccluded && !isOccluded && showing) {
5479             mKeyguardOccluded = false;
5480             mKeyguardDelegate.setOccluded(false, true /* animate */);
5481             mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
5482             if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
5483                 mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5484             }
5485             return true;
5486         } else if (!wasOccluded && isOccluded && showing) {
5487             mKeyguardOccluded = true;
5488             mKeyguardDelegate.setOccluded(true, false /* animate */);
5489             mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
5490             mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
5491             return true;
5492         } else if (wasOccluded != isOccluded) {
5493             mKeyguardOccluded = isOccluded;
5494             mKeyguardDelegate.setOccluded(isOccluded, false /* animate */);
5495             return false;
5496         } else {
5497             return false;
5498         }
5499     }
5500
5501     private boolean isStatusBarKeyguard() {
5502         return mStatusBar != null
5503                 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
5504     }
5505
5506     @Override
5507     public boolean allowAppAnimationsLw() {
5508         if (mShowingDream) {
5509             // If keyguard or dreams is currently visible, no reason to animate behind it.
5510             return false;
5511         }
5512         return true;
5513     }
5514
5515     @Override
5516     public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
5517         mFocusedWindow = newFocus;
5518         if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5519             // If the navigation bar has been hidden or shown, we need to do another
5520             // layout pass to update that window.
5521             return FINISH_LAYOUT_REDO_LAYOUT;
5522         }
5523         return 0;
5524     }
5525
5526     /** {@inheritDoc} */
5527     @Override
5528     public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
5529         // lid changed state
5530         final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
5531         if (newLidState == mLidState) {
5532             return;
5533         }
5534
5535         mLidState = newLidState;
5536         applyLidSwitchState();
5537         updateRotation(true);
5538
5539         if (lidOpen) {
5540             wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
5541                     "android.policy:LID");
5542         } else if (!mLidControlsSleep) {
5543             mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
5544         }
5545     }
5546
5547     @Override
5548     public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
5549         int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
5550         if (mCameraLensCoverState == lensCoverState) {
5551             return;
5552         }
5553         if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
5554                 lensCoverState == CAMERA_LENS_UNCOVERED) {
5555             Intent intent;
5556             final boolean keyguardActive = mKeyguardDelegate == null ? false :
5557                     mKeyguardDelegate.isShowing();
5558             if (keyguardActive) {
5559                 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
5560             } else {
5561                 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
5562             }
5563             wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
5564                     "android.policy:CAMERA_COVER");
5565             startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
5566         }
5567         mCameraLensCoverState = lensCoverState;
5568     }
5569
5570     void setHdmiPlugged(boolean plugged) {
5571         if (mHdmiPlugged != plugged) {
5572             mHdmiPlugged = plugged;
5573             updateRotation(true, true);
5574             Intent intent = new Intent(ACTION_HDMI_PLUGGED);
5575             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
5576             intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
5577             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
5578         }
5579     }
5580
5581     void initializeHdmiState() {
5582         boolean plugged = false;
5583         // watch for HDMI plug messages if the hdmi switch exists
5584         if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
5585             mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
5586
5587             final String filename = "/sys/class/switch/hdmi/state";
5588             FileReader reader = null;
5589             try {
5590                 reader = new FileReader(filename);
5591                 char[] buf = new char[15];
5592                 int n = reader.read(buf);
5593                 if (n > 1) {
5594                     plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
5595                 }
5596             } catch (IOException ex) {
5597                 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5598             } catch (NumberFormatException ex) {
5599                 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5600             } finally {
5601                 if (reader != null) {
5602                     try {
5603                         reader.close();
5604                     } catch (IOException ex) {
5605                     }
5606                 }
5607             }
5608         }
5609         // This dance forces the code in setHdmiPlugged to run.
5610         // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
5611         mHdmiPlugged = !plugged;
5612         setHdmiPlugged(!mHdmiPlugged);
5613     }
5614
5615     final Object mScreenshotLock = new Object();
5616     ServiceConnection mScreenshotConnection = null;
5617
5618     final Runnable mScreenshotTimeout = new Runnable() {
5619         @Override public void run() {
5620             synchronized (mScreenshotLock) {
5621                 if (mScreenshotConnection != null) {
5622                     mContext.unbindService(mScreenshotConnection);
5623                     mScreenshotConnection = null;
5624                     notifyScreenshotError();
5625                 }
5626             }
5627         }
5628     };
5629
5630     // Assume this is called from the Handler thread.
5631     private void takeScreenshot(final int screenshotType) {
5632         synchronized (mScreenshotLock) {
5633             if (mScreenshotConnection != null) {
5634                 return;
5635             }
5636             final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
5637                     SYSUI_SCREENSHOT_SERVICE);
5638             final Intent serviceIntent = new Intent();
5639             serviceIntent.setComponent(serviceComponent);
5640             ServiceConnection conn = new ServiceConnection() {
5641                 @Override
5642                 public void onServiceConnected(ComponentName name, IBinder service) {
5643                     synchronized (mScreenshotLock) {
5644                         if (mScreenshotConnection != this) {
5645                             return;
5646                         }
5647                         Messenger messenger = new Messenger(service);
5648                         Message msg = Message.obtain(null, screenshotType);
5649                         final ServiceConnection myConn = this;
5650                         Handler h = new Handler(mHandler.getLooper()) {
5651                             @Override
5652                             public void handleMessage(Message msg) {
5653                                 synchronized (mScreenshotLock) {
5654                                     if (mScreenshotConnection == myConn) {
5655                                         mContext.unbindService(mScreenshotConnection);
5656                                         mScreenshotConnection = null;
5657                                         mHandler.removeCallbacks(mScreenshotTimeout);
5658                                     }
5659                                 }
5660                             }
5661                         };
5662                         msg.replyTo = new Messenger(h);
5663                         msg.arg1 = msg.arg2 = 0;
5664                         if (mStatusBar != null && mStatusBar.isVisibleLw())
5665                             msg.arg1 = 1;
5666                         if (mNavigationBar != null && mNavigationBar.isVisibleLw())
5667                             msg.arg2 = 1;
5668                         try {
5669                             messenger.send(msg);
5670                         } catch (RemoteException e) {
5671                         }
5672                     }
5673                 }
5674
5675                 @Override
5676                 public void onServiceDisconnected(ComponentName name) {
5677                     synchronized (mScreenshotLock) {
5678                         if (mScreenshotConnection != null) {
5679                             mContext.unbindService(mScreenshotConnection);
5680                             mScreenshotConnection = null;
5681                             mHandler.removeCallbacks(mScreenshotTimeout);
5682                             notifyScreenshotError();
5683                         }
5684                     }
5685                 }
5686             };
5687             if (mContext.bindServiceAsUser(serviceIntent, conn,
5688                     Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
5689                     UserHandle.CURRENT)) {
5690                 mScreenshotConnection = conn;
5691                 mHandler.postDelayed(mScreenshotTimeout, 10000);
5692             }
5693         }
5694     }
5695
5696     /**
5697      * Notifies the screenshot service to show an error.
5698      */
5699     private void notifyScreenshotError() {
5700         // If the service process is killed, then ask it to clean up after itself
5701         final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
5702                 SYSUI_SCREENSHOT_ERROR_RECEIVER);
5703         Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
5704         errorIntent.setComponent(errorComponent);
5705         errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
5706                 Intent.FLAG_RECEIVER_FOREGROUND);
5707         mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT);
5708     }
5709
5710     /** {@inheritDoc} */
5711     @Override
5712     public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
5713         if (!mSystemBooted) {
5714             // If we have not yet booted, don't let key events do anything.
5715             return 0;
5716         }
5717
5718         final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
5719         final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
5720         final boolean canceled = event.isCanceled();
5721         final int keyCode = event.getKeyCode();
5722
5723         final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
5724
5725         // If screen is off then we treat the case where the keyguard is open but hidden
5726         // the same as if it were open and in front.
5727         // This will prevent any keys other than the power button from waking the screen
5728         // when the keyguard is hidden by another activity.
5729         final boolean keyguardActive = (mKeyguardDelegate == null ? false :
5730                                             (interactive ?
5731                                                 isKeyguardShowingAndNotOccluded() :
5732                                                 mKeyguardDelegate.isShowing()));
5733
5734         if (DEBUG_INPUT) {
5735             Log.d(TAG, "interceptKeyTq keycode=" + keyCode
5736                     + " interactive=" + interactive + " keyguardActive=" + keyguardActive
5737                     + " policyFlags=" + Integer.toHexString(policyFlags));
5738         }
5739
5740         // Basic policy based on interactive state.
5741         int result;
5742         boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
5743                 || event.isWakeKey();
5744         if (interactive || (isInjected && !isWakeKey)) {
5745             // When the device is interactive or the key is injected pass the
5746             // key to the application.
5747             result = ACTION_PASS_TO_USER;
5748             isWakeKey = false;
5749
5750             if (interactive) {
5751                 // If the screen is awake, but the button pressed was the one that woke the device
5752                 // then don't pass it to the application
5753                 if (keyCode == mPendingWakeKey && !down) {
5754                     result = 0;
5755                 }
5756                 // Reset the pending key
5757                 mPendingWakeKey = PENDING_KEY_NULL;
5758             }
5759         } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
5760             // If we're currently dozing with the screen on and the keyguard showing, pass the key
5761             // to the application but preserve its wake key status to make sure we still move
5762             // from dozing to fully interactive if we would normally go from off to fully
5763             // interactive.
5764             result = ACTION_PASS_TO_USER;
5765             // Since we're dispatching the input, reset the pending key
5766             mPendingWakeKey = PENDING_KEY_NULL;
5767         } else {
5768             // When the screen is off and the key is not injected, determine whether
5769             // to wake the device but don't pass the key to the application.
5770             result = 0;
5771             if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
5772                 isWakeKey = false;
5773             }
5774             // Cache the wake key on down event so we can also avoid sending the up event to the app
5775             if (isWakeKey && down) {
5776                 mPendingWakeKey = keyCode;
5777             }
5778         }
5779
5780         // If the key would be handled globally, just return the result, don't worry about special
5781         // key processing.
5782         if (isValidGlobalKey(keyCode)
5783                 && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
5784             if (isWakeKey) {
5785                 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5786             }
5787             return result;
5788         }
5789
5790         boolean useHapticFeedback = down
5791                 && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
5792                 && event.getRepeatCount() == 0;
5793
5794         // Handle special keys.
5795         switch (keyCode) {
5796             case KeyEvent.KEYCODE_BACK: {
5797                 if (down) {
5798                     interceptBackKeyDown();
5799                 } else {
5800                     boolean handled = interceptBackKeyUp(event);
5801
5802                     // Don't pass back press to app if we've already handled it via long press
5803                     if (handled) {
5804                         result &= ~ACTION_PASS_TO_USER;
5805                     }
5806                 }
5807                 break;
5808             }
5809
5810             case KeyEvent.KEYCODE_VOLUME_DOWN:
5811             case KeyEvent.KEYCODE_VOLUME_UP:
5812             case KeyEvent.KEYCODE_VOLUME_MUTE: {
5813                 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
5814                     if (down) {
5815                         if (interactive && !mScreenshotChordVolumeDownKeyTriggered
5816                                 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5817                             mScreenshotChordVolumeDownKeyTriggered = true;
5818                             mScreenshotChordVolumeDownKeyTime = event.getDownTime();
5819                             mScreenshotChordVolumeDownKeyConsumed = false;
5820                             cancelPendingPowerKeyAction();
5821                             interceptScreenshotChord();
5822                             if (!isKeyguardLocked()) {
5823                                 interceptAccessibilityShortcutChord();
5824                             }
5825                         }
5826                     } else {
5827                         mScreenshotChordVolumeDownKeyTriggered = false;
5828                         cancelPendingScreenshotChordAction();
5829                         cancelPendingAccessibilityShortcutAction();
5830                     }
5831                 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
5832                     if (down) {
5833                         if (interactive && !mA11yShortcutChordVolumeUpKeyTriggered
5834                                 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5835                             mA11yShortcutChordVolumeUpKeyTriggered = true;
5836                             mA11yShortcutChordVolumeUpKeyTime = event.getDownTime();
5837                             mA11yShortcutChordVolumeUpKeyConsumed = false;
5838                             cancelPendingPowerKeyAction();
5839                             cancelPendingScreenshotChordAction();
5840                             if (!isKeyguardLocked()) {
5841                                 interceptAccessibilityShortcutChord();
5842                             }
5843                         }
5844                     } else {
5845                         mA11yShortcutChordVolumeUpKeyTriggered = false;
5846                         cancelPendingScreenshotChordAction();
5847                         cancelPendingAccessibilityShortcutAction();
5848                     }
5849                 }
5850                 if (down) {
5851                     TelecomManager telecomManager = getTelecommService();
5852                     if (telecomManager != null) {
5853                         if (telecomManager.isRinging()) {
5854                             // If an incoming call is ringing, either VOLUME key means
5855                             // "silence ringer".  We handle these keys here, rather than
5856                             // in the InCallScreen, to make sure we'll respond to them
5857                             // even if the InCallScreen hasn't come to the foreground yet.
5858                             // Look for the DOWN event here, to agree with the "fallback"
5859                             // behavior in the InCallScreen.
5860                             Log.i(TAG, "interceptKeyBeforeQueueing:"
5861                                   + " VOLUME key-down while ringing: Silence ringer!");
5862
5863                             // Silence the ringer.  (It's safe to call this
5864                             // even if the ringer has already been silenced.)
5865                             telecomManager.silenceRinger();
5866
5867                             // And *don't* pass this key thru to the current activity
5868                             // (which is probably the InCallScreen.)
5869                             result &= ~ACTION_PASS_TO_USER;
5870                             break;
5871                         }
5872                         if (telecomManager.isInCall()
5873                                 && (result & ACTION_PASS_TO_USER) == 0) {
5874                             // If we are in call but we decided not to pass the key to
5875                             // the application, just pass it to the session service.
5876                             MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
5877                                     event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
5878                             break;
5879                         }
5880                     }
5881                 }
5882                 if (mUseTvRouting) {
5883                     // On TVs, defer special key handlings to
5884                     // {@link interceptKeyBeforeDispatching()}.
5885                     result |= ACTION_PASS_TO_USER;
5886                 } else if ((result & ACTION_PASS_TO_USER) == 0) {
5887                     // If we aren't passing to the user and no one else
5888                     // handled it send it to the session manager to
5889                     // figure out.
5890                     MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
5891                             event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
5892                 }
5893                 break;
5894             }
5895
5896             case KeyEvent.KEYCODE_ENDCALL: {
5897                 result &= ~ACTION_PASS_TO_USER;
5898                 if (down) {
5899                     TelecomManager telecomManager = getTelecommService();
5900                     boolean hungUp = false;
5901                     if (telecomManager != null) {
5902                         hungUp = telecomManager.endCall();
5903                     }
5904                     if (interactive && !hungUp) {
5905                         mEndCallKeyHandled = false;
5906                         mHandler.postDelayed(mEndCallLongPress,
5907                                 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
5908                     } else {
5909                         mEndCallKeyHandled = true;
5910                     }
5911                 } else {
5912                     if (!mEndCallKeyHandled) {
5913                         mHandler.removeCallbacks(mEndCallLongPress);
5914                         if (!canceled) {
5915                             if ((mEndcallBehavior
5916                                     & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
5917                                 if (goHome()) {
5918                                     break;
5919                                 }
5920                             }
5921                             if ((mEndcallBehavior
5922                                     & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
5923                                 mPowerManager.goToSleep(event.getEventTime(),
5924                                         PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
5925                                 isWakeKey = false;
5926                             }
5927                         }
5928                     }
5929                 }
5930                 break;
5931             }
5932
5933             case KeyEvent.KEYCODE_POWER: {
5934                 // Any activity on the power button stops the accessibility shortcut
5935                 cancelPendingAccessibilityShortcutAction();
5936                 result &= ~ACTION_PASS_TO_USER;
5937                 isWakeKey = false; // wake-up will be handled separately
5938                 if (down) {
5939                     interceptPowerKeyDown(event, interactive);
5940                 } else {
5941                     interceptPowerKeyUp(event, interactive, canceled);
5942                 }
5943                 break;
5944             }
5945
5946             case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
5947                 // fall through
5948             case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
5949                 // fall through
5950             case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
5951                 // fall through
5952             case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
5953                 result &= ~ACTION_PASS_TO_USER;
5954                 interceptSystemNavigationKey(event);
5955                 break;
5956             }
5957
5958             case KeyEvent.KEYCODE_SLEEP: {
5959                 result &= ~ACTION_PASS_TO_USER;
5960                 isWakeKey = false;
5961                 if (!mPowerManager.isInteractive()) {
5962                     useHapticFeedback = false; // suppress feedback if already non-interactive
5963                 }
5964                 if (down) {
5965                     sleepPress(event.getEventTime());
5966                 } else {
5967                     sleepRelease(event.getEventTime());
5968                 }
5969                 break;
5970             }
5971
5972             case KeyEvent.KEYCODE_SOFT_SLEEP: {
5973                 result &= ~ACTION_PASS_TO_USER;
5974                 isWakeKey = false;
5975                 if (!down) {
5976                     mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
5977                 }
5978                 break;
5979             }
5980
5981             case KeyEvent.KEYCODE_WAKEUP: {
5982                 result &= ~ACTION_PASS_TO_USER;
5983                 isWakeKey = true;
5984                 break;
5985             }
5986
5987             case KeyEvent.KEYCODE_MEDIA_PLAY:
5988             case KeyEvent.KEYCODE_MEDIA_PAUSE:
5989             case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
5990             case KeyEvent.KEYCODE_HEADSETHOOK:
5991             case KeyEvent.KEYCODE_MUTE:
5992             case KeyEvent.KEYCODE_MEDIA_STOP:
5993             case KeyEvent.KEYCODE_MEDIA_NEXT:
5994             case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
5995             case KeyEvent.KEYCODE_MEDIA_REWIND:
5996             case KeyEvent.KEYCODE_MEDIA_RECORD:
5997             case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
5998             case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
5999                 if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
6000                     // If the global session is active pass all media keys to it
6001                     // instead of the active window.
6002                     result &= ~ACTION_PASS_TO_USER;
6003                 }
6004                 if ((result & ACTION_PASS_TO_USER) == 0) {
6005                     // Only do this if we would otherwise not pass it to the user. In that
6006                     // case, the PhoneWindow class will do the same thing, except it will
6007                     // only do it if the showing app doesn't process the key on its own.
6008                     // Note that we need to make a copy of the key event here because the
6009                     // original key event will be recycled when we return.
6010                     mBroadcastWakeLock.acquire();
6011                     Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
6012                             new KeyEvent(event));
6013                     msg.setAsynchronous(true);
6014                     msg.sendToTarget();
6015                 }
6016                 break;
6017             }
6018
6019             case KeyEvent.KEYCODE_CALL: {
6020                 if (down) {
6021                     TelecomManager telecomManager = getTelecommService();
6022                     if (telecomManager != null) {
6023                         if (telecomManager.isRinging()) {
6024                             Log.i(TAG, "interceptKeyBeforeQueueing:"
6025                                   + " CALL key-down while ringing: Answer the call!");
6026                             telecomManager.acceptRingingCall();
6027
6028                             // And *don't* pass this key thru to the current activity
6029                             // (which is presumably the InCallScreen.)
6030                             result &= ~ACTION_PASS_TO_USER;
6031                         }
6032                     }
6033                 }
6034                 break;
6035             }
6036             case KeyEvent.KEYCODE_VOICE_ASSIST: {
6037                 // Only do this if we would otherwise not pass it to the user. In that case,
6038                 // interceptKeyBeforeDispatching would apply a similar but different policy in
6039                 // order to invoke voice assist actions. Note that we need to make a copy of the
6040                 // key event here because the original key event will be recycled when we return.
6041                 if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
6042                     mBroadcastWakeLock.acquire();
6043                     Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
6044                             keyguardActive ? 1 : 0, 0);
6045                     msg.setAsynchronous(true);
6046                     msg.sendToTarget();
6047                 }
6048                 break;
6049             }
6050             case KeyEvent.KEYCODE_WINDOW: {
6051                 if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
6052                     if (mTvPictureInPictureVisible) {
6053                         // Consumes the key only if picture-in-picture is visible
6054                         // to show picture-in-picture control menu.
6055                         // This gives a chance to the foreground activity
6056                         // to customize PIP key behavior.
6057                         if (!down) {
6058                             showTvPictureInPictureMenu(event);
6059                         }
6060                         result &= ~ACTION_PASS_TO_USER;
6061                     }
6062                 }
6063                 break;
6064             }
6065         }
6066
6067         if (useHapticFeedback) {
6068             performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
6069         }
6070
6071         if (isWakeKey) {
6072             wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
6073         }
6074
6075         return result;
6076     }
6077
6078     /**
6079      * Handle statusbar expansion events.
6080      * @param event
6081      */
6082     private void interceptSystemNavigationKey(KeyEvent event) {
6083         if (event.getAction() == KeyEvent.ACTION_UP) {
6084             if (!mAccessibilityManager.isEnabled()
6085                     || !mAccessibilityManager.sendFingerprintGesture(event.getKeyCode())) {
6086                 if (areSystemNavigationKeysEnabled()) {
6087                     IStatusBarService sbar = getStatusBarService();
6088                     if (sbar != null) {
6089                         try {
6090                             sbar.handleSystemNavigationKey(event.getKeyCode());
6091                         } catch (RemoteException e1) {
6092                             // oops, no statusbar. Ignore event.
6093                         }
6094                     }
6095                 }
6096             }
6097         }
6098     }
6099
6100     /**
6101      * Returns true if the key can have global actions attached to it.
6102      * We reserve all power management keys for the system since they require
6103      * very careful handling.
6104      */
6105     private static boolean isValidGlobalKey(int keyCode) {
6106         switch (keyCode) {
6107             case KeyEvent.KEYCODE_POWER:
6108             case KeyEvent.KEYCODE_WAKEUP:
6109             case KeyEvent.KEYCODE_SLEEP:
6110                 return false;
6111             default:
6112                 return true;
6113         }
6114     }
6115
6116     /**
6117      * When the screen is off we ignore some keys that might otherwise typically
6118      * be considered wake keys.  We filter them out here.
6119      *
6120      * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
6121      * is always considered a wake key.
6122      */
6123     private boolean isWakeKeyWhenScreenOff(int keyCode) {
6124         switch (keyCode) {
6125             // ignore volume keys unless docked
6126             case KeyEvent.KEYCODE_VOLUME_UP:
6127             case KeyEvent.KEYCODE_VOLUME_DOWN:
6128             case KeyEvent.KEYCODE_VOLUME_MUTE:
6129                 return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
6130
6131             // ignore media and camera keys
6132             case KeyEvent.KEYCODE_MUTE:
6133             case KeyEvent.KEYCODE_HEADSETHOOK:
6134             case KeyEvent.KEYCODE_MEDIA_PLAY:
6135             case KeyEvent.KEYCODE_MEDIA_PAUSE:
6136             case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6137             case KeyEvent.KEYCODE_MEDIA_STOP:
6138             case KeyEvent.KEYCODE_MEDIA_NEXT:
6139             case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6140             case KeyEvent.KEYCODE_MEDIA_REWIND:
6141             case KeyEvent.KEYCODE_MEDIA_RECORD:
6142             case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6143             case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
6144             case KeyEvent.KEYCODE_CAMERA:
6145                 return false;
6146         }
6147         return true;
6148     }
6149
6150
6151     /** {@inheritDoc} */
6152     @Override
6153     public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
6154         if ((policyFlags & FLAG_WAKE) != 0) {
6155             if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
6156                     "android.policy:MOTION")) {
6157                 return 0;
6158             }
6159         }
6160
6161         if (shouldDispatchInputWhenNonInteractive(null)) {
6162             return ACTION_PASS_TO_USER;
6163         }
6164
6165         // If we have not passed the action up and we are in theater mode without dreaming,
6166         // there will be no dream to intercept the touch and wake into ambient.  The device should
6167         // wake up in this case.
6168         if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
6169             wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
6170                     "android.policy:MOTION");
6171         }
6172
6173         return 0;
6174     }
6175
6176     private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
6177         final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
6178
6179         if (displayOff && !mHasFeatureWatch) {
6180             return false;
6181         }
6182
6183         // Send events to keyguard while the screen is on and it's showing.
6184         if (isKeyguardShowingAndNotOccluded() && !displayOff) {
6185             return true;
6186         }
6187
6188         // Watches handle BACK specially
6189         if (mHasFeatureWatch
6190                 && event != null
6191                 && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
6192                         || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
6193             return false;
6194         }
6195
6196         // Send events to a dozing dream even if the screen is off since the dream
6197         // is in control of the state of the screen.
6198         IDreamManager dreamManager = getDreamManager();
6199
6200         try {
6201             if (dreamManager != null && dreamManager.isDreaming()) {
6202                 return true;
6203             }
6204         } catch (RemoteException e) {
6205             Slog.e(TAG, "RemoteException when checking if dreaming", e);
6206         }
6207
6208         // Otherwise, consume events since the user can't see what is being
6209         // interacted with.
6210         return false;
6211     }
6212
6213     private void dispatchDirectAudioEvent(KeyEvent event) {
6214         if (event.getAction() != KeyEvent.ACTION_DOWN) {
6215             return;
6216         }
6217         int keyCode = event.getKeyCode();
6218         int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
6219                 | AudioManager.FLAG_FROM_KEY;
6220         String pkgName = mContext.getOpPackageName();
6221         switch (keyCode) {
6222             case KeyEvent.KEYCODE_VOLUME_UP:
6223                 try {
6224                     getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
6225                             AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6226                 } catch (RemoteException e) {
6227                     Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
6228                 }
6229                 break;
6230             case KeyEvent.KEYCODE_VOLUME_DOWN:
6231                 try {
6232                     getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
6233                             AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6234                 } catch (RemoteException e) {
6235                     Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
6236                 }
6237                 break;
6238             case KeyEvent.KEYCODE_VOLUME_MUTE:
6239                 try {
6240                     if (event.getRepeatCount() == 0) {
6241                         getAudioService().adjustSuggestedStreamVolume(
6242                                 AudioManager.ADJUST_TOGGLE_MUTE,
6243                                 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6244                     }
6245                 } catch (RemoteException e) {
6246                     Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
6247                 }
6248                 break;
6249         }
6250     }
6251
6252     void dispatchMediaKeyWithWakeLock(KeyEvent event) {
6253         if (DEBUG_INPUT) {
6254             Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
6255         }
6256
6257         if (mHavePendingMediaKeyRepeatWithWakeLock) {
6258             if (DEBUG_INPUT) {
6259                 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
6260             }
6261
6262             mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
6263             mHavePendingMediaKeyRepeatWithWakeLock = false;
6264             mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
6265         }
6266
6267         dispatchMediaKeyWithWakeLockToAudioService(event);
6268
6269         if (event.getAction() == KeyEvent.ACTION_DOWN
6270                 && event.getRepeatCount() == 0) {
6271             mHavePendingMediaKeyRepeatWithWakeLock = true;
6272
6273             Message msg = mHandler.obtainMessage(
6274                     MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
6275             msg.setAsynchronous(true);
6276             mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
6277         } else {
6278             mBroadcastWakeLock.release();
6279         }
6280     }
6281
6282     void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
6283         mHavePendingMediaKeyRepeatWithWakeLock = false;
6284
6285         KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
6286                 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6287         if (DEBUG_INPUT) {
6288             Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
6289         }
6290
6291         dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
6292         mBroadcastWakeLock.release();
6293     }
6294
6295     void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
6296         if (mActivityManagerInternal.isSystemReady()) {
6297             MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
6298         }
6299     }
6300
6301     void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
6302         IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
6303                 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
6304         if (dic != null) {
6305             try {
6306                 dic.exitIdle("voice-search");
6307             } catch (RemoteException e) {
6308             }
6309         }
6310         Intent voiceIntent =
6311             new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
6312         voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
6313         startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
6314         mBroadcastWakeLock.release();
6315     }
6316
6317     BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
6318         @Override
6319         public void onReceive(Context context, Intent intent) {
6320             if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
6321                 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6322                         Intent.EXTRA_DOCK_STATE_UNDOCKED);
6323             } else {
6324                 try {
6325                     IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
6326                             ServiceManager.getService(Context.UI_MODE_SERVICE));
6327                     mUiMode = uiModeService.getCurrentModeType();
6328                 } catch (RemoteException e) {
6329                 }
6330             }
6331             updateRotation(true);
6332             synchronized (mLock) {
6333                 updateOrientationListenerLp();
6334             }
6335         }
6336     };
6337
6338     BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
6339         @Override
6340         public void onReceive(Context context, Intent intent) {
6341             if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
6342                 if (mKeyguardDelegate != null) {
6343                     mKeyguardDelegate.onDreamingStarted();
6344                 }
6345             } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
6346                 if (mKeyguardDelegate != null) {
6347                     mKeyguardDelegate.onDreamingStopped();
6348                 }
6349             }
6350         }
6351     };
6352
6353     BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
6354         @Override
6355         public void onReceive(Context context, Intent intent) {
6356             if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
6357                 // tickle the settings observer: this first ensures that we're
6358                 // observing the relevant settings for the newly-active user,
6359                 // and then updates our own bookkeeping based on the now-
6360                 // current user.
6361                 mSettingsObserver.onChange(false);
6362
6363                 // force a re-application of focused window sysui visibility.
6364                 // the window may never have been shown for this user
6365                 // e.g. the keyguard when going through the new-user setup flow
6366                 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6367                     mLastSystemUiFlags = 0;
6368                     updateSystemUiVisibilityLw();
6369                 }
6370             }
6371         }
6372     };
6373
6374     private final Runnable mHiddenNavPanic = new Runnable() {
6375         @Override
6376         public void run() {
6377             synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6378                 if (!isUserSetupComplete()) {
6379                     // Swipe-up for navigation bar is disabled during setup
6380                     return;
6381                 }
6382                 mPendingPanicGestureUptime = SystemClock.uptimeMillis();
6383                 if (!isNavBarEmpty(mLastSystemUiFlags)) {
6384                     mNavigationBarController.showTransient();
6385                 }
6386             }
6387         }
6388     };
6389
6390     private void requestTransientBars(WindowState swipeTarget) {
6391         synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6392             if (!isUserSetupComplete()) {
6393                 // Swipe-up for navigation bar is disabled during setup
6394                 return;
6395             }
6396             boolean sb = mStatusBarController.checkShowTransientBarLw();
6397             boolean nb = mNavigationBarController.checkShowTransientBarLw()
6398                     && !isNavBarEmpty(mLastSystemUiFlags);
6399             if (sb || nb) {
6400                 // Don't show status bar when swiping on already visible navigation bar
6401                 if (!nb && swipeTarget == mNavigationBar) {
6402                     if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
6403                     return;
6404                 }
6405                 if (sb) mStatusBarController.showTransient();
6406                 if (nb) mNavigationBarController.showTransient();
6407                 mImmersiveModeConfirmation.confirmCurrentPrompt();
6408                 updateSystemUiVisibilityLw();
6409             }
6410         }
6411     }
6412
6413     // Called on the PowerManager's Notifier thread.
6414     @Override
6415     public void startedGoingToSleep(int why) {
6416         if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
6417         mCameraGestureTriggeredDuringGoingToSleep = false;
6418         mGoingToSleep = true;
6419         if (mKeyguardDelegate != null) {
6420             mKeyguardDelegate.onStartedGoingToSleep(why);
6421         }
6422     }
6423
6424     // Called on the PowerManager's Notifier thread.
6425     @Override
6426     public void finishedGoingToSleep(int why) {
6427         EventLog.writeEvent(70000, 0);
6428         if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
6429         MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
6430
6431         mGoingToSleep = false;
6432
6433         // We must get this work done here because the power manager will drop
6434         // the wake lock and let the system suspend once this function returns.
6435         synchronized (mLock) {
6436             mAwake = false;
6437             updateWakeGestureListenerLp();
6438             updateOrientationListenerLp();
6439             updateLockScreenTimeout();
6440         }
6441         if (mKeyguardDelegate != null) {
6442             mKeyguardDelegate.onFinishedGoingToSleep(why,
6443                     mCameraGestureTriggeredDuringGoingToSleep);
6444         }
6445         mCameraGestureTriggeredDuringGoingToSleep = false;
6446     }
6447
6448     // Called on the PowerManager's Notifier thread.
6449     @Override
6450     public void startedWakingUp() {
6451         EventLog.writeEvent(70000, 1);
6452         if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
6453
6454         // Since goToSleep performs these functions synchronously, we must
6455         // do the same here.  We cannot post this work to a handler because
6456         // that might cause it to become reordered with respect to what
6457         // may happen in a future call to goToSleep.
6458         synchronized (mLock) {
6459             mAwake = true;
6460
6461             updateWakeGestureListenerLp();
6462             updateOrientationListenerLp();
6463             updateLockScreenTimeout();
6464         }
6465
6466         if (mKeyguardDelegate != null) {
6467             mKeyguardDelegate.onStartedWakingUp();
6468         }
6469     }
6470
6471     // Called on the PowerManager's Notifier thread.
6472     @Override
6473     public void finishedWakingUp() {
6474         if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
6475     }
6476
6477     private void wakeUpFromPowerKey(long eventTime) {
6478         wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
6479     }
6480
6481     private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
6482         final boolean theaterModeEnabled = isTheaterModeEnabled();
6483         if (!wakeInTheaterMode && theaterModeEnabled) {
6484             return false;
6485         }
6486
6487         if (theaterModeEnabled) {
6488             Settings.Global.putInt(mContext.getContentResolver(),
6489                     Settings.Global.THEATER_MODE_ON, 0);
6490         }
6491
6492         mPowerManager.wakeUp(wakeTime, reason);
6493         return true;
6494     }
6495
6496     private void finishKeyguardDrawn() {
6497         synchronized (mLock) {
6498             if (!mScreenOnEarly || mKeyguardDrawComplete) {
6499                 return; // We are not awake yet or we have already informed of this event.
6500             }
6501
6502             mKeyguardDrawComplete = true;
6503             if (mKeyguardDelegate != null) {
6504                 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6505             }
6506             mWindowManagerDrawComplete = false;
6507         }
6508
6509         // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
6510         // as well as enabling the orientation change logic/sensor.
6511         mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
6512                 WAITING_FOR_DRAWN_TIMEOUT);
6513     }
6514
6515     // Called on the DisplayManager's DisplayPowerController thread.
6516     @Override
6517     public void screenTurnedOff() {
6518         if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
6519
6520         updateScreenOffSleepToken(true);
6521         synchronized (mLock) {
6522             mScreenOnEarly = false;
6523             mScreenOnFully = false;
6524             mKeyguardDrawComplete = false;
6525             mWindowManagerDrawComplete = false;
6526             mScreenOnListener = null;
6527             updateOrientationListenerLp();
6528
6529             if (mKeyguardDelegate != null) {
6530                 mKeyguardDelegate.onScreenTurnedOff();
6531             }
6532         }
6533         reportScreenStateToVrManager(false);
6534     }
6535
6536     // Called on the DisplayManager's DisplayPowerController thread.
6537     @Override
6538     public void screenTurningOn(final ScreenOnListener screenOnListener) {
6539         if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
6540
6541         updateScreenOffSleepToken(false);
6542         synchronized (mLock) {
6543             mScreenOnEarly = true;
6544             mScreenOnFully = false;
6545             mKeyguardDrawComplete = false;
6546             mWindowManagerDrawComplete = false;
6547             mScreenOnListener = screenOnListener;
6548
6549             if (mKeyguardDelegate != null) {
6550                 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6551                 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
6552                 mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
6553             } else {
6554                 if (DEBUG_WAKEUP) Slog.d(TAG,
6555                         "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
6556                 finishKeyguardDrawn();
6557             }
6558         }
6559     }
6560
6561     // Called on the DisplayManager's DisplayPowerController thread.
6562     @Override
6563     public void screenTurnedOn() {
6564         synchronized (mLock) {
6565             if (mKeyguardDelegate != null) {
6566                 mKeyguardDelegate.onScreenTurnedOn();
6567             }
6568         }
6569         reportScreenStateToVrManager(true);
6570     }
6571
6572     private void reportScreenStateToVrManager(boolean isScreenOn) {
6573         if (mVrManagerInternal == null) {
6574             return;
6575         }
6576         mVrManagerInternal.onScreenStateChanged(isScreenOn);
6577     }
6578
6579     private void exitPersistentVrMode() {
6580         if (mVrManagerInternal == null) {
6581             return;
6582         }
6583         mVrManagerInternal.setPersistentVrModeEnabled(false);
6584     }
6585
6586     private void finishWindowsDrawn() {
6587         synchronized (mLock) {
6588             if (!mScreenOnEarly || mWindowManagerDrawComplete) {
6589                 return; // Screen is not turned on or we did already handle this case earlier.
6590             }
6591
6592             mWindowManagerDrawComplete = true;
6593         }
6594
6595         finishScreenTurningOn();
6596     }
6597
6598     private void finishScreenTurningOn() {
6599         synchronized (mLock) {
6600             // We have just finished drawing screen content. Since the orientation listener
6601             // gets only installed when all windows are drawn, we try to install it again.
6602             updateOrientationListenerLp();
6603         }
6604         final ScreenOnListener listener;
6605         final boolean enableScreen;
6606         synchronized (mLock) {
6607             if (DEBUG_WAKEUP) Slog.d(TAG,
6608                     "finishScreenTurningOn: mAwake=" + mAwake
6609                             + ", mScreenOnEarly=" + mScreenOnEarly
6610                             + ", mScreenOnFully=" + mScreenOnFully
6611                             + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
6612                             + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
6613
6614             if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
6615                     || (mAwake && !mKeyguardDrawComplete)) {
6616                 return; // spurious or not ready yet
6617             }
6618
6619             if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
6620             listener = mScreenOnListener;
6621             mScreenOnListener = null;
6622             mScreenOnFully = true;
6623
6624             // Remember the first time we draw the keyguard so we know when we're done with
6625             // the main part of booting and can enable the screen and hide boot messages.
6626             if (!mKeyguardDrawnOnce && mAwake) {
6627                 mKeyguardDrawnOnce = true;
6628                 enableScreen = true;
6629                 if (mBootMessageNeedsHiding) {
6630                     mBootMessageNeedsHiding = false;
6631                     hideBootMessages();
6632                 }
6633             } else {
6634                 enableScreen = false;
6635             }
6636         }
6637
6638         if (listener != null) {
6639             listener.onScreenOn();
6640         }
6641
6642         if (enableScreen) {
6643             try {
6644                 mWindowManager.enableScreenIfNeeded();
6645             } catch (RemoteException unhandled) {
6646             }
6647         }
6648     }
6649
6650     private void handleHideBootMessage() {
6651         synchronized (mLock) {
6652             if (!mKeyguardDrawnOnce) {
6653                 mBootMessageNeedsHiding = true;
6654                 return; // keyguard hasn't drawn the first time yet, not done booting
6655             }
6656         }
6657
6658         if (mBootMsgDialog != null) {
6659             if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
6660             mBootMsgDialog.dismiss();
6661             mBootMsgDialog = null;
6662         }
6663     }
6664
6665     @Override
6666     public boolean isScreenOn() {
6667         return mScreenOnFully;
6668     }
6669
6670     /** {@inheritDoc} */
6671     @Override
6672     public void enableKeyguard(boolean enabled) {
6673         if (mKeyguardDelegate != null) {
6674             mKeyguardDelegate.setKeyguardEnabled(enabled);
6675         }
6676     }
6677
6678     /** {@inheritDoc} */
6679     @Override
6680     public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
6681         if (mKeyguardDelegate != null) {
6682             mKeyguardDelegate.verifyUnlock(callback);
6683         }
6684     }
6685
6686     @Override
6687     public boolean isKeyguardShowingAndNotOccluded() {
6688         if (mKeyguardDelegate == null) return false;
6689         return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
6690     }
6691
6692     @Override
6693     public boolean isKeyguardTrustedLw() {
6694         if (mKeyguardDelegate == null) return false;
6695         return mKeyguardDelegate.isTrusted();
6696     }
6697
6698     /** {@inheritDoc} */
6699     @Override
6700     public boolean isKeyguardLocked() {
6701         return keyguardOn();
6702     }
6703
6704     /** {@inheritDoc} */
6705     @Override
6706     public boolean isKeyguardSecure(int userId) {
6707         if (mKeyguardDelegate == null) return false;
6708         return mKeyguardDelegate.isSecure(userId);
6709     }
6710
6711     /** {@inheritDoc} */
6712     @Override
6713     public boolean isKeyguardOccluded() {
6714         if (mKeyguardDelegate == null) return false;
6715         return mKeyguardOccluded;
6716     }
6717
6718     /** {@inheritDoc} */
6719     @Override
6720     public boolean inKeyguardRestrictedKeyInputMode() {
6721         if (mKeyguardDelegate == null) return false;
6722         return mKeyguardDelegate.isInputRestricted();
6723     }
6724
6725     @Override
6726     public void dismissKeyguardLw(IKeyguardDismissCallback callback) {
6727         if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
6728             if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
6729
6730             // ask the keyguard to prompt the user to authenticate if necessary
6731             mKeyguardDelegate.dismiss(callback);
6732         } else if (callback != null) {
6733             try {
6734                 callback.onDismissError();
6735             } catch (RemoteException e) {
6736                 Slog.w(TAG, "Failed to call callback", e);
6737             }
6738         }
6739     }
6740
6741     @Override
6742     public boolean isKeyguardDrawnLw() {
6743         synchronized (mLock) {
6744             return mKeyguardDrawnOnce;
6745         }
6746     }
6747
6748     @Override
6749     public boolean isShowingDreamLw() {
6750         return mShowingDream;
6751     }
6752
6753     @Override
6754     public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
6755         if (mKeyguardDelegate != null) {
6756             if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
6757             mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
6758         }
6759     }
6760
6761     @Override
6762     public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6763             Rect outInsets) {
6764         outInsets.setEmpty();
6765
6766         // Navigation bar and status bar.
6767         getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
6768         outInsets.top = mStatusBarHeight;
6769     }
6770
6771     @Override
6772     public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6773             Rect outInsets) {
6774         outInsets.setEmpty();
6775
6776         // Only navigation bar
6777         if (mHasNavigationBar) {
6778             int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
6779             if (position == NAV_BAR_BOTTOM) {
6780                 outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
6781             } else if (position == NAV_BAR_RIGHT) {
6782                 outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
6783             } else if (position == NAV_BAR_LEFT) {
6784                 outInsets.left = getNavigationBarWidth(displayRotation, mUiMode);
6785             }
6786         }
6787     }
6788
6789     @Override
6790     public boolean isNavBarForcedShownLw(WindowState windowState) {
6791         return mForceShowSystemBars;
6792     }
6793
6794     @Override
6795     public boolean isDockSideAllowed(int dockSide) {
6796
6797         // We do not allow all dock sides at which the navigation bar touches the docked stack.
6798         if (!mNavigationBarCanMove) {
6799             return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT;
6800         } else {
6801             return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT;
6802         }
6803     }
6804
6805     void sendCloseSystemWindows() {
6806         PhoneWindow.sendCloseSystemWindows(mContext, null);
6807     }
6808
6809     void sendCloseSystemWindows(String reason) {
6810         PhoneWindow.sendCloseSystemWindows(mContext, reason);
6811     }
6812
6813     @Override
6814     public int rotationForOrientationLw(int orientation, int lastRotation) {
6815         if (false) {
6816             Slog.v(TAG, "rotationForOrientationLw(orient="
6817                         + orientation + ", last=" + lastRotation
6818                         + "); user=" + mUserRotation + " "
6819                         + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
6820                             ? "USER_ROTATION_LOCKED" : "")
6821                         );
6822         }
6823
6824         if (mForceDefaultOrientation) {
6825             return Surface.ROTATION_0;
6826         }
6827
6828         synchronized (mLock) {
6829             int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
6830             if (sensorRotation < 0) {
6831                 sensorRotation = lastRotation;
6832             }
6833
6834             final int preferredRotation;
6835             if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
6836                 // Ignore sensor when lid switch is open and rotation is forced.
6837                 preferredRotation = mLidOpenRotation;
6838             } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
6839                     && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
6840                 // Ignore sensor when in car dock unless explicitly enabled.
6841                 // This case can override the behavior of NOSENSOR, and can also
6842                 // enable 180 degree rotation while docked.
6843                 preferredRotation = mCarDockEnablesAccelerometer
6844                         ? sensorRotation : mCarDockRotation;
6845             } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
6846                     || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
6847                     || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
6848                     && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
6849                 // Ignore sensor when in desk dock unless explicitly enabled.
6850                 // This case can override the behavior of NOSENSOR, and can also
6851                 // enable 180 degree rotation while docked.
6852                 preferredRotation = mDeskDockEnablesAccelerometer
6853                         ? sensorRotation : mDeskDockRotation;
6854             } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
6855                 // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
6856                 // Note that the dock orientation overrides the HDMI orientation.
6857                 preferredRotation = mDemoHdmiRotation;
6858             } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
6859                     && mUndockedHdmiRotation >= 0) {
6860                 // Ignore sensor when plugged into HDMI and an undocked orientation has
6861                 // been specified in the configuration (only for legacy devices without
6862                 // full multi-display support).
6863                 // Note that the dock orientation overrides the HDMI orientation.
6864                 preferredRotation = mUndockedHdmiRotation;
6865             } else if (mDemoRotationLock) {
6866                 // Ignore sensor when demo rotation lock is enabled.
6867                 // Note that the dock orientation and HDMI rotation lock override this.
6868                 preferredRotation = mDemoRotation;
6869             } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
6870                 // Application just wants to remain locked in the last rotation.
6871                 preferredRotation = lastRotation;
6872             } else if (!mSupportAutoRotation) {
6873                 // If we don't support auto-rotation then bail out here and ignore
6874                 // the sensor and any rotation lock settings.
6875                 preferredRotation = -1;
6876             } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
6877                             && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
6878                                     || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
6879                                     || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
6880                                     || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
6881                                     || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
6882                     || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
6883                     || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6884                     || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
6885                     || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
6886                 // Otherwise, use sensor only if requested by the application or enabled
6887                 // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
6888                 if (mAllowAllRotations < 0) {
6889                     // Can't read this during init() because the context doesn't
6890                     // have display metrics at that time so we cannot determine
6891                     // tablet vs. phone then.
6892                     mAllowAllRotations = mContext.getResources().getBoolean(
6893                             com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
6894                 }
6895                 if (sensorRotation != Surface.ROTATION_180
6896                         || mAllowAllRotations == 1
6897                         || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6898                         || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
6899                     preferredRotation = sensorRotation;
6900                 } else {
6901                     preferredRotation = lastRotation;
6902                 }
6903             } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
6904                     && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
6905                 // Apply rotation lock.  Does not apply to NOSENSOR.
6906                 // The idea is that the user rotation expresses a weak preference for the direction
6907                 // of gravity and as NOSENSOR is never affected by gravity, then neither should
6908                 // NOSENSOR be affected by rotation lock (although it will be affected by docks).
6909                 preferredRotation = mUserRotation;
6910             } else {
6911                 // No overriding preference.
6912                 // We will do exactly what the application asked us to do.
6913                 preferredRotation = -1;
6914             }
6915
6916             switch (orientation) {
6917                 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6918                     // Return portrait unless overridden.
6919                     if (isAnyPortrait(preferredRotation)) {
6920                         return preferredRotation;
6921                     }
6922                     return mPortraitRotation;
6923
6924                 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6925                     // Return landscape unless overridden.
6926                     if (isLandscapeOrSeascape(preferredRotation)) {
6927                         return preferredRotation;
6928                     }
6929                     return mLandscapeRotation;
6930
6931                 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6932                     // Return reverse portrait unless overridden.
6933                     if (isAnyPortrait(preferredRotation)) {
6934                         return preferredRotation;
6935                     }
6936                     return mUpsideDownRotation;
6937
6938                 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6939                     // Return seascape unless overridden.
6940                     if (isLandscapeOrSeascape(preferredRotation)) {
6941                         return preferredRotation;
6942                     }
6943                     return mSeascapeRotation;
6944
6945                 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6946                 case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
6947                     // Return either landscape rotation.
6948                     if (isLandscapeOrSeascape(preferredRotation)) {
6949                         return preferredRotation;
6950                     }
6951                     if (isLandscapeOrSeascape(lastRotation)) {
6952                         return lastRotation;
6953                     }
6954                     return mLandscapeRotation;
6955
6956                 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6957                 case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
6958                     // Return either portrait rotation.
6959                     if (isAnyPortrait(preferredRotation)) {
6960                         return preferredRotation;
6961                     }
6962                     if (isAnyPortrait(lastRotation)) {
6963                         return lastRotation;
6964                     }
6965                     return mPortraitRotation;
6966
6967                 default:
6968                     // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
6969                     // just return the preferred orientation we already calculated.
6970                     if (preferredRotation >= 0) {
6971                         return preferredRotation;
6972                     }
6973                     return Surface.ROTATION_0;
6974             }
6975         }
6976     }
6977
6978     @Override
6979     public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
6980         switch (orientation) {
6981             case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6982             case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6983             case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6984                 return isAnyPortrait(rotation);
6985
6986             case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6987             case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6988             case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6989                 return isLandscapeOrSeascape(rotation);
6990
6991             default:
6992                 return true;
6993         }
6994     }
6995
6996     @Override
6997     public void setRotationLw(int rotation) {
6998         mOrientationListener.setCurrentRotation(rotation);
6999     }
7000
7001     private boolean isLandscapeOrSeascape(int rotation) {
7002         return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
7003     }
7004
7005     private boolean isAnyPortrait(int rotation) {
7006         return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
7007     }
7008
7009     @Override
7010     public int getUserRotationMode() {
7011         return Settings.System.getIntForUser(mContext.getContentResolver(),
7012                 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
7013                         WindowManagerPolicy.USER_ROTATION_FREE :
7014                                 WindowManagerPolicy.USER_ROTATION_LOCKED;
7015     }
7016
7017     // User rotation: to be used when all else fails in assigning an orientation to the device
7018     @Override
7019     public void setUserRotationMode(int mode, int rot) {
7020         ContentResolver res = mContext.getContentResolver();
7021
7022         // mUserRotationMode and mUserRotation will be assigned by the content observer
7023         if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
7024             Settings.System.putIntForUser(res,
7025                     Settings.System.USER_ROTATION,
7026                     rot,
7027                     UserHandle.USER_CURRENT);
7028             Settings.System.putIntForUser(res,
7029                     Settings.System.ACCELEROMETER_ROTATION,
7030                     0,
7031                     UserHandle.USER_CURRENT);
7032         } else {
7033             Settings.System.putIntForUser(res,
7034                     Settings.System.ACCELEROMETER_ROTATION,
7035                     1,
7036                     UserHandle.USER_CURRENT);
7037         }
7038     }
7039
7040     @Override
7041     public void setSafeMode(boolean safeMode) {
7042         mSafeMode = safeMode;
7043         performHapticFeedbackLw(null, safeMode
7044                 ? HapticFeedbackConstants.SAFE_MODE_ENABLED
7045                 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
7046     }
7047
7048     static long[] getLongIntArray(Resources r, int resid) {
7049         int[] ar = r.getIntArray(resid);
7050         if (ar == null) {
7051             return null;
7052         }
7053         long[] out = new long[ar.length];
7054         for (int i=0; i<ar.length; i++) {
7055             out[i] = ar[i];
7056         }
7057         return out;
7058     }
7059
7060     /** {@inheritDoc} */
7061     @Override
7062     public void systemReady() {
7063         mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
7064                 new StateCallback() {
7065                     @Override
7066                     public void onTrustedChanged() {
7067                         mWindowManagerFuncs.notifyKeyguardTrustedChanged();
7068                     }
7069                 });
7070         mKeyguardDelegate.onSystemReady();
7071
7072         mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
7073         if (mVrManagerInternal != null) {
7074             mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
7075         }
7076
7077         readCameraLensCoverState();
7078         updateUiMode();
7079         boolean bindKeyguardNow;
7080         synchronized (mLock) {
7081             updateOrientationListenerLp();
7082             mSystemReady = true;
7083             mHandler.post(new Runnable() {
7084                 @Override
7085                 public void run() {
7086                     updateSettings();
7087                 }
7088             });
7089
7090             bindKeyguardNow = mDeferBindKeyguard;
7091             if (bindKeyguardNow) {
7092                 // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now.
7093                 mDeferBindKeyguard = false;
7094             }
7095         }
7096
7097         if (bindKeyguardNow) {
7098             mKeyguardDelegate.bindService(mContext);
7099             mKeyguardDelegate.onBootCompleted();
7100         }
7101         mSystemGestures.systemReady();
7102         mImmersiveModeConfirmation.systemReady();
7103     }
7104
7105     /** {@inheritDoc} */
7106     @Override
7107     public void systemBooted() {
7108         boolean bindKeyguardNow = false;
7109         synchronized (mLock) {
7110             // Time to bind Keyguard; take care to only bind it once, either here if ready or
7111             // in systemReady if not.
7112             if (mKeyguardDelegate != null) {
7113                 bindKeyguardNow = true;
7114             } else {
7115                 // Because mKeyguardDelegate is null, we know that the synchronized block in
7116                 // systemReady didn't run yet and setting this will actually have an effect.
7117                 mDeferBindKeyguard = true;
7118             }
7119         }
7120         if (bindKeyguardNow) {
7121             mKeyguardDelegate.bindService(mContext);
7122             mKeyguardDelegate.onBootCompleted();
7123         }
7124         synchronized (mLock) {
7125             mSystemBooted = true;
7126         }
7127         startedWakingUp();
7128         screenTurningOn(null);
7129         screenTurnedOn();
7130     }
7131
7132     ProgressDialog mBootMsgDialog = null;
7133
7134     /** {@inheritDoc} */
7135     @Override
7136     public void showBootMessage(final CharSequence msg, final boolean always) {
7137         mHandler.post(new Runnable() {
7138             @Override public void run() {
7139                 if (mBootMsgDialog == null) {
7140                     int theme;
7141                     if (mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK)) {
7142                         theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
7143                     } else {
7144                         theme = 0;
7145                     }
7146
7147                     mBootMsgDialog = new ProgressDialog(mContext, theme) {
7148                         // This dialog will consume all events coming in to
7149                         // it, to avoid it trying to do things too early in boot.
7150                         @Override public boolean dispatchKeyEvent(KeyEvent event) {
7151                             return true;
7152                         }
7153                         @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7154                             return true;
7155                         }
7156                         @Override public boolean dispatchTouchEvent(MotionEvent ev) {
7157                             return true;
7158                         }
7159                         @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
7160                             return true;
7161                         }
7162                         @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
7163                             return true;
7164                         }
7165                         @Override public boolean dispatchPopulateAccessibilityEvent(
7166                                 AccessibilityEvent event) {
7167                             return true;
7168                         }
7169                     };
7170                     if (mContext.getPackageManager().isUpgrade()) {
7171                         mBootMsgDialog.setTitle(R.string.android_upgrading_title);
7172                     } else {
7173                         mBootMsgDialog.setTitle(R.string.android_start_title);
7174                     }
7175                     mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
7176                     mBootMsgDialog.setIndeterminate(true);
7177                     mBootMsgDialog.getWindow().setType(
7178                             WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
7179                     mBootMsgDialog.getWindow().addFlags(
7180                             WindowManager.LayoutParams.FLAG_DIM_BEHIND
7181                             | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
7182                     mBootMsgDialog.getWindow().setDimAmount(1);
7183                     WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
7184                     lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
7185                     mBootMsgDialog.getWindow().setAttributes(lp);
7186                     mBootMsgDialog.setCancelable(false);
7187                     mBootMsgDialog.show();
7188                 }
7189                 mBootMsgDialog.setMessage(msg);
7190             }
7191         });
7192     }
7193
7194     /** {@inheritDoc} */
7195     @Override
7196     public void hideBootMessages() {
7197         mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
7198     }
7199
7200     /** {@inheritDoc} */
7201     @Override
7202     public void userActivity() {
7203         // ***************************************
7204         // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
7205         // ***************************************
7206         // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
7207         // WITH ITS LOCKS HELD.
7208         //
7209         // This code must be VERY careful about the locks
7210         // it acquires.
7211         // In fact, the current code acquires way too many,
7212         // and probably has lurking deadlocks.
7213
7214         synchronized (mScreenLockTimeout) {
7215             if (mLockScreenTimerActive) {
7216                 // reset the timer
7217                 mHandler.removeCallbacks(mScreenLockTimeout);
7218                 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7219             }
7220         }
7221     }
7222
7223     class ScreenLockTimeout implements Runnable {
7224         Bundle options;
7225
7226         @Override
7227         public void run() {
7228             synchronized (this) {
7229                 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
7230                 if (mKeyguardDelegate != null) {
7231                     mKeyguardDelegate.doKeyguardTimeout(options);
7232                 }
7233                 mLockScreenTimerActive = false;
7234                 options = null;
7235             }
7236         }
7237
7238         public void setLockOptions(Bundle options) {
7239             this.options = options;
7240         }
7241     }
7242
7243     ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
7244
7245     @Override
7246     public void lockNow(Bundle options) {
7247         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
7248         mHandler.removeCallbacks(mScreenLockTimeout);
7249         if (options != null) {
7250             // In case multiple calls are made to lockNow, we don't wipe out the options
7251             // until the runnable actually executes.
7252             mScreenLockTimeout.setLockOptions(options);
7253         }
7254         mHandler.post(mScreenLockTimeout);
7255     }
7256
7257     private void updateLockScreenTimeout() {
7258         synchronized (mScreenLockTimeout) {
7259             boolean enable = (mAllowLockscreenWhenOn && mAwake &&
7260                     mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
7261             if (mLockScreenTimerActive != enable) {
7262                 if (enable) {
7263                     if (localLOGV) Log.v(TAG, "setting lockscreen timer");
7264                     mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
7265                     mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7266                 } else {
7267                     if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
7268                     mHandler.removeCallbacks(mScreenLockTimeout);
7269                 }
7270                 mLockScreenTimerActive = enable;
7271             }
7272         }
7273     }
7274
7275     private void updateDreamingSleepToken(boolean acquire) {
7276         if (acquire) {
7277             if (mDreamingSleepToken == null) {
7278                 mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream");
7279             }
7280         } else {
7281             if (mDreamingSleepToken != null) {
7282                 mDreamingSleepToken.release();
7283                 mDreamingSleepToken = null;
7284             }
7285         }
7286     }
7287
7288     private void updateScreenOffSleepToken(boolean acquire) {
7289         if (acquire) {
7290             if (mScreenOffSleepToken == null) {
7291                 mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff");
7292             }
7293         } else {
7294             if (mScreenOffSleepToken != null) {
7295                 mScreenOffSleepToken.release();
7296                 mScreenOffSleepToken = null;
7297             }
7298         }
7299     }
7300
7301     /** {@inheritDoc} */
7302     @Override
7303     public void enableScreenAfterBoot() {
7304         readLidState();
7305         applyLidSwitchState();
7306         updateRotation(true);
7307     }
7308
7309     private void applyLidSwitchState() {
7310         if (mLidState == LID_CLOSED && mLidControlsSleep) {
7311             mPowerManager.goToSleep(SystemClock.uptimeMillis(),
7312                     PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
7313                     PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
7314         } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
7315             mWindowManagerFuncs.lockDeviceNow();
7316         }
7317
7318         synchronized (mLock) {
7319             updateWakeGestureListenerLp();
7320         }
7321     }
7322
7323     void updateUiMode() {
7324         if (mUiModeManager == null) {
7325             mUiModeManager = IUiModeManager.Stub.asInterface(
7326                     ServiceManager.getService(Context.UI_MODE_SERVICE));
7327         }
7328         try {
7329             mUiMode = mUiModeManager.getCurrentModeType();
7330         } catch (RemoteException e) {
7331         }
7332     }
7333
7334     void updateRotation(boolean alwaysSendConfiguration) {
7335         try {
7336             //set orientation on WindowManager
7337             mWindowManager.updateRotation(alwaysSendConfiguration, false);
7338         } catch (RemoteException e) {
7339             // Ignore
7340         }
7341     }
7342
7343     void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
7344         try {
7345             //set orientation on WindowManager
7346             mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
7347         } catch (RemoteException e) {
7348             // Ignore
7349         }
7350     }
7351
7352     /**
7353      * Return an Intent to launch the currently active dock app as home.  Returns
7354      * null if the standard home should be launched, which is the case if any of the following is
7355      * true:
7356      * <ul>
7357      *  <li>The device is not in either car mode or desk mode
7358      *  <li>The device is in car mode but mEnableCarDockHomeCapture is false
7359      *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
7360      *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
7361      *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
7362      * </ul>
7363      * @return A dock intent.
7364      */
7365     Intent createHomeDockIntent() {
7366         Intent intent = null;
7367
7368         // What home does is based on the mode, not the dock state.  That
7369         // is, when in car mode you should be taken to car home regardless
7370         // of whether we are actually in a car dock.
7371         if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
7372             if (mEnableCarDockHomeCapture) {
7373                 intent = mCarDockIntent;
7374             }
7375         } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
7376             if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
7377                 intent = mDeskDockIntent;
7378             }
7379         } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
7380                 && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7381                         || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
7382                         || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
7383             // Always launch dock home from home when watch is docked, if it exists.
7384             intent = mDeskDockIntent;
7385         } else if (mUiMode == Configuration.UI_MODE_TYPE_VR_HEADSET) {
7386             if (ENABLE_VR_HEADSET_HOME_CAPTURE) {
7387                 intent = mVrHeadsetHomeIntent;
7388             }
7389         }
7390
7391         if (intent == null) {
7392             return null;
7393         }
7394
7395         ActivityInfo ai = null;
7396         ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
7397                 intent,
7398                 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
7399                 mCurrentUserId);
7400         if (info != null) {
7401             ai = info.activityInfo;
7402         }
7403         if (ai != null
7404                 && ai.metaData != null
7405                 && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
7406             intent = new Intent(intent);
7407             intent.setClassName(ai.packageName, ai.name);
7408             return intent;
7409         }
7410
7411         return null;
7412     }
7413
7414     void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
7415         if (awakenFromDreams) {
7416             awakenDreams();
7417         }
7418
7419         Intent dock = createHomeDockIntent();
7420         if (dock != null) {
7421             try {
7422                 if (fromHomeKey) {
7423                     dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7424                 }
7425                 startActivityAsUser(dock, UserHandle.CURRENT);
7426                 return;
7427             } catch (ActivityNotFoundException e) {
7428             }
7429         }
7430
7431         Intent intent;
7432
7433         if (fromHomeKey) {
7434             intent = new Intent(mHomeIntent);
7435             intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7436         } else {
7437             intent = mHomeIntent;
7438         }
7439
7440         startActivityAsUser(intent, UserHandle.CURRENT);
7441     }
7442
7443     /**
7444      * goes to the home screen
7445      * @return whether it did anything
7446      */
7447     boolean goHome() {
7448         if (!isUserSetupComplete()) {
7449             Slog.i(TAG, "Not going home because user setup is in progress.");
7450             return false;
7451         }
7452         if (false) {
7453             // This code always brings home to the front.
7454             try {
7455                 ActivityManager.getService().stopAppSwitches();
7456             } catch (RemoteException e) {
7457             }
7458             sendCloseSystemWindows();
7459             startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
7460         } else {
7461             // This code brings home to the front or, if it is already
7462             // at the front, puts the device to sleep.
7463             try {
7464                 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
7465                     /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
7466                     Log.d(TAG, "UTS-TEST-MODE");
7467                 } else {
7468                     ActivityManager.getService().stopAppSwitches();
7469                     sendCloseSystemWindows();
7470                     Intent dock = createHomeDockIntent();
7471                     if (dock != null) {
7472                         int result = ActivityManager.getService()
7473                                 .startActivityAsUser(null, null, dock,
7474                                         dock.resolveTypeIfNeeded(mContext.getContentResolver()),
7475                                         null, null, 0,
7476                                         ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7477                                         null, null, UserHandle.USER_CURRENT);
7478                         if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7479                             return false;
7480                         }
7481                     }
7482                 }
7483                 int result = ActivityManager.getService()
7484                         .startActivityAsUser(null, null, mHomeIntent,
7485                                 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
7486                                 null, null, 0,
7487                                 ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7488                                 null, null, UserHandle.USER_CURRENT);
7489                 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7490                     return false;
7491                 }
7492             } catch (RemoteException ex) {
7493                 // bummer, the activity manager, which is in this process, is dead
7494             }
7495         }
7496         return true;
7497     }
7498
7499     @Override
7500     public void setCurrentOrientationLw(int newOrientation) {
7501         synchronized (mLock) {
7502             if (newOrientation != mCurrentAppOrientation) {
7503                 mCurrentAppOrientation = newOrientation;
7504                 updateOrientationListenerLp();
7505             }
7506         }
7507     }
7508
7509     private boolean isTheaterModeEnabled() {
7510         return Settings.Global.getInt(mContext.getContentResolver(),
7511                 Settings.Global.THEATER_MODE_ON, 0) == 1;
7512     }
7513
7514     private boolean areSystemNavigationKeysEnabled() {
7515         return Settings.Secure.getIntForUser(mContext.getContentResolver(),
7516                 Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
7517     }
7518
7519     @Override
7520     public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
7521         if (!mVibrator.hasVibrator()) {
7522             return false;
7523         }
7524         final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
7525                 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
7526         if (hapticsDisabled && !always) {
7527             return false;
7528         }
7529         long[] pattern = null;
7530         switch (effectId) {
7531             case HapticFeedbackConstants.LONG_PRESS:
7532                 pattern = mLongPressVibePattern;
7533                 break;
7534             case HapticFeedbackConstants.VIRTUAL_KEY:
7535                 pattern = mVirtualKeyVibePattern;
7536                 break;
7537             case HapticFeedbackConstants.KEYBOARD_TAP:
7538                 pattern = mKeyboardTapVibePattern;
7539                 break;
7540             case HapticFeedbackConstants.CLOCK_TICK:
7541                 pattern = mClockTickVibePattern;
7542                 break;
7543             case HapticFeedbackConstants.CALENDAR_DATE:
7544                 pattern = mCalendarDateVibePattern;
7545                 break;
7546             case HapticFeedbackConstants.SAFE_MODE_DISABLED:
7547                 pattern = mSafeModeDisabledVibePattern;
7548                 break;
7549             case HapticFeedbackConstants.SAFE_MODE_ENABLED:
7550                 pattern = mSafeModeEnabledVibePattern;
7551                 break;
7552             case HapticFeedbackConstants.CONTEXT_CLICK:
7553                 pattern = mContextClickVibePattern;
7554                 break;
7555             default:
7556                 return false;
7557         }
7558         int owningUid;
7559         String owningPackage;
7560         if (win != null) {
7561             owningUid = win.getOwningUid();
7562             owningPackage = win.getOwningPackage();
7563         } else {
7564             owningUid = android.os.Process.myUid();
7565             owningPackage = mContext.getOpPackageName();
7566         }
7567         if (pattern.length == 1) {
7568             // One-shot vibration
7569             mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES);
7570         } else {
7571             // Pattern vibration
7572             mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES);
7573         }
7574         return true;
7575     }
7576
7577     @Override
7578     public void keepScreenOnStartedLw() {
7579     }
7580
7581     @Override
7582     public void keepScreenOnStoppedLw() {
7583         if (isKeyguardShowingAndNotOccluded()) {
7584             mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
7585         }
7586     }
7587
7588     private int updateSystemUiVisibilityLw() {
7589         // If there is no window focused, there will be nobody to handle the events
7590         // anyway, so just hang on in whatever state we're in until things settle down.
7591         WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
7592                 : mTopFullscreenOpaqueWindowState;
7593         if (winCandidate == null) {
7594             return 0;
7595         }
7596         if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
7597             // The immersive mode confirmation should never affect the system bar visibility,
7598             // otherwise it will unhide the navigation bar and hide itself.
7599             winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState;
7600             if (winCandidate == null) {
7601                 return 0;
7602             }
7603         }
7604         final WindowState win = winCandidate;
7605         if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mKeyguardOccluded) {
7606             // We are updating at a point where the keyguard has gotten
7607             // focus, but we were last in a state where the top window is
7608             // hiding it.  This is probably because the keyguard as been
7609             // shown while the top window was displayed, so we want to ignore
7610             // it here because this is just a very transient change and it
7611             // will quickly lose focus once it correctly gets hidden.
7612             return 0;
7613         }
7614
7615         int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
7616                 & ~mResettingSystemUiFlags
7617                 & ~mForceClearedSystemUiFlags;
7618         if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
7619             tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
7620         }
7621
7622         final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
7623                 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
7624         final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
7625                 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
7626         mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);
7627         mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);
7628         final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
7629         final int diff = visibility ^ mLastSystemUiFlags;
7630         final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
7631         final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
7632         final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
7633         if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
7634                 && mFocusedApp == win.getAppToken()
7635                 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
7636                 && mLastDockedStackBounds.equals(mDockedStackBounds)) {
7637             return 0;
7638         }
7639         mLastSystemUiFlags = visibility;
7640         mLastFullscreenStackSysUiFlags = fullscreenVisibility;
7641         mLastDockedStackSysUiFlags = dockedVisibility;
7642         mLastFocusNeedsMenu = needsMenu;
7643         mFocusedApp = win.getAppToken();
7644         final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
7645         final Rect dockedStackBounds = new Rect(mDockedStackBounds);
7646         mHandler.post(new Runnable() {
7647                 @Override
7648                 public void run() {
7649                     StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
7650                     if (statusbar != null) {
7651                         statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
7652                                 dockedVisibility, 0xffffffff, fullscreenStackBounds,
7653                                 dockedStackBounds, win.toString());
7654                         statusbar.topAppWindowChanged(needsMenu);
7655                     }
7656                 }
7657             });
7658         return diff;
7659     }
7660
7661     private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
7662         WindowState statusColorWin = isStatusBarKeyguard() && !mKeyguardOccluded
7663                 ? mStatusBar
7664                 : opaqueOrDimming;
7665
7666         if (statusColorWin != null) {
7667             if (statusColorWin == opaque) {
7668                 // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7669                 // its light flag.
7670                 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7671                 vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
7672                         & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7673             } else if (statusColorWin != null && statusColorWin.isDimming()) {
7674                 // Otherwise if it's dimming, clear the light flag.
7675                 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7676             }
7677         }
7678         return vis;
7679     }
7680
7681     private int updateLightNavigationBarLw(int vis, WindowState opaque,
7682             WindowState opaqueOrDimming) {
7683         final WindowState imeWin = mWindowManagerFuncs.getInputMethodWindowLw();
7684
7685         final WindowState navColorWin;
7686         if (imeWin != null && imeWin.isVisibleLw()) {
7687             navColorWin = imeWin;
7688         } else {
7689             navColorWin = opaqueOrDimming;
7690         }
7691
7692         if (navColorWin != null) {
7693             if (navColorWin == opaque) {
7694                 // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7695                 // its light flag.
7696                 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7697                 vis |= PolicyControl.getSystemUiVisibility(navColorWin, null)
7698                         & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7699             } else if (navColorWin.isDimming() || navColorWin == imeWin) {
7700                 // Otherwise if it's dimming or it's the IME window, clear the light flag.
7701                 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7702             }
7703         }
7704         return vis;
7705     }
7706
7707     private boolean drawsSystemBarBackground(WindowState win) {
7708         return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
7709     }
7710
7711     private boolean forcesDrawStatusBarBackground(WindowState win) {
7712         return win == null || (win.getAttrs().privateFlags
7713                 & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
7714     }
7715
7716     private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
7717         final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
7718         final boolean freeformStackVisible =
7719                 mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
7720         final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
7721
7722         // We need to force system bars when the docked stack is visible, when the freeform stack
7723         // is visible but also when we are resizing for the transitions when docked stack
7724         // visibility changes.
7725         mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
7726         final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
7727
7728         // apply translucent bar vis flags
7729         WindowState fullscreenTransWin = isStatusBarKeyguard() && !mKeyguardOccluded
7730                 ? mStatusBar
7731                 : mTopFullscreenOpaqueWindowState;
7732         vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7733         vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7734         final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
7735                 mTopDockedOpaqueWindowState, 0, 0);
7736
7737         final boolean fullscreenDrawsStatusBarBackground =
7738                 (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
7739                         && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
7740                 || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
7741         final boolean dockedDrawsStatusBarBackground =
7742                 (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
7743                         && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
7744                 || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
7745
7746         // prevent status bar interaction from clearing certain flags
7747         int type = win.getAttrs().type;
7748         boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
7749         if (statusBarHasFocus && !isStatusBarKeyguard()) {
7750             int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
7751                     | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
7752                     | View.SYSTEM_UI_FLAG_IMMERSIVE
7753                     | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
7754                     | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7755             if (mKeyguardOccluded) {
7756                 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
7757             }
7758             vis = (vis & ~flags) | (oldVis & flags);
7759         }
7760
7761         if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
7762             vis |= View.STATUS_BAR_TRANSPARENT;
7763             vis &= ~View.STATUS_BAR_TRANSLUCENT;
7764         } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
7765                 || forceOpaqueStatusBar) {
7766             vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
7767         }
7768
7769         vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
7770
7771         // update status bar
7772         boolean immersiveSticky =
7773                 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7774         final boolean hideStatusBarWM =
7775                 mTopFullscreenOpaqueWindowState != null
7776                 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
7777                         & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
7778         final boolean hideStatusBarSysui =
7779                 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
7780         final boolean hideNavBarSysui =
7781                 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
7782
7783         final boolean transientStatusBarAllowed = mStatusBar != null
7784                 && (statusBarHasFocus || (!mForceShowSystemBars
7785                         && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
7786
7787         final boolean transientNavBarAllowed = mNavigationBar != null
7788                 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
7789
7790         final long now = SystemClock.uptimeMillis();
7791         final boolean pendingPanic = mPendingPanicGestureUptime != 0
7792                 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
7793         if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
7794             // The user performed the panic gesture recently, we're about to hide the bars,
7795             // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
7796             mPendingPanicGestureUptime = 0;
7797             mStatusBarController.showTransient();
7798             if (!isNavBarEmpty(vis)) {
7799                 mNavigationBarController.showTransient();
7800             }
7801         }
7802
7803         final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
7804                 && !transientStatusBarAllowed && hideStatusBarSysui;
7805         final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
7806                 && !transientNavBarAllowed;
7807         if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
7808             // clear the clearable flags instead
7809             clearClearableFlagsLw();
7810             vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
7811         }
7812
7813         final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
7814         immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7815         final boolean navAllowedHidden = immersive || immersiveSticky;
7816
7817         if (hideNavBarSysui && !navAllowedHidden
7818                 && getWindowLayerLw(win) > getWindowLayerFromTypeLw(TYPE_INPUT_CONSUMER)) {
7819             // We can't hide the navbar from this window otherwise the input consumer would not get
7820             // the input events.
7821             vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
7822         }
7823
7824         vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
7825
7826         // update navigation bar
7827         boolean oldImmersiveMode = isImmersiveMode(oldVis);
7828         boolean newImmersiveMode = isImmersiveMode(vis);
7829         if (win != null && oldImmersiveMode != newImmersiveMode) {
7830             final String pkg = win.getOwningPackage();
7831             mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
7832                     isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility()));
7833         }
7834
7835         vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
7836
7837         vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState,
7838                 mTopFullscreenOpaqueOrDimmingWindowState);
7839
7840         return vis;
7841     }
7842
7843     /**
7844      * @return the current visibility flags with the nav-bar opacity related flags toggled based
7845      *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
7846      */
7847     private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
7848             boolean freeformStackVisible, boolean isDockedDividerResizing) {
7849         if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
7850             if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
7851                 visibility = setNavBarOpaqueFlag(visibility);
7852             }
7853         } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
7854             if (isDockedDividerResizing) {
7855                 visibility = setNavBarOpaqueFlag(visibility);
7856             } else if (freeformStackVisible) {
7857                 visibility = setNavBarTranslucentFlag(visibility);
7858             } else {
7859                 visibility = setNavBarOpaqueFlag(visibility);
7860             }
7861         }
7862
7863         if (!areTranslucentBarsAllowed()) {
7864             visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
7865         }
7866         return visibility;
7867     }
7868
7869     private int setNavBarOpaqueFlag(int visibility) {
7870         return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
7871     }
7872
7873     private int setNavBarTranslucentFlag(int visibility) {
7874         visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
7875         return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
7876     }
7877
7878     private void clearClearableFlagsLw() {
7879         int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
7880         if (newVal != mResettingSystemUiFlags) {
7881             mResettingSystemUiFlags = newVal;
7882             mWindowManagerFuncs.reevaluateStatusBarVisibility();
7883         }
7884     }
7885
7886     private boolean isImmersiveMode(int vis) {
7887         final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
7888         return mNavigationBar != null
7889                 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
7890                 && (vis & flags) != 0
7891                 && canHideNavigationBar();
7892     }
7893
7894     private static boolean isNavBarEmpty(int systemUiFlags) {
7895         final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
7896                 | View.STATUS_BAR_DISABLE_BACK
7897                 | View.STATUS_BAR_DISABLE_RECENT);
7898
7899         return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
7900     }
7901
7902     /**
7903      * @return whether the navigation or status bar can be made translucent
7904      *
7905      * This should return true unless touch exploration is not enabled or
7906      * R.boolean.config_enableTranslucentDecor is false.
7907      */
7908     private boolean areTranslucentBarsAllowed() {
7909         return mTranslucentDecorEnabled;
7910     }
7911
7912     // Use this instead of checking config_showNavigationBar so that it can be consistently
7913     // overridden by qemu.hw.mainkeys in the emulator.
7914     @Override
7915     public boolean hasNavigationBar() {
7916         return mHasNavigationBar;
7917     }
7918
7919     @Override
7920     public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
7921         mLastInputMethodWindow = ime;
7922         mLastInputMethodTargetWindow = target;
7923     }
7924
7925     @Override
7926     public int getInputMethodWindowVisibleHeightLw() {
7927         return mDockBottom - mCurBottom;
7928     }
7929
7930     @Override
7931     public void setCurrentUserLw(int newUserId) {
7932         mCurrentUserId = newUserId;
7933         if (mKeyguardDelegate != null) {
7934             mKeyguardDelegate.setCurrentUser(newUserId);
7935         }
7936         StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
7937         if (statusBar != null) {
7938             statusBar.setCurrentUser(newUserId);
7939         }
7940         setLastInputMethodWindowLw(null, null);
7941     }
7942
7943     @Override
7944     public void setSwitchingUser(boolean switching) {
7945         mKeyguardDelegate.setSwitchingUser(switching);
7946     }
7947
7948     @Override
7949     public boolean canMagnifyWindow(int windowType) {
7950         switch (windowType) {
7951             case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
7952             case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
7953             case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
7954             case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
7955                 return false;
7956             }
7957         }
7958         return true;
7959     }
7960
7961     @Override
7962     public boolean isTopLevelWindow(int windowType) {
7963         if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
7964                 && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
7965             return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
7966         }
7967         return true;
7968     }
7969
7970     @Override
7971     public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
7972         // For the upside down rotation we don't rotate seamlessly as the navigation
7973         // bar moves position.
7974         // Note most apps (using orientation:sensor or user as opposed to fullSensor)
7975         // will not enter the reverse portrait orientation, so actually the
7976         // orientation won't change at all.
7977         if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
7978             return false;
7979         }
7980         // If the navigation bar can't change sides, then it will
7981         // jump when we change orientations and we don't rotate
7982         // seamlessly.
7983         if (!mNavigationBarCanMove) {
7984             return false;
7985         }
7986         int delta = newRotation - oldRotation;
7987         if (delta < 0) delta += 4;
7988         // Likewise we don't rotate seamlessly for 180 degree rotations
7989         // in this case the surfaces never resize, and our logic to
7990         // revert the transformations on size change will fail. We could
7991         // fix this in the future with the "tagged" frames idea.
7992         if (delta == Surface.ROTATION_180) {
7993             return false;
7994         }
7995
7996         final WindowState w = mTopFullscreenOpaqueWindowState;
7997         if (w != mFocusedWindow) {
7998             return false;
7999         }
8000
8001         // We only enable seamless rotation if the top window has requested
8002         // it and is in the fullscreen opaque state. Seamless rotation
8003         // requires freezing various Surface states and won't work well
8004         // with animations, so we disable it in the animation case for now.
8005         if (w != null && !w.isAnimatingLw() &&
8006                 ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) ||
8007                         (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) {
8008             return true;
8009         }
8010         return false;
8011     }
8012
8013     @Override
8014     public void dump(String prefix, PrintWriter pw, String[] args) {
8015         pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
8016                 pw.print(" mSystemReady="); pw.print(mSystemReady);
8017                 pw.print(" mSystemBooted="); pw.println(mSystemBooted);
8018         pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
8019                 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
8020                 pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
8021                 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
8022         if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
8023                 || mForceClearedSystemUiFlags != 0) {
8024             pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
8025                     pw.print(Integer.toHexString(mLastSystemUiFlags));
8026                     pw.print(" mResettingSystemUiFlags=0x");
8027                     pw.print(Integer.toHexString(mResettingSystemUiFlags));
8028                     pw.print(" mForceClearedSystemUiFlags=0x");
8029                     pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
8030         }
8031         if (mLastFocusNeedsMenu) {
8032             pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
8033                     pw.println(mLastFocusNeedsMenu);
8034         }
8035         pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
8036                 pw.println(mWakeGestureEnabledSetting);
8037
8038         pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
8039         pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
8040                 pw.print(" mDockMode="); pw.print(mDockMode);
8041                 pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
8042                 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
8043                 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
8044         pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
8045                 pw.print(" mUserRotation="); pw.print(mUserRotation);
8046                 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
8047         pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
8048         pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
8049                 pw.print(mCarDockEnablesAccelerometer);
8050                 pw.print(" mDeskDockEnablesAccelerometer=");
8051                 pw.println(mDeskDockEnablesAccelerometer);
8052         pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
8053                 pw.print(mLidKeyboardAccessibility);
8054                 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
8055                 pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
8056                 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
8057         pw.print(prefix);
8058                 pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
8059         pw.print(prefix);
8060                 pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
8061                 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
8062         pw.print(prefix);
8063                 pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
8064                 pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
8065         pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
8066         pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
8067         pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
8068                 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
8069         pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
8070                 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
8071         pw.print(prefix); pw.print("mOrientationSensorEnabled=");
8072                 pw.println(mOrientationSensorEnabled);
8073         pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
8074                 pw.print(","); pw.print(mOverscanScreenTop);
8075                 pw.print(") "); pw.print(mOverscanScreenWidth);
8076                 pw.print("x"); pw.println(mOverscanScreenHeight);
8077         if (mOverscanLeft != 0 || mOverscanTop != 0
8078                 || mOverscanRight != 0 || mOverscanBottom != 0) {
8079             pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
8080                     pw.print(" top="); pw.print(mOverscanTop);
8081                     pw.print(" right="); pw.print(mOverscanRight);
8082                     pw.print(" bottom="); pw.println(mOverscanBottom);
8083         }
8084         pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
8085                 pw.print(mRestrictedOverscanScreenLeft);
8086                 pw.print(","); pw.print(mRestrictedOverscanScreenTop);
8087                 pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
8088                 pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
8089         pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
8090                 pw.print(","); pw.print(mUnrestrictedScreenTop);
8091                 pw.print(") "); pw.print(mUnrestrictedScreenWidth);
8092                 pw.print("x"); pw.println(mUnrestrictedScreenHeight);
8093         pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
8094                 pw.print(","); pw.print(mRestrictedScreenTop);
8095                 pw.print(") "); pw.print(mRestrictedScreenWidth);
8096                 pw.print("x"); pw.println(mRestrictedScreenHeight);
8097         pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
8098                 pw.print(","); pw.print(mStableFullscreenTop);
8099                 pw.print(")-("); pw.print(mStableFullscreenRight);
8100                 pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
8101         pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
8102                 pw.print(","); pw.print(mStableTop);
8103                 pw.print(")-("); pw.print(mStableRight);
8104                 pw.print(","); pw.print(mStableBottom); pw.println(")");
8105         pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
8106                 pw.print(","); pw.print(mSystemTop);
8107                 pw.print(")-("); pw.print(mSystemRight);
8108                 pw.print(","); pw.print(mSystemBottom); pw.println(")");
8109         pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
8110                 pw.print(","); pw.print(mCurTop);
8111                 pw.print(")-("); pw.print(mCurRight);
8112                 pw.print(","); pw.print(mCurBottom); pw.println(")");
8113         pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
8114                 pw.print(","); pw.print(mContentTop);
8115                 pw.print(")-("); pw.print(mContentRight);
8116                 pw.print(","); pw.print(mContentBottom); pw.println(")");
8117         pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft);
8118                 pw.print(","); pw.print(mVoiceContentTop);
8119                 pw.print(")-("); pw.print(mVoiceContentRight);
8120                 pw.print(","); pw.print(mVoiceContentBottom); pw.println(")");
8121         pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
8122                 pw.print(","); pw.print(mDockTop);
8123                 pw.print(")-("); pw.print(mDockRight);
8124                 pw.print(","); pw.print(mDockBottom); pw.println(")");
8125         pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
8126                 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
8127         pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
8128                 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
8129                 pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
8130         if (mLastInputMethodWindow != null) {
8131             pw.print(prefix); pw.print("mLastInputMethodWindow=");
8132                     pw.println(mLastInputMethodWindow);
8133         }
8134         if (mLastInputMethodTargetWindow != null) {
8135             pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
8136                     pw.println(mLastInputMethodTargetWindow);
8137         }
8138         if (mStatusBar != null) {
8139             pw.print(prefix); pw.print("mStatusBar=");
8140                     pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
8141                     pw.println(isStatusBarKeyguard());
8142         }
8143         if (mNavigationBar != null) {
8144             pw.print(prefix); pw.print("mNavigationBar=");
8145                     pw.println(mNavigationBar);
8146         }
8147         if (mFocusedWindow != null) {
8148             pw.print(prefix); pw.print("mFocusedWindow=");
8149                     pw.println(mFocusedWindow);
8150         }
8151         if (mFocusedApp != null) {
8152             pw.print(prefix); pw.print("mFocusedApp=");
8153                     pw.println(mFocusedApp);
8154         }
8155         if (mTopFullscreenOpaqueWindowState != null) {
8156             pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
8157                     pw.println(mTopFullscreenOpaqueWindowState);
8158         }
8159         if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
8160             pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
8161                     pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
8162         }
8163         if (mForcingShowNavBar) {
8164             pw.print(prefix); pw.print("mForcingShowNavBar=");
8165                     pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
8166                     pw.println(mForcingShowNavBarLayer);
8167         }
8168         pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
8169                 pw.print(" mKeyguardOccluded="); pw.println(mKeyguardOccluded);
8170                 pw.print(" mKeyguardOccludedChanged="); pw.println(mKeyguardOccludedChanged);
8171                 pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded);
8172         pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
8173                 pw.print(" mForceStatusBarFromKeyguard=");
8174                 pw.println(mForceStatusBarFromKeyguard);
8175         pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
8176         pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
8177                 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
8178                 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
8179         pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
8180                 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
8181                 pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior);
8182                 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
8183         pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
8184                 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
8185         pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
8186                 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
8187         pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
8188                 pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
8189         pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
8190
8191         mGlobalKeyManager.dump(prefix, pw);
8192         mStatusBarController.dump(pw, prefix);
8193         mNavigationBarController.dump(pw, prefix);
8194         PolicyControl.dump(prefix, pw);
8195
8196         if (mWakeGestureListener != null) {
8197             mWakeGestureListener.dump(pw, prefix);
8198         }
8199         if (mOrientationListener != null) {
8200             mOrientationListener.dump(pw, prefix);
8201         }
8202         if (mBurnInProtectionHelper != null) {
8203             mBurnInProtectionHelper.dump(prefix, pw);
8204         }
8205         if (mKeyguardDelegate != null) {
8206             mKeyguardDelegate.dump(prefix, pw);
8207         }
8208     }
8209 }