OSDN Git Service

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