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