OSDN Git Service

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