2 * Copyright (C) 2006 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.server.policy;
19 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
20 import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
21 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
22 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
23 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
24 import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
25 import static android.app.AppOpsManager.OP_TOAST_WINDOW;
26 import static android.content.Context.DISPLAY_SERVICE;
27 import static android.content.Context.WINDOW_SERVICE;
28 import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
29 import static android.content.pm.PackageManager.FEATURE_LEANBACK;
30 import static android.content.pm.PackageManager.FEATURE_WATCH;
31 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
32 import static android.content.res.Configuration.EMPTY;
33 import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
34 import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
35 import static android.os.Build.VERSION_CODES.M;
36 import static android.os.Build.VERSION_CODES.O;
37 import static android.view.WindowManager.DOCKED_LEFT;
38 import static android.view.WindowManager.DOCKED_RIGHT;
39 import static android.view.WindowManager.DOCKED_TOP;
40 import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
41 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
42 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
43 import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
44 import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
45 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
46 import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
47 import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
48 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR;
49 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
50 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN;
51 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
52 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
53 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
54 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
55 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
56 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
57 import static android.view.WindowManager.LayoutParams.LAST_SYSTEM_WINDOW;
58 import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
59 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
60 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
61 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
62 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
63 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TASK_SNAPSHOT;
64 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
65 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
66 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
67 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
68 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
69 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
70 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
71 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
72 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
73 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
74 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
75 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
76 import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
77 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
78 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
79 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
80 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
81 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
82 import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
83 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
84 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
85 import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
86 import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
87 import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
88 import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
89 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
90 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
91 import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
92 import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR;
93 import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
94 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
95 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
96 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
97 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
98 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
99 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
100 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
101 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
102 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
103 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING;
104 import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
105 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
106 import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
107 import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
108 import static android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION;
109 import static android.view.WindowManagerGlobal.ADD_OKAY;
110 import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED;
111 import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
112 import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
113 import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
114 import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
115 import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
116 import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
118 import android.annotation.Nullable;
119 import android.app.ActivityManager;
120 import android.app.ActivityManager.StackId;
121 import android.app.ActivityManagerInternal;
122 import android.app.ActivityManagerInternal.SleepToken;
123 import android.app.AppOpsManager;
124 import android.app.IUiModeManager;
125 import android.app.ProgressDialog;
126 import android.app.SearchManager;
127 import android.app.StatusBarManager;
128 import android.app.UiModeManager;
129 import android.content.ActivityNotFoundException;
130 import android.content.BroadcastReceiver;
131 import android.content.ComponentName;
132 import android.content.ContentResolver;
133 import android.content.Context;
134 import android.content.Intent;
135 import android.content.IntentFilter;
136 import android.content.ServiceConnection;
137 import android.content.pm.ActivityInfo;
138 import android.content.pm.ApplicationInfo;
139 import android.content.pm.PackageManager;
140 import android.content.pm.ResolveInfo;
141 import android.content.res.CompatibilityInfo;
142 import android.content.res.Configuration;
143 import android.content.res.Resources;
144 import android.content.res.TypedArray;
145 import android.database.ContentObserver;
146 import android.graphics.PixelFormat;
147 import android.graphics.Rect;
148 import android.hardware.display.DisplayManager;
149 import android.hardware.hdmi.HdmiControlManager;
150 import android.hardware.hdmi.HdmiPlaybackClient;
151 import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback;
152 import android.hardware.input.InputManager;
153 import android.hardware.input.InputManagerInternal;
154 import android.hardware.power.V1_0.PowerHint;
155 import android.media.AudioAttributes;
156 import android.media.AudioManager;
157 import android.media.AudioSystem;
158 import android.media.IAudioService;
159 import android.media.session.MediaSessionLegacyHelper;
160 import android.os.Binder;
161 import android.os.Build;
162 import android.os.Bundle;
163 import android.os.FactoryTest;
164 import android.os.Handler;
165 import android.os.IBinder;
166 import android.os.IDeviceIdleController;
167 import android.os.Looper;
168 import android.os.Message;
169 import android.os.Messenger;
170 import android.os.PowerManager;
171 import android.os.PowerManagerInternal;
172 import android.os.Process;
173 import android.os.RemoteException;
174 import android.os.ServiceManager;
175 import android.os.SystemClock;
176 import android.os.SystemProperties;
177 import android.os.UEventObserver;
178 import android.os.UserHandle;
179 import android.os.Vibrator;
180 import android.provider.MediaStore;
181 import android.provider.Settings;
182 import android.service.dreams.DreamManagerInternal;
183 import android.service.dreams.DreamService;
184 import android.service.dreams.IDreamManager;
185 import android.speech.RecognizerIntent;
186 import android.telecom.TelecomManager;
187 import android.util.DisplayMetrics;
188 import android.util.EventLog;
189 import android.util.Log;
190 import android.util.LongSparseArray;
191 import android.util.MutableBoolean;
192 import android.util.Slog;
193 import android.util.SparseArray;
194 import android.view.Display;
195 import android.view.Gravity;
196 import android.view.HapticFeedbackConstants;
197 import android.view.IApplicationToken;
198 import android.view.IWindowManager;
199 import android.view.InputChannel;
200 import android.view.InputDevice;
201 import android.view.InputEvent;
202 import android.view.InputEventReceiver;
203 import android.view.KeyCharacterMap;
204 import android.view.KeyCharacterMap.FallbackAction;
205 import android.view.KeyEvent;
206 import android.view.MotionEvent;
207 import android.view.PointerIcon;
208 import android.view.Surface;
209 import android.view.View;
210 import android.view.ViewConfiguration;
211 import android.view.WindowManager;
212 import android.view.WindowManager.LayoutParams;
213 import android.view.WindowManagerGlobal;
214 import android.view.WindowManagerInternal;
215 import android.view.WindowManagerInternal.AppTransitionListener;
216 import android.view.WindowManagerPolicy;
217 import android.view.accessibility.AccessibilityEvent;
218 import android.view.accessibility.AccessibilityManager;
219 import android.view.animation.Animation;
220 import android.view.animation.AnimationSet;
221 import android.view.animation.AnimationUtils;
223 import com.android.internal.R;
224 import com.android.internal.logging.MetricsLogger;
225 import com.android.internal.policy.IKeyguardDismissCallback;
226 import com.android.internal.policy.IShortcutService;
227 import com.android.internal.policy.PhoneWindow;
228 import com.android.internal.statusbar.IStatusBarService;
229 import com.android.internal.util.ScreenShapeHelper;
230 import com.android.internal.widget.PointerLocationView;
231 import com.android.server.GestureLauncherService;
232 import com.android.server.LocalServices;
233 import com.android.server.policy.keyguard.KeyguardServiceDelegate;
234 import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener;
235 import com.android.server.policy.keyguard.KeyguardStateMonitor.StateCallback;
236 import com.android.server.statusbar.StatusBarManagerInternal;
237 import com.android.server.wm.AppTransition;
238 import com.android.server.vr.VrManagerInternal;
239 import com.android.server.vr.PersistentVrStateListener;
242 import java.io.FileReader;
243 import java.io.IOException;
244 import java.io.PrintWriter;
245 import java.util.List;
248 * WindowManagerPolicy implementation for the Android phone UI. This
249 * introduces a new method suffix, Lp, for an internal lock of the
250 * PhoneWindowManager. This is used to protect some internal state, and
251 * can be acquired with either the Lw and Li lock held, so has the restrictions
252 * of both of those when held.
254 public class PhoneWindowManager implements WindowManagerPolicy {
255 static final String TAG = "WindowManager";
256 static final boolean DEBUG = false;
257 static final boolean localLOGV = false;
258 static final boolean DEBUG_INPUT = false;
259 static final boolean DEBUG_KEYGUARD = false;
260 static final boolean DEBUG_LAYOUT = false;
261 static final boolean DEBUG_SPLASH_SCREEN = false;
262 static final boolean DEBUG_WAKEUP = false;
263 static final boolean SHOW_SPLASH_SCREENS = true;
265 // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
266 // No longer recommended for desk docks;
267 static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
269 // Whether to allow devices placed in vr headset viewers to have an alternative Home intent.
270 static final boolean ENABLE_VR_HEADSET_HOME_CAPTURE = true;
272 static final boolean ALTERNATE_CAR_MODE_NAV_SIZE = false;
274 static final int SHORT_PRESS_POWER_NOTHING = 0;
275 static final int SHORT_PRESS_POWER_GO_TO_SLEEP = 1;
276 static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2;
277 static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3;
278 static final int SHORT_PRESS_POWER_GO_HOME = 4;
280 static final int LONG_PRESS_POWER_NOTHING = 0;
281 static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
282 static final int LONG_PRESS_POWER_SHUT_OFF = 2;
283 static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
285 static final int LONG_PRESS_BACK_NOTHING = 0;
286 static final int LONG_PRESS_BACK_GO_TO_VOICE_ASSIST = 1;
288 static final int MULTI_PRESS_POWER_NOTHING = 0;
289 static final int MULTI_PRESS_POWER_THEATER_MODE = 1;
290 static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2;
292 // Number of presses needed before we induce panic press behavior on the back button
293 static final int PANIC_PRESS_BACK_COUNT = 4;
294 static final int PANIC_PRESS_BACK_NOTHING = 0;
295 static final int PANIC_PRESS_BACK_HOME = 1;
297 // These need to match the documentation/constant in
298 // core/res/res/values/config.xml
299 static final int LONG_PRESS_HOME_NOTHING = 0;
300 static final int LONG_PRESS_HOME_RECENT_SYSTEM_UI = 1;
301 static final int LONG_PRESS_HOME_ASSIST = 2;
302 static final int LAST_LONG_PRESS_HOME_BEHAVIOR = LONG_PRESS_HOME_ASSIST;
304 static final int DOUBLE_TAP_HOME_NOTHING = 0;
305 static final int DOUBLE_TAP_HOME_RECENT_SYSTEM_UI = 1;
307 static final int SHORT_PRESS_WINDOW_NOTHING = 0;
308 static final int SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE = 1;
310 static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP = 0;
311 static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME = 1;
313 static final int PENDING_KEY_NULL = -1;
315 // Controls navigation bar opacity depending on which workspace stacks are currently
317 // Nav bar is always opaque when either the freeform stack or docked stack is visible.
318 static final int NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED = 0;
319 // Nav bar is always translucent when the freeform stack is visible, otherwise always opaque.
320 static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1;
322 static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
323 static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
324 static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
325 static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
326 static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";
329 * These are the system UI flags that, when changing, can cause the layout
330 * of the screen to change.
332 static final int SYSTEM_UI_CHANGING_LAYOUT =
333 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
334 | View.SYSTEM_UI_FLAG_FULLSCREEN
335 | View.STATUS_BAR_TRANSLUCENT
336 | View.NAVIGATION_BAR_TRANSLUCENT
337 | View.STATUS_BAR_TRANSPARENT
338 | View.NAVIGATION_BAR_TRANSPARENT;
340 private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
341 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
342 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
345 // The panic gesture may become active only after the keyguard is dismissed and the immersive
346 // app shows again. If that doesn't happen for 30s we drop the gesture.
347 private static final long PANIC_GESTURE_EXPIRATION = 30000;
349 private static final String SYSUI_PACKAGE = "com.android.systemui";
350 private static final String SYSUI_SCREENSHOT_SERVICE =
351 "com.android.systemui.screenshot.TakeScreenshotService";
352 private static final String SYSUI_SCREENSHOT_ERROR_RECEIVER =
353 "com.android.systemui.screenshot.ScreenshotServiceErrorReceiver";
355 private static final int NAV_BAR_BOTTOM = 0;
356 private static final int NAV_BAR_RIGHT = 1;
357 private static final int NAV_BAR_LEFT = 2;
362 private boolean mKeyguardDrawnOnce;
364 /* Table of Application Launch keys. Maps from key codes to intent categories.
366 * These are special keys that are used to launch particular kinds of applications,
367 * such as a web browser. HID defines nearly a hundred of them in the Consumer (0x0C)
368 * usage page. We don't support quite that many yet...
370 static SparseArray<String> sApplicationLaunchKeyCategories;
372 sApplicationLaunchKeyCategories = new SparseArray<String>();
373 sApplicationLaunchKeyCategories.append(
374 KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER);
375 sApplicationLaunchKeyCategories.append(
376 KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL);
377 sApplicationLaunchKeyCategories.append(
378 KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS);
379 sApplicationLaunchKeyCategories.append(
380 KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR);
381 sApplicationLaunchKeyCategories.append(
382 KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC);
383 sApplicationLaunchKeyCategories.append(
384 KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
387 /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
388 static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;
390 /** Amount of time (in milliseconds) a toast window can be shown. */
391 public static final int TOAST_WINDOW_TIMEOUT = 3500; // 3.5 seconds
394 * Lock protecting internal state. Must not call out into window
395 * manager with lock held. (This lock will be acquired in places
396 * where the window manager is calling in with its own lock held.)
398 private final Object mLock = new Object();
401 IWindowManager mWindowManager;
402 WindowManagerFuncs mWindowManagerFuncs;
403 WindowManagerInternal mWindowManagerInternal;
404 PowerManager mPowerManager;
405 ActivityManagerInternal mActivityManagerInternal;
406 InputManagerInternal mInputManagerInternal;
407 DreamManagerInternal mDreamManagerInternal;
408 PowerManagerInternal mPowerManagerInternal;
409 IStatusBarService mStatusBarService;
410 StatusBarManagerInternal mStatusBarManagerInternal;
411 boolean mPreloadedRecentApps;
412 final Object mServiceAquireLock = new Object();
413 Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
414 SearchManager mSearchManager;
415 AccessibilityManager mAccessibilityManager;
416 BurnInProtectionHelper mBurnInProtectionHelper;
417 AppOpsManager mAppOpsManager;
418 private boolean mHasFeatureWatch;
419 private boolean mHasFeatureLeanback;
421 // Assigned on main thread, accessed on UI thread
422 volatile VrManagerInternal mVrManagerInternal;
424 // Vibrator pattern for haptic feedback of a long press.
425 long[] mLongPressVibePattern;
427 // Vibrator pattern for haptic feedback of virtual key press.
428 long[] mVirtualKeyVibePattern;
430 // Vibrator pattern for a short vibration.
431 long[] mKeyboardTapVibePattern;
433 // Vibrator pattern for a short vibration when tapping on an hour/minute tick of a Clock.
434 long[] mClockTickVibePattern;
436 // Vibrator pattern for a short vibration when tapping on a day/month/year date of a Calendar.
437 long[] mCalendarDateVibePattern;
439 // Vibrator pattern for haptic feedback during boot when safe mode is disabled.
440 long[] mSafeModeDisabledVibePattern;
442 // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
443 long[] mSafeModeEnabledVibePattern;
445 // Vibrator pattern for haptic feedback of a context click.
446 long[] mContextClickVibePattern;
448 /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
449 boolean mEnableShiftMenuBugReports = false;
451 /** Controller that supports enabling an AccessibilityService by holding down the volume keys */
452 private AccessibilityShortcutController mAccessibilityShortcutController;
455 WindowState mStatusBar = null;
456 int mStatusBarHeight;
457 WindowState mNavigationBar = null;
458 boolean mHasNavigationBar = false;
459 boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?
460 int mNavigationBarPosition = NAV_BAR_BOTTOM;
461 int[] mNavigationBarHeightForRotationDefault = new int[4];
462 int[] mNavigationBarWidthForRotationDefault = new int[4];
463 int[] mNavigationBarHeightForRotationInCarMode = new int[4];
464 int[] mNavigationBarWidthForRotationInCarMode = new int[4];
466 private LongSparseArray<IShortcutService> mShortcutKeyServices = new LongSparseArray<>();
468 // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
469 // This is for car dock and this is updated from resource.
470 private boolean mEnableCarDockHomeCapture = true;
472 boolean mBootMessageNeedsHiding;
473 KeyguardServiceDelegate mKeyguardDelegate;
474 final Runnable mWindowManagerDrawCallback = new Runnable() {
477 if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!");
478 mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);
481 final DrawnListener mKeyguardDrawnCallback = new DrawnListener() {
483 public void onDrawn() {
484 if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn.");
485 mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
489 GlobalActions mGlobalActions;
491 WindowState mLastInputMethodWindow = null;
492 WindowState mLastInputMethodTargetWindow = null;
494 // FIXME This state is shared between the input reader and handler thread.
495 // Technically it's broken and buggy but it has been like this for many years
496 // and we have not yet seen any problems. Someday we'll rewrite this logic
497 // so that only one thread is involved in handling input policy. Unfortunately
498 // it's on a critical path for power management so we can't just post the work to the
499 // handler thread. We'll need to resolve this someday by teaching the input dispatcher
500 // to hold wakelocks during dispatch and eliminating the critical path.
501 volatile boolean mPowerKeyHandled;
502 volatile boolean mBackKeyHandled;
503 volatile boolean mBeganFromNonInteractive;
504 volatile int mPowerKeyPressCounter;
505 volatile int mBackKeyPressCounter;
506 volatile boolean mEndCallKeyHandled;
507 volatile boolean mCameraGestureTriggeredDuringGoingToSleep;
508 volatile boolean mGoingToSleep;
509 volatile boolean mRecentsVisible;
510 volatile boolean mTvPictureInPictureVisible;
511 // Written by vr manager thread, only read in this class
512 volatile boolean mPersistentVrModeEnabled;
514 // Used to hold the last user key used to wake the device. This helps us prevent up events
515 // from being passed to the foregrounded app without a corresponding down event
516 volatile int mPendingWakeKey = PENDING_KEY_NULL;
518 int mRecentAppsHeldModifiers;
519 boolean mLanguageSwitchKeyPressed;
521 int mLidState = LID_ABSENT;
522 int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT;
523 boolean mHaveBuiltInKeyboard;
525 boolean mSystemReady;
526 boolean mSystemBooted;
527 private boolean mDeferBindKeyguard;
528 boolean mHdmiPlugged;
529 HdmiControl mHdmiControl;
530 IUiModeManager mUiModeManager;
532 int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
533 int mLidOpenRotation;
534 int mCarDockRotation;
535 int mDeskDockRotation;
536 int mUndockedHdmiRotation;
537 int mDemoHdmiRotation;
538 boolean mDemoHdmiRotationLock;
540 boolean mDemoRotationLock;
542 boolean mWakeGestureEnabledSetting;
543 MyWakeGestureListener mWakeGestureListener;
545 // Default display does not rotate, apps that require non-default orientation will have to
546 // have the orientation emulated.
547 private boolean mForceDefaultOrientation = false;
549 int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
550 int mUserRotation = Surface.ROTATION_0;
551 boolean mAccelerometerDefault;
553 boolean mSupportAutoRotation;
554 int mAllowAllRotations = -1;
555 boolean mCarDockEnablesAccelerometer;
556 boolean mDeskDockEnablesAccelerometer;
557 int mLidKeyboardAccessibility;
558 int mLidNavigationAccessibility;
559 boolean mLidControlsScreenLock;
560 boolean mLidControlsSleep;
561 int mShortPressOnPowerBehavior;
562 int mLongPressOnPowerBehavior;
563 int mDoublePressOnPowerBehavior;
564 int mTriplePressOnPowerBehavior;
565 int mLongPressOnBackBehavior;
566 int mPanicPressOnBackBehavior;
567 int mShortPressOnSleepBehavior;
568 int mShortPressWindowBehavior;
570 boolean mScreenOnEarly;
571 boolean mScreenOnFully;
572 ScreenOnListener mScreenOnListener;
573 boolean mKeyguardDrawComplete;
574 boolean mWindowManagerDrawComplete;
575 boolean mOrientationSensorEnabled = false;
576 int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
577 boolean mHasSoftInput = false;
578 boolean mTranslucentDecorEnabled = true;
579 boolean mUseTvRouting;
581 int mPointerLocationMode = 0; // guarded by mLock
583 // The last window we were told about in focusChanged.
584 WindowState mFocusedWindow;
585 IApplicationToken mFocusedApp;
587 PointerLocationView mPointerLocationView;
589 // The current size of the screen; really; extends into the overscan area of
590 // the screen and doesn't account for any system elements like the status bar.
591 int mOverscanScreenLeft, mOverscanScreenTop;
592 int mOverscanScreenWidth, mOverscanScreenHeight;
593 // The current visible size of the screen; really; (ir)regardless of whether the status
594 // bar can be hidden but not extending into the overscan area.
595 int mUnrestrictedScreenLeft, mUnrestrictedScreenTop;
596 int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight;
597 // Like mOverscanScreen*, but allowed to move into the overscan region where appropriate.
598 int mRestrictedOverscanScreenLeft, mRestrictedOverscanScreenTop;
599 int mRestrictedOverscanScreenWidth, mRestrictedOverscanScreenHeight;
600 // The current size of the screen; these may be different than (0,0)-(dw,dh)
601 // if the status bar can't be hidden; in that case it effectively carves out
602 // that area of the display from all other windows.
603 int mRestrictedScreenLeft, mRestrictedScreenTop;
604 int mRestrictedScreenWidth, mRestrictedScreenHeight;
605 // During layout, the current screen borders accounting for any currently
606 // visible system UI elements.
607 int mSystemLeft, mSystemTop, mSystemRight, mSystemBottom;
608 // For applications requesting stable content insets, these are them.
609 int mStableLeft, mStableTop, mStableRight, mStableBottom;
610 // For applications requesting stable content insets but have also set the
611 // fullscreen window flag, these are the stable dimensions without the status bar.
612 int mStableFullscreenLeft, mStableFullscreenTop;
613 int mStableFullscreenRight, mStableFullscreenBottom;
614 // During layout, the current screen borders with all outer decoration
615 // (status bar, input method dock) accounted for.
616 int mCurLeft, mCurTop, mCurRight, mCurBottom;
617 // During layout, the frame in which content should be displayed
618 // to the user, accounting for all screen decoration except for any
619 // space they deem as available for other content. This is usually
620 // the same as mCur*, but may be larger if the screen decor has supplied
622 int mContentLeft, mContentTop, mContentRight, mContentBottom;
623 // During layout, the frame in which voice content should be displayed
624 // to the user, accounting for all screen decoration except for any
625 // space they deem as available for other content.
626 int mVoiceContentLeft, mVoiceContentTop, mVoiceContentRight, mVoiceContentBottom;
627 // During layout, the current screen borders along which input method
628 // windows are placed.
629 int mDockLeft, mDockTop, mDockRight, mDockBottom;
630 // During layout, the layer at which the doc window is placed.
632 // During layout, this is the layer of the status bar.
634 int mLastSystemUiFlags;
635 // Bits that we are in the process of clearing, so we want to prevent
636 // them from being set by applications until everything has been updated
637 // to have them clear.
638 int mResettingSystemUiFlags = 0;
639 // Bits that we are currently always keeping cleared.
640 int mForceClearedSystemUiFlags = 0;
641 int mLastFullscreenStackSysUiFlags;
642 int mLastDockedStackSysUiFlags;
643 final Rect mNonDockedStackBounds = new Rect();
644 final Rect mDockedStackBounds = new Rect();
645 final Rect mLastNonDockedStackBounds = new Rect();
646 final Rect mLastDockedStackBounds = new Rect();
648 // What we last reported to system UI about whether the compatibility
649 // menu needs to be displayed.
650 boolean mLastFocusNeedsMenu = false;
651 // If nonzero, a panic gesture was performed at that time in uptime millis and is still pending.
652 private long mPendingPanicGestureUptime;
654 InputConsumer mInputConsumer = null;
656 static final Rect mTmpParentFrame = new Rect();
657 static final Rect mTmpDisplayFrame = new Rect();
658 static final Rect mTmpOverscanFrame = new Rect();
659 static final Rect mTmpContentFrame = new Rect();
660 static final Rect mTmpVisibleFrame = new Rect();
661 static final Rect mTmpDecorFrame = new Rect();
662 static final Rect mTmpStableFrame = new Rect();
663 static final Rect mTmpNavigationFrame = new Rect();
664 static final Rect mTmpOutsetFrame = new Rect();
665 private static final Rect mTmpRect = new Rect();
667 WindowState mTopFullscreenOpaqueWindowState;
668 WindowState mTopFullscreenOpaqueOrDimmingWindowState;
669 WindowState mTopDockedOpaqueWindowState;
670 WindowState mTopDockedOpaqueOrDimmingWindowState;
671 boolean mTopIsFullscreen;
672 boolean mForceStatusBar;
673 boolean mForceStatusBarFromKeyguard;
674 private boolean mForceStatusBarTransparent;
675 int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
676 boolean mForcingShowNavBar;
677 int mForcingShowNavBarLayer;
679 private boolean mPendingKeyguardOccluded;
680 private boolean mKeyguardOccludedChanged;
682 boolean mShowingDream;
683 private boolean mLastShowingDream;
684 boolean mDreamingLockscreen;
685 boolean mDreamingSleepTokenNeeded;
686 SleepToken mDreamingSleepToken;
687 SleepToken mScreenOffSleepToken;
688 volatile boolean mKeyguardOccluded;
689 boolean mHomePressed;
690 boolean mHomeConsumed;
691 boolean mHomeDoubleTapPending;
693 Intent mCarDockIntent;
694 Intent mDeskDockIntent;
695 Intent mVrHeadsetHomeIntent;
696 boolean mSearchKeyShortcutPending;
697 boolean mConsumeSearchKeyUp;
698 boolean mAssistKeyLongPressed;
699 boolean mPendingMetaAction;
700 boolean mPendingCapsLockToggle;
702 int mInitialMetaState;
703 boolean mForceShowSystemBars;
705 // support for activating the lock screen while the screen is on
706 boolean mAllowLockscreenWhenOn;
707 int mLockScreenTimeout;
708 boolean mLockScreenTimerActive;
710 // Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.)
711 int mEndcallBehavior;
713 // Behavior of POWER button while in-call and screen on.
714 // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
715 int mIncallPowerBehavior;
717 // Behavior of Back button while in-call and screen on
718 int mIncallBackBehavior;
722 private int mDisplayRotation;
724 int mLandscapeRotation = 0; // default landscape rotation
725 int mSeascapeRotation = 0; // "other" landscape rotation, 180 degrees from mLandscapeRotation
726 int mPortraitRotation = 0; // default portrait rotation
727 int mUpsideDownRotation = 0; // "other" portrait rotation
729 int mOverscanLeft = 0;
730 int mOverscanTop = 0;
731 int mOverscanRight = 0;
732 int mOverscanBottom = 0;
734 // What we do when the user long presses on home
735 private int mLongPressOnHomeBehavior;
737 // What we do when the user double-taps on home
738 private int mDoubleTapOnHomeBehavior;
740 // Allowed theater mode wake actions
741 private boolean mAllowTheaterModeWakeFromKey;
742 private boolean mAllowTheaterModeWakeFromPowerKey;
743 private boolean mAllowTheaterModeWakeFromMotion;
744 private boolean mAllowTheaterModeWakeFromMotionWhenNotDreaming;
745 private boolean mAllowTheaterModeWakeFromCameraLens;
746 private boolean mAllowTheaterModeWakeFromLidSwitch;
747 private boolean mAllowTheaterModeWakeFromWakeGesture;
749 // Whether to support long press from power button in non-interactive mode
750 private boolean mSupportLongPressPowerWhenNonInteractive;
752 // Whether to go to sleep entering theater mode from power button
753 private boolean mGoToSleepOnButtonPressTheaterMode;
755 // Screenshot trigger states
756 // Time to volume and power must be pressed within this interval of each other.
757 private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
758 // Increase the chord delay when taking a screenshot from the keyguard
759 private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f;
760 private boolean mScreenshotChordEnabled;
761 private boolean mScreenshotChordVolumeDownKeyTriggered;
762 private long mScreenshotChordVolumeDownKeyTime;
763 private boolean mScreenshotChordVolumeDownKeyConsumed;
764 private boolean mA11yShortcutChordVolumeUpKeyTriggered;
765 private long mA11yShortcutChordVolumeUpKeyTime;
766 private boolean mA11yShortcutChordVolumeUpKeyConsumed;
768 private boolean mScreenshotChordPowerKeyTriggered;
769 private long mScreenshotChordPowerKeyTime;
771 private static final long BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS = 1000;
773 private boolean mBugreportTvKey1Pressed;
774 private boolean mBugreportTvKey2Pressed;
775 private boolean mBugreportTvScheduled;
777 /* The number of steps between min and max brightness */
778 private static final int BRIGHTNESS_STEPS = 10;
780 SettingsObserver mSettingsObserver;
781 ShortcutManager mShortcutManager;
782 PowerManager.WakeLock mBroadcastWakeLock;
783 PowerManager.WakeLock mPowerKeyWakeLock;
784 boolean mHavePendingMediaKeyRepeatWithWakeLock;
786 private int mCurrentUserId;
788 // Maps global key codes to the components that will handle them.
789 private GlobalKeyManager mGlobalKeyManager;
791 // Fallback actions by key code.
792 private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions =
793 new SparseArray<KeyCharacterMap.FallbackAction>();
795 private final LogDecelerateInterpolator mLogDecelerateInterpolator
796 = new LogDecelerateInterpolator(100, 0);
798 private final MutableBoolean mTmpBoolean = new MutableBoolean(false);
800 private static final int MSG_ENABLE_POINTER_LOCATION = 1;
801 private static final int MSG_DISABLE_POINTER_LOCATION = 2;
802 private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
803 private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
804 private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
805 private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6;
806 private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7;
807 private static final int MSG_DISPATCH_SHOW_RECENTS = 9;
808 private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10;
809 private static final int MSG_HIDE_BOOT_MESSAGE = 11;
810 private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12;
811 private static final int MSG_POWER_DELAYED_PRESS = 13;
812 private static final int MSG_POWER_LONG_PRESS = 14;
813 private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 15;
814 private static final int MSG_REQUEST_TRANSIENT_BARS = 16;
815 private static final int MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU = 17;
816 private static final int MSG_BACK_LONG_PRESS = 18;
817 private static final int MSG_DISPOSE_INPUT_CONSUMER = 19;
818 private static final int MSG_BACK_DELAYED_PRESS = 20;
819 private static final int MSG_ACCESSIBILITY_SHORTCUT = 21;
820 private static final int MSG_BUGREPORT_TV = 22;
822 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
823 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
825 private class PolicyHandler extends Handler {
827 public void handleMessage(Message msg) {
829 case MSG_ENABLE_POINTER_LOCATION:
830 enablePointerLocation();
832 case MSG_DISABLE_POINTER_LOCATION:
833 disablePointerLocation();
835 case MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK:
836 dispatchMediaKeyWithWakeLock((KeyEvent)msg.obj);
838 case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK:
839 dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj);
841 case MSG_DISPATCH_SHOW_RECENTS:
842 showRecentApps(false, msg.arg1 != 0);
844 case MSG_DISPATCH_SHOW_GLOBAL_ACTIONS:
845 showGlobalActionsInternal();
847 case MSG_KEYGUARD_DRAWN_COMPLETE:
848 if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete");
849 finishKeyguardDrawn();
851 case MSG_KEYGUARD_DRAWN_TIMEOUT:
852 Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete");
853 finishKeyguardDrawn();
855 case MSG_WINDOW_MANAGER_DRAWN_COMPLETE:
856 if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete");
857 finishWindowsDrawn();
859 case MSG_HIDE_BOOT_MESSAGE:
860 handleHideBootMessage();
862 case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK:
863 launchVoiceAssistWithWakeLock(msg.arg1 != 0);
865 case MSG_POWER_DELAYED_PRESS:
866 powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2);
867 finishPowerKeyPress();
869 case MSG_POWER_LONG_PRESS:
872 case MSG_UPDATE_DREAMING_SLEEP_TOKEN:
873 updateDreamingSleepToken(msg.arg1 != 0);
875 case MSG_REQUEST_TRANSIENT_BARS:
876 WindowState targetBar = (msg.arg1 == MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS) ?
877 mStatusBar : mNavigationBar;
878 if (targetBar != null) {
879 requestTransientBars(targetBar);
882 case MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU:
883 showTvPictureInPictureMenuInternal();
885 case MSG_BACK_LONG_PRESS:
887 finishBackKeyPress();
889 case MSG_DISPOSE_INPUT_CONSUMER:
890 disposeInputConsumer((InputConsumer) msg.obj);
892 case MSG_BACK_DELAYED_PRESS:
893 backMultiPressAction((Long) msg.obj, msg.arg1);
894 finishBackKeyPress();
896 case MSG_ACCESSIBILITY_SHORTCUT:
897 accessibilityShortcutActivated();
899 case MSG_BUGREPORT_TV:
906 private UEventObserver mHDMIObserver = new UEventObserver() {
908 public void onUEvent(UEventObserver.UEvent event) {
909 setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
913 class SettingsObserver extends ContentObserver {
914 SettingsObserver(Handler handler) {
919 // Observe all users' changes
920 ContentResolver resolver = mContext.getContentResolver();
921 resolver.registerContentObserver(Settings.System.getUriFor(
922 Settings.System.END_BUTTON_BEHAVIOR), false, this,
923 UserHandle.USER_ALL);
924 resolver.registerContentObserver(Settings.Secure.getUriFor(
925 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this,
926 UserHandle.USER_ALL);
927 resolver.registerContentObserver(Settings.Secure.getUriFor(
928 Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR), false, this,
929 UserHandle.USER_ALL);
930 resolver.registerContentObserver(Settings.Secure.getUriFor(
931 Settings.Secure.WAKE_GESTURE_ENABLED), false, this,
932 UserHandle.USER_ALL);
933 resolver.registerContentObserver(Settings.System.getUriFor(
934 Settings.System.ACCELEROMETER_ROTATION), false, this,
935 UserHandle.USER_ALL);
936 resolver.registerContentObserver(Settings.System.getUriFor(
937 Settings.System.USER_ROTATION), false, this,
938 UserHandle.USER_ALL);
939 resolver.registerContentObserver(Settings.System.getUriFor(
940 Settings.System.SCREEN_OFF_TIMEOUT), false, this,
941 UserHandle.USER_ALL);
942 resolver.registerContentObserver(Settings.System.getUriFor(
943 Settings.System.POINTER_LOCATION), false, this,
944 UserHandle.USER_ALL);
945 resolver.registerContentObserver(Settings.Secure.getUriFor(
946 Settings.Secure.DEFAULT_INPUT_METHOD), false, this,
947 UserHandle.USER_ALL);
948 resolver.registerContentObserver(Settings.Secure.getUriFor(
949 Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this,
950 UserHandle.USER_ALL);
951 resolver.registerContentObserver(Settings.Global.getUriFor(
952 Settings.Global.POLICY_CONTROL), false, this,
953 UserHandle.USER_ALL);
957 @Override public void onChange(boolean selfChange) {
959 updateRotation(false);
963 class MyWakeGestureListener extends WakeGestureListener {
964 MyWakeGestureListener(Context context, Handler handler) {
965 super(context, handler);
969 public void onWakeUp() {
970 synchronized (mLock) {
971 if (shouldEnableWakeGestureLp()) {
972 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
973 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture,
974 "android.policy:GESTURE");
980 class MyOrientationListener extends WindowOrientationListener {
981 private final Runnable mUpdateRotationRunnable = new Runnable() {
984 // send interaction hint to improve redraw performance
985 mPowerManagerInternal.powerHint(PowerHint.INTERACTION, 0);
986 updateRotation(false);
990 MyOrientationListener(Context context, Handler handler) {
991 super(context, handler);
995 public void onProposedRotationChanged(int rotation) {
996 if (localLOGV) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
997 mHandler.post(mUpdateRotationRunnable);
1000 MyOrientationListener mOrientationListener;
1002 final PersistentVrStateListener mPersistentVrModeListener =
1003 new PersistentVrStateListener() {
1005 public void onPersistentVrStateChanged(boolean enabled) {
1006 mPersistentVrModeEnabled = enabled;
1010 private final StatusBarController mStatusBarController = new StatusBarController();
1012 private final BarController mNavigationBarController = new BarController("NavigationBar",
1013 View.NAVIGATION_BAR_TRANSIENT,
1014 View.NAVIGATION_BAR_UNHIDE,
1015 View.NAVIGATION_BAR_TRANSLUCENT,
1016 StatusBarManager.WINDOW_NAVIGATION_BAR,
1017 WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
1018 View.NAVIGATION_BAR_TRANSPARENT);
1020 private final BarController.OnBarVisibilityChangedListener mNavBarVisibilityListener =
1021 new BarController.OnBarVisibilityChangedListener() {
1023 public void onBarVisibilityChanged(boolean visible) {
1024 mAccessibilityManager.notifyAccessibilityButtonAvailabilityChanged(visible);
1028 private ImmersiveModeConfirmation mImmersiveModeConfirmation;
1030 private SystemGesturesPointerEventListener mSystemGestures;
1032 IStatusBarService getStatusBarService() {
1033 synchronized (mServiceAquireLock) {
1034 if (mStatusBarService == null) {
1035 mStatusBarService = IStatusBarService.Stub.asInterface(
1036 ServiceManager.getService("statusbar"));
1038 return mStatusBarService;
1042 StatusBarManagerInternal getStatusBarManagerInternal() {
1043 synchronized (mServiceAquireLock) {
1044 if (mStatusBarManagerInternal == null) {
1045 mStatusBarManagerInternal =
1046 LocalServices.getService(StatusBarManagerInternal.class);
1048 return mStatusBarManagerInternal;
1053 * We always let the sensor be switched on by default except when
1054 * the user has explicitly disabled sensor based rotation or when the
1055 * screen is switched off.
1057 boolean needSensorRunningLp() {
1058 if (mSupportAutoRotation) {
1059 if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
1060 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
1061 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
1062 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
1063 // If the application has explicitly requested to follow the
1064 // orientation, then we need to turn the sensor on.
1068 if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
1069 (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
1070 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
1071 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
1072 // enable accelerometer if we are docked in a dock that enables accelerometer
1073 // orientation management,
1076 if (mUserRotationMode == USER_ROTATION_LOCKED) {
1077 // If the setting for using the sensor by default is enabled, then
1078 // we will always leave it on. Note that the user could go to
1079 // a window that forces an orientation that does not use the
1080 // sensor and in theory we could turn it off... however, when next
1081 // turning it on we won't have a good value for the current
1082 // orientation for a little bit, which can cause orientation
1083 // changes to lag, so we'd like to keep it always on. (It will
1084 // still be turned off when the screen is off.)
1087 return mSupportAutoRotation;
1091 * Various use cases for invoking this function
1092 * screen turning off, should always disable listeners if already enabled
1093 * screen turned on and current app has sensor based orientation, enable listeners
1094 * if not already enabled
1095 * screen turned on and current app does not have sensor orientation, disable listeners if
1097 * screen turning on and current app has sensor based orientation, enable listeners if needed
1098 * screen turning on and current app has nosensor based orientation, do nothing
1100 void updateOrientationListenerLp() {
1101 if (!mOrientationListener.canDetectOrientation()) {
1102 // If sensor is turned off or nonexistent for some reason
1105 // Could have been invoked due to screen turning on or off or
1106 // change of the currently visible window's orientation.
1107 if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly
1108 + ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation
1109 + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled
1110 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
1111 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
1112 boolean disable = true;
1113 // Note: We postpone the rotating of the screen until the keyguard as well as the
1114 // window manager have reported a draw complete.
1115 if (mScreenOnEarly && mAwake &&
1116 mKeyguardDrawComplete && mWindowManagerDrawComplete) {
1117 if (needSensorRunningLp()) {
1119 //enable listener if not already enabled
1120 if (!mOrientationSensorEnabled) {
1121 mOrientationListener.enable();
1122 if(localLOGV) Slog.v(TAG, "Enabling listeners");
1123 mOrientationSensorEnabled = true;
1127 //check if sensors need to be disabled
1128 if (disable && mOrientationSensorEnabled) {
1129 mOrientationListener.disable();
1130 if(localLOGV) Slog.v(TAG, "Disabling listeners");
1131 mOrientationSensorEnabled = false;
1135 private void interceptBackKeyDown() {
1136 MetricsLogger.count(mContext, "key_back_down", 1);
1137 // Reset back key state for long press
1138 mBackKeyHandled = false;
1140 // Cancel multi-press detection timeout.
1141 if (hasPanicPressOnBackBehavior()) {
1142 if (mBackKeyPressCounter != 0
1143 && mBackKeyPressCounter < PANIC_PRESS_BACK_COUNT) {
1144 mHandler.removeMessages(MSG_BACK_DELAYED_PRESS);
1148 if (hasLongPressOnBackBehavior()) {
1149 Message msg = mHandler.obtainMessage(MSG_BACK_LONG_PRESS);
1150 msg.setAsynchronous(true);
1151 mHandler.sendMessageDelayed(msg,
1152 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1156 // returns true if the key was handled and should not be passed to the user
1157 private boolean interceptBackKeyUp(KeyEvent event) {
1158 // Cache handled state
1159 boolean handled = mBackKeyHandled;
1161 if (hasPanicPressOnBackBehavior()) {
1162 // Check for back key panic press
1163 ++mBackKeyPressCounter;
1165 final long eventTime = event.getDownTime();
1167 if (mBackKeyPressCounter <= PANIC_PRESS_BACK_COUNT) {
1168 // This could be a multi-press. Wait a little bit longer to confirm.
1169 Message msg = mHandler.obtainMessage(MSG_BACK_DELAYED_PRESS,
1170 mBackKeyPressCounter, 0, eventTime);
1171 msg.setAsynchronous(true);
1172 mHandler.sendMessageDelayed(msg, ViewConfiguration.getMultiPressTimeout());
1176 // Reset back long press state
1177 cancelPendingBackKeyAction();
1179 if (mHasFeatureWatch) {
1180 TelecomManager telecomManager = getTelecommService();
1182 if (telecomManager != null) {
1183 if (telecomManager.isRinging()) {
1184 // Pressing back while there's a ringing incoming
1185 // call should silence the ringer.
1186 telecomManager.silenceRinger();
1188 // It should not prevent navigating away
1191 (mIncallBackBehavior & Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_HANGUP) != 0
1192 && telecomManager.isInCall()) {
1193 // Otherwise, if "Back button ends call" is enabled,
1194 // the Back button will hang up any current active call.
1195 return telecomManager.endCall();
1203 private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
1204 // Hold a wake lock until the power key is released.
1205 if (!mPowerKeyWakeLock.isHeld()) {
1206 mPowerKeyWakeLock.acquire();
1209 // Cancel multi-press detection timeout.
1210 if (mPowerKeyPressCounter != 0) {
1211 mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);
1214 // Detect user pressing the power button in panic when an application has
1215 // taken over the whole screen.
1216 boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
1217 SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags),
1218 isNavBarEmpty(mLastSystemUiFlags));
1220 mHandler.post(mHiddenNavPanic);
1223 // Latch power key state to detect screenshot chord.
1224 if (interactive && !mScreenshotChordPowerKeyTriggered
1225 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
1226 mScreenshotChordPowerKeyTriggered = true;
1227 mScreenshotChordPowerKeyTime = event.getDownTime();
1228 interceptScreenshotChord();
1231 // Stop ringing or end call if configured to do so when power is pressed.
1232 TelecomManager telecomManager = getTelecommService();
1233 boolean hungUp = false;
1234 if (telecomManager != null) {
1235 if (telecomManager.isRinging()) {
1236 // Pressing Power while there's a ringing incoming
1237 // call should silence the ringer.
1238 telecomManager.silenceRinger();
1239 } else if ((mIncallPowerBehavior
1240 & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
1241 && telecomManager.isInCall() && interactive) {
1242 // Otherwise, if "Power button ends call" is enabled,
1243 // the Power button will hang up any current active call.
1244 hungUp = telecomManager.endCall();
1248 GestureLauncherService gestureService = LocalServices.getService(
1249 GestureLauncherService.class);
1250 boolean gesturedServiceIntercepted = false;
1251 if (gestureService != null) {
1252 gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive,
1254 if (mTmpBoolean.value && mGoingToSleep) {
1255 mCameraGestureTriggeredDuringGoingToSleep = true;
1259 // If the power key has still not yet been handled, then detect short
1260 // press, long press, or multi press and decide what to do.
1261 mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
1262 || mA11yShortcutChordVolumeUpKeyTriggered || gesturedServiceIntercepted;
1263 if (!mPowerKeyHandled) {
1265 // When interactive, we're already awake.
1266 // Wait for a long press or for the button to be released to decide what to do.
1267 if (hasLongPressOnPowerBehavior()) {
1268 Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
1269 msg.setAsynchronous(true);
1270 mHandler.sendMessageDelayed(msg,
1271 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1274 wakeUpFromPowerKey(event.getDownTime());
1276 if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
1277 Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
1278 msg.setAsynchronous(true);
1279 mHandler.sendMessageDelayed(msg,
1280 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1281 mBeganFromNonInteractive = true;
1283 final int maxCount = getMaxMultiPressPowerCount();
1285 if (maxCount <= 1) {
1286 mPowerKeyHandled = true;
1288 mBeganFromNonInteractive = true;
1295 private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
1296 final boolean handled = canceled || mPowerKeyHandled;
1297 mScreenshotChordPowerKeyTriggered = false;
1298 cancelPendingScreenshotChordAction();
1299 cancelPendingPowerKeyAction();
1302 // Figure out how to handle the key now that it has been released.
1303 mPowerKeyPressCounter += 1;
1305 final int maxCount = getMaxMultiPressPowerCount();
1306 final long eventTime = event.getDownTime();
1307 if (mPowerKeyPressCounter < maxCount) {
1308 // This could be a multi-press. Wait a little bit longer to confirm.
1309 // Continue holding the wake lock.
1310 Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
1311 interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
1312 msg.setAsynchronous(true);
1313 mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
1317 // No other actions. Handle it immediately.
1318 powerPress(eventTime, interactive, mPowerKeyPressCounter);
1321 // Done. Reset our state.
1322 finishPowerKeyPress();
1325 private void finishPowerKeyPress() {
1326 mBeganFromNonInteractive = false;
1327 mPowerKeyPressCounter = 0;
1328 if (mPowerKeyWakeLock.isHeld()) {
1329 mPowerKeyWakeLock.release();
1333 private void finishBackKeyPress() {
1334 mBackKeyPressCounter = 0;
1337 private void cancelPendingPowerKeyAction() {
1338 if (!mPowerKeyHandled) {
1339 mPowerKeyHandled = true;
1340 mHandler.removeMessages(MSG_POWER_LONG_PRESS);
1344 private void cancelPendingBackKeyAction() {
1345 if (!mBackKeyHandled) {
1346 mBackKeyHandled = true;
1347 mHandler.removeMessages(MSG_BACK_LONG_PRESS);
1351 private void backMultiPressAction(long eventTime, int count) {
1352 if (count >= PANIC_PRESS_BACK_COUNT) {
1353 switch (mPanicPressOnBackBehavior) {
1354 case PANIC_PRESS_BACK_NOTHING:
1356 case PANIC_PRESS_BACK_HOME:
1357 launchHomeFromHotKey();
1363 private void powerPress(long eventTime, boolean interactive, int count) {
1364 if (mScreenOnEarly && !mScreenOnFully) {
1365 Slog.i(TAG, "Suppressed redundant power key press while "
1366 + "already in the process of turning the screen on.");
1371 powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
1372 } else if (count == 3) {
1373 powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
1374 } else if (interactive && !mBeganFromNonInteractive) {
1375 switch (mShortPressOnPowerBehavior) {
1376 case SHORT_PRESS_POWER_NOTHING:
1378 case SHORT_PRESS_POWER_GO_TO_SLEEP:
1379 mPowerManager.goToSleep(eventTime,
1380 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
1382 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
1383 mPowerManager.goToSleep(eventTime,
1384 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
1385 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
1387 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
1388 mPowerManager.goToSleep(eventTime,
1389 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
1390 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
1391 launchHomeFromHotKey();
1393 case SHORT_PRESS_POWER_GO_HOME:
1394 launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
1400 private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) {
1402 case MULTI_PRESS_POWER_NOTHING:
1404 case MULTI_PRESS_POWER_THEATER_MODE:
1405 if (!isUserSetupComplete()) {
1406 Slog.i(TAG, "Ignoring toggling theater mode - device not setup.");
1410 if (isTheaterModeEnabled()) {
1411 Slog.i(TAG, "Toggling theater mode off.");
1412 Settings.Global.putInt(mContext.getContentResolver(),
1413 Settings.Global.THEATER_MODE_ON, 0);
1415 wakeUpFromPowerKey(eventTime);
1418 Slog.i(TAG, "Toggling theater mode on.");
1419 Settings.Global.putInt(mContext.getContentResolver(),
1420 Settings.Global.THEATER_MODE_ON, 1);
1422 if (mGoToSleepOnButtonPressTheaterMode && interactive) {
1423 mPowerManager.goToSleep(eventTime,
1424 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
1428 case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
1429 Slog.i(TAG, "Starting brightness boost.");
1431 wakeUpFromPowerKey(eventTime);
1433 mPowerManager.boostScreenBrightness(eventTime);
1438 private int getMaxMultiPressPowerCount() {
1439 if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
1442 if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
1448 private void powerLongPress() {
1449 final int behavior = getResolvedLongPressOnPowerBehavior();
1451 case LONG_PRESS_POWER_NOTHING:
1453 case LONG_PRESS_POWER_GLOBAL_ACTIONS:
1454 mPowerKeyHandled = true;
1455 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1456 showGlobalActionsInternal();
1458 case LONG_PRESS_POWER_SHUT_OFF:
1459 case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
1460 mPowerKeyHandled = true;
1461 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1462 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
1463 mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
1468 private void backLongPress() {
1469 mBackKeyHandled = true;
1471 switch (mLongPressOnBackBehavior) {
1472 case LONG_PRESS_BACK_NOTHING:
1474 case LONG_PRESS_BACK_GO_TO_VOICE_ASSIST:
1475 final boolean keyguardActive = mKeyguardDelegate == null
1477 : mKeyguardDelegate.isShowing();
1478 if (!keyguardActive) {
1479 Intent intent = new Intent(Intent.ACTION_VOICE_ASSIST);
1480 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
1486 private void accessibilityShortcutActivated() {
1487 mAccessibilityShortcutController.performAccessibilityShortcut();
1490 private void disposeInputConsumer(InputConsumer inputConsumer) {
1491 if (inputConsumer != null) {
1492 inputConsumer.dismiss();
1496 private void sleepPress(long eventTime) {
1497 if (mShortPressOnSleepBehavior == SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME) {
1498 launchHomeFromHotKey(false /* awakenDreams */, true /*respectKeyguard*/);
1502 private void sleepRelease(long eventTime) {
1503 switch (mShortPressOnSleepBehavior) {
1504 case SHORT_PRESS_SLEEP_GO_TO_SLEEP:
1505 case SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME:
1506 Slog.i(TAG, "sleepRelease() calling goToSleep(GO_TO_SLEEP_REASON_SLEEP_BUTTON)");
1507 mPowerManager.goToSleep(eventTime,
1508 PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON, 0);
1513 private int getResolvedLongPressOnPowerBehavior() {
1514 if (FactoryTest.isLongPressOnPowerOffEnabled()) {
1515 return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
1517 return mLongPressOnPowerBehavior;
1520 private boolean hasLongPressOnPowerBehavior() {
1521 return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;
1524 private boolean hasLongPressOnBackBehavior() {
1525 return mLongPressOnBackBehavior != LONG_PRESS_BACK_NOTHING;
1528 private boolean hasPanicPressOnBackBehavior() {
1529 return mPanicPressOnBackBehavior != PANIC_PRESS_BACK_NOTHING;
1532 private void interceptScreenshotChord() {
1533 if (mScreenshotChordEnabled
1534 && mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered
1535 && !mA11yShortcutChordVolumeUpKeyTriggered) {
1536 final long now = SystemClock.uptimeMillis();
1537 if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
1538 && now <= mScreenshotChordPowerKeyTime
1539 + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
1540 mScreenshotChordVolumeDownKeyConsumed = true;
1541 cancelPendingPowerKeyAction();
1542 mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
1543 mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
1548 private void interceptAccessibilityShortcutChord() {
1549 if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable()
1550 && mScreenshotChordVolumeDownKeyTriggered && mA11yShortcutChordVolumeUpKeyTriggered
1551 && !mScreenshotChordPowerKeyTriggered) {
1552 final long now = SystemClock.uptimeMillis();
1553 if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
1554 && now <= mA11yShortcutChordVolumeUpKeyTime
1555 + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
1556 mScreenshotChordVolumeDownKeyConsumed = true;
1557 mA11yShortcutChordVolumeUpKeyConsumed = true;
1558 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_ACCESSIBILITY_SHORTCUT),
1559 ViewConfiguration.get(mContext).getAccessibilityShortcutKeyTimeout());
1564 private long getScreenshotChordLongPressDelay() {
1565 if (mKeyguardDelegate.isShowing()) {
1566 // Double the time it takes to take a screenshot from the keyguard
1567 return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER *
1568 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1570 return ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout();
1573 private void cancelPendingScreenshotChordAction() {
1574 mHandler.removeCallbacks(mScreenshotRunnable);
1577 private void cancelPendingAccessibilityShortcutAction() {
1578 mHandler.removeMessages(MSG_ACCESSIBILITY_SHORTCUT);
1581 private final Runnable mEndCallLongPress = new Runnable() {
1584 mEndCallKeyHandled = true;
1585 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1586 showGlobalActionsInternal();
1590 private class ScreenshotRunnable implements Runnable {
1591 private int mScreenshotType = TAKE_SCREENSHOT_FULLSCREEN;
1593 public void setScreenshotType(int screenshotType) {
1594 mScreenshotType = screenshotType;
1599 takeScreenshot(mScreenshotType);
1603 private final ScreenshotRunnable mScreenshotRunnable = new ScreenshotRunnable();
1606 public void showGlobalActions() {
1607 mHandler.removeMessages(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
1608 mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
1611 void showGlobalActionsInternal() {
1612 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
1613 if (mGlobalActions == null) {
1614 mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
1616 final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();
1617 mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
1618 if (keyguardShowing) {
1619 // since it took two seconds of long press to bring this up,
1620 // poke the wake lock so they have some time to see the dialog.
1621 mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
1625 boolean isDeviceProvisioned() {
1626 return Settings.Global.getInt(
1627 mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
1630 boolean isUserSetupComplete() {
1631 return Settings.Secure.getIntForUser(mContext.getContentResolver(),
1632 Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
1635 private void handleShortPressOnHome() {
1636 // Turn on the connected TV and switch HDMI input if we're a HDMI playback device.
1637 final HdmiControl hdmiControl = getHdmiControl();
1638 if (hdmiControl != null) {
1639 hdmiControl.turnOnTv();
1642 // If there's a dream running then use home to escape the dream
1643 // but don't actually go home.
1644 if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) {
1645 mDreamManagerInternal.stopDream(false /*immediate*/);
1650 launchHomeFromHotKey();
1654 * Creates an accessor to HDMI control service that performs the operation of
1655 * turning on TV (optional) and switching input to us. If HDMI control service
1656 * is not available or we're not a HDMI playback device, the operation is no-op.
1657 * @return {@link HdmiControl} instance if available, null otherwise.
1659 private HdmiControl getHdmiControl() {
1660 if (null == mHdmiControl) {
1661 if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
1664 HdmiControlManager manager = (HdmiControlManager) mContext.getSystemService(
1665 Context.HDMI_CONTROL_SERVICE);
1666 HdmiPlaybackClient client = null;
1667 if (manager != null) {
1668 client = manager.getPlaybackClient();
1670 mHdmiControl = new HdmiControl(client);
1672 return mHdmiControl;
1675 private static class HdmiControl {
1676 private final HdmiPlaybackClient mClient;
1678 private HdmiControl(HdmiPlaybackClient client) {
1682 public void turnOnTv() {
1683 if (mClient == null) {
1686 mClient.oneTouchPlay(new OneTouchPlayCallback() {
1688 public void onComplete(int result) {
1689 if (result != HdmiControlManager.RESULT_SUCCESS) {
1690 Log.w(TAG, "One touch play failed: " + result);
1697 private void handleLongPressOnHome(int deviceId) {
1698 if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_NOTHING) {
1701 mHomeConsumed = true;
1702 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1704 switch (mLongPressOnHomeBehavior) {
1705 case LONG_PRESS_HOME_RECENT_SYSTEM_UI:
1708 case LONG_PRESS_HOME_ASSIST:
1709 launchAssistAction(null, deviceId);
1712 Log.w(TAG, "Undefined home long press behavior: " + mLongPressOnHomeBehavior);
1717 private void handleDoubleTapOnHome() {
1718 if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
1719 mHomeConsumed = true;
1724 private void showTvPictureInPictureMenu(KeyEvent event) {
1725 if (DEBUG_INPUT) Log.d(TAG, "showTvPictureInPictureMenu event=" + event);
1726 mHandler.removeMessages(MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU);
1727 Message msg = mHandler.obtainMessage(MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU);
1728 msg.setAsynchronous(true);
1732 private void showTvPictureInPictureMenuInternal() {
1733 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
1734 if (statusbar != null) {
1735 statusbar.showTvPictureInPictureMenu();
1739 private final Runnable mHomeDoubleTapTimeoutRunnable = new Runnable() {
1742 if (mHomeDoubleTapPending) {
1743 mHomeDoubleTapPending = false;
1744 handleShortPressOnHome();
1749 private boolean isRoundWindow() {
1750 return mContext.getResources().getConfiguration().isScreenRound();
1753 /** {@inheritDoc} */
1755 public void init(Context context, IWindowManager windowManager,
1756 WindowManagerFuncs windowManagerFuncs) {
1758 mWindowManager = windowManager;
1759 mWindowManagerFuncs = windowManagerFuncs;
1760 mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
1761 mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
1762 mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
1763 mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
1764 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
1765 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
1766 mHasFeatureWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH);
1767 mHasFeatureLeanback = mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK);
1768 mAccessibilityShortcutController =
1769 new AccessibilityShortcutController(mContext, new Handler());
1770 // Init display burn-in protection
1771 boolean burnInProtectionEnabled = context.getResources().getBoolean(
1772 com.android.internal.R.bool.config_enableBurnInProtection);
1773 // Allow a system property to override this. Used by developer settings.
1774 boolean burnInProtectionDevMode =
1775 SystemProperties.getBoolean("persist.debug.force_burn_in", false);
1776 if (burnInProtectionEnabled || burnInProtectionDevMode) {
1777 final int minHorizontal;
1778 final int maxHorizontal;
1779 final int minVertical;
1780 final int maxVertical;
1781 final int maxRadius;
1782 if (burnInProtectionDevMode) {
1787 maxRadius = (isRoundWindow()) ? 6 : -1;
1789 Resources resources = context.getResources();
1790 minHorizontal = resources.getInteger(
1791 com.android.internal.R.integer.config_burnInProtectionMinHorizontalOffset);
1792 maxHorizontal = resources.getInteger(
1793 com.android.internal.R.integer.config_burnInProtectionMaxHorizontalOffset);
1794 minVertical = resources.getInteger(
1795 com.android.internal.R.integer.config_burnInProtectionMinVerticalOffset);
1796 maxVertical = resources.getInteger(
1797 com.android.internal.R.integer.config_burnInProtectionMaxVerticalOffset);
1798 maxRadius = resources.getInteger(
1799 com.android.internal.R.integer.config_burnInProtectionMaxRadius);
1801 mBurnInProtectionHelper = new BurnInProtectionHelper(
1802 context, minHorizontal, maxHorizontal, minVertical, maxVertical, maxRadius);
1805 mHandler = new PolicyHandler();
1806 mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
1807 mOrientationListener = new MyOrientationListener(mContext, mHandler);
1809 mOrientationListener.setCurrentRotation(windowManager.getDefaultDisplayRotation());
1810 } catch (RemoteException ex) { }
1811 mSettingsObserver = new SettingsObserver(mHandler);
1812 mSettingsObserver.observe();
1813 mShortcutManager = new ShortcutManager(context);
1814 mUiMode = context.getResources().getInteger(
1815 com.android.internal.R.integer.config_defaultUiModeType);
1816 mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
1817 mHomeIntent.addCategory(Intent.CATEGORY_HOME);
1818 mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1819 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1820 mEnableCarDockHomeCapture = context.getResources().getBoolean(
1821 com.android.internal.R.bool.config_enableCarDockHomeLaunch);
1822 mCarDockIntent = new Intent(Intent.ACTION_MAIN, null);
1823 mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
1824 mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1825 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1826 mDeskDockIntent = new Intent(Intent.ACTION_MAIN, null);
1827 mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
1828 mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1829 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1830 mVrHeadsetHomeIntent = new Intent(Intent.ACTION_MAIN, null);
1831 mVrHeadsetHomeIntent.addCategory(Intent.CATEGORY_VR_HOME);
1832 mVrHeadsetHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1833 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1835 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1836 mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1837 "PhoneWindowManager.mBroadcastWakeLock");
1838 mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1839 "PhoneWindowManager.mPowerKeyWakeLock");
1840 mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
1841 mSupportAutoRotation = mContext.getResources().getBoolean(
1842 com.android.internal.R.bool.config_supportAutoRotation);
1843 mLidOpenRotation = readRotation(
1844 com.android.internal.R.integer.config_lidOpenRotation);
1845 mCarDockRotation = readRotation(
1846 com.android.internal.R.integer.config_carDockRotation);
1847 mDeskDockRotation = readRotation(
1848 com.android.internal.R.integer.config_deskDockRotation);
1849 mUndockedHdmiRotation = readRotation(
1850 com.android.internal.R.integer.config_undockedHdmiRotation);
1851 mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
1852 com.android.internal.R.bool.config_carDockEnablesAccelerometer);
1853 mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
1854 com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
1855 mLidKeyboardAccessibility = mContext.getResources().getInteger(
1856 com.android.internal.R.integer.config_lidKeyboardAccessibility);
1857 mLidNavigationAccessibility = mContext.getResources().getInteger(
1858 com.android.internal.R.integer.config_lidNavigationAccessibility);
1859 mLidControlsScreenLock = mContext.getResources().getBoolean(
1860 com.android.internal.R.bool.config_lidControlsScreenLock);
1861 mLidControlsSleep = mContext.getResources().getBoolean(
1862 com.android.internal.R.bool.config_lidControlsSleep);
1863 mTranslucentDecorEnabled = mContext.getResources().getBoolean(
1864 com.android.internal.R.bool.config_enableTranslucentDecor);
1866 mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
1867 com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
1868 mAllowTheaterModeWakeFromPowerKey = mAllowTheaterModeWakeFromKey
1869 || mContext.getResources().getBoolean(
1870 com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey);
1871 mAllowTheaterModeWakeFromMotion = mContext.getResources().getBoolean(
1872 com.android.internal.R.bool.config_allowTheaterModeWakeFromMotion);
1873 mAllowTheaterModeWakeFromMotionWhenNotDreaming = mContext.getResources().getBoolean(
1874 com.android.internal.R.bool.config_allowTheaterModeWakeFromMotionWhenNotDreaming);
1875 mAllowTheaterModeWakeFromCameraLens = mContext.getResources().getBoolean(
1876 com.android.internal.R.bool.config_allowTheaterModeWakeFromCameraLens);
1877 mAllowTheaterModeWakeFromLidSwitch = mContext.getResources().getBoolean(
1878 com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch);
1879 mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean(
1880 com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture);
1882 mGoToSleepOnButtonPressTheaterMode = mContext.getResources().getBoolean(
1883 com.android.internal.R.bool.config_goToSleepOnButtonPressTheaterMode);
1885 mSupportLongPressPowerWhenNonInteractive = mContext.getResources().getBoolean(
1886 com.android.internal.R.bool.config_supportLongPressPowerWhenNonInteractive);
1888 mLongPressOnBackBehavior = mContext.getResources().getInteger(
1889 com.android.internal.R.integer.config_longPressOnBackBehavior);
1890 mPanicPressOnBackBehavior = mContext.getResources().getInteger(
1891 com.android.internal.R.integer.config_backPanicBehavior);
1893 mShortPressOnPowerBehavior = mContext.getResources().getInteger(
1894 com.android.internal.R.integer.config_shortPressOnPowerBehavior);
1895 mLongPressOnPowerBehavior = mContext.getResources().getInteger(
1896 com.android.internal.R.integer.config_longPressOnPowerBehavior);
1897 mDoublePressOnPowerBehavior = mContext.getResources().getInteger(
1898 com.android.internal.R.integer.config_doublePressOnPowerBehavior);
1899 mTriplePressOnPowerBehavior = mContext.getResources().getInteger(
1900 com.android.internal.R.integer.config_triplePressOnPowerBehavior);
1901 mShortPressOnSleepBehavior = mContext.getResources().getInteger(
1902 com.android.internal.R.integer.config_shortPressOnSleepBehavior);
1904 mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION;
1906 readConfigurationDependentBehaviors();
1908 mAccessibilityManager = (AccessibilityManager) context.getSystemService(
1909 Context.ACCESSIBILITY_SERVICE);
1911 // register for dock events
1912 IntentFilter filter = new IntentFilter();
1913 filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
1914 filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
1915 filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
1916 filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
1917 filter.addAction(Intent.ACTION_DOCK_EVENT);
1918 Intent intent = context.registerReceiver(mDockReceiver, filter);
1919 if (intent != null) {
1920 // Retrieve current sticky dock event broadcast.
1921 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
1922 Intent.EXTRA_DOCK_STATE_UNDOCKED);
1925 // register for dream-related broadcasts
1926 filter = new IntentFilter();
1927 filter.addAction(Intent.ACTION_DREAMING_STARTED);
1928 filter.addAction(Intent.ACTION_DREAMING_STOPPED);
1929 context.registerReceiver(mDreamReceiver, filter);
1931 // register for multiuser-relevant broadcasts
1932 filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
1933 context.registerReceiver(mMultiuserReceiver, filter);
1935 // monitor for system gestures
1936 mSystemGestures = new SystemGesturesPointerEventListener(context,
1937 new SystemGesturesPointerEventListener.Callbacks() {
1939 public void onSwipeFromTop() {
1940 if (mStatusBar != null) {
1941 requestTransientBars(mStatusBar);
1943 if (mPersistentVrModeEnabled) {
1944 exitPersistentVrMode();
1948 public void onSwipeFromBottom() {
1949 if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_BOTTOM) {
1950 requestTransientBars(mNavigationBar);
1952 if (mPersistentVrModeEnabled) {
1953 exitPersistentVrMode();
1957 public void onSwipeFromRight() {
1958 if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_RIGHT) {
1959 requestTransientBars(mNavigationBar);
1961 if (mPersistentVrModeEnabled) {
1962 exitPersistentVrMode();
1966 public void onSwipeFromLeft() {
1967 if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_LEFT) {
1968 requestTransientBars(mNavigationBar);
1970 if (mPersistentVrModeEnabled) {
1971 exitPersistentVrMode();
1975 public void onFling(int duration) {
1976 if (mPowerManagerInternal != null) {
1977 mPowerManagerInternal.powerHint(
1978 PowerHint.INTERACTION, duration);
1982 public void onDebug() {
1986 public void onDown() {
1987 mOrientationListener.onTouchStart();
1990 public void onUpOrCancel() {
1991 mOrientationListener.onTouchEnd();
1994 public void onMouseHoverAtTop() {
1995 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
1996 Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
1997 msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
1998 mHandler.sendMessageDelayed(msg, 500);
2001 public void onMouseHoverAtBottom() {
2002 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
2003 Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
2004 msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
2005 mHandler.sendMessageDelayed(msg, 500);
2008 public void onMouseLeaveFromEdge() {
2009 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
2012 mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext);
2013 mWindowManagerFuncs.registerPointerEventListener(mSystemGestures);
2015 mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
2016 mLongPressVibePattern = getLongIntArray(mContext.getResources(),
2017 com.android.internal.R.array.config_longPressVibePattern);
2018 mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(),
2019 com.android.internal.R.array.config_virtualKeyVibePattern);
2020 mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(),
2021 com.android.internal.R.array.config_keyboardTapVibePattern);
2022 mClockTickVibePattern = getLongIntArray(mContext.getResources(),
2023 com.android.internal.R.array.config_clockTickVibePattern);
2024 mCalendarDateVibePattern = getLongIntArray(mContext.getResources(),
2025 com.android.internal.R.array.config_calendarDateVibePattern);
2026 mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
2027 com.android.internal.R.array.config_safeModeDisabledVibePattern);
2028 mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
2029 com.android.internal.R.array.config_safeModeEnabledVibePattern);
2030 mContextClickVibePattern = getLongIntArray(mContext.getResources(),
2031 com.android.internal.R.array.config_contextClickVibePattern);
2033 mScreenshotChordEnabled = mContext.getResources().getBoolean(
2034 com.android.internal.R.bool.config_enableScreenshotChord);
2036 mGlobalKeyManager = new GlobalKeyManager(mContext);
2038 // Controls rotation and the like.
2039 initializeHdmiState();
2041 // Match current screen state.
2042 if (!mPowerManager.isInteractive()) {
2043 startedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
2044 finishedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
2047 mWindowManagerInternal.registerAppTransitionListener(
2048 mStatusBarController.getAppTransitionListener());
2049 mWindowManagerInternal.registerAppTransitionListener(new AppTransitionListener() {
2051 public int onAppTransitionStartingLocked(int transit, IBinder openToken,
2053 Animation openAnimation, Animation closeAnimation) {
2054 return handleStartTransitionForKeyguardLw(transit, openAnimation);
2058 public void onAppTransitionCancelledLocked(int transit) {
2059 handleStartTransitionForKeyguardLw(transit, null /* transit */);
2065 * Read values from config.xml that may be overridden depending on
2066 * the configuration of the device.
2067 * eg. Disable long press on home goes to recents on sw600dp.
2069 private void readConfigurationDependentBehaviors() {
2070 final Resources res = mContext.getResources();
2072 mLongPressOnHomeBehavior = res.getInteger(
2073 com.android.internal.R.integer.config_longPressOnHomeBehavior);
2074 if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||
2075 mLongPressOnHomeBehavior > LAST_LONG_PRESS_HOME_BEHAVIOR) {
2076 mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
2079 mDoubleTapOnHomeBehavior = res.getInteger(
2080 com.android.internal.R.integer.config_doubleTapOnHomeBehavior);
2081 if (mDoubleTapOnHomeBehavior < DOUBLE_TAP_HOME_NOTHING ||
2082 mDoubleTapOnHomeBehavior > DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
2083 mDoubleTapOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
2086 mShortPressWindowBehavior = SHORT_PRESS_WINDOW_NOTHING;
2087 if (mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
2088 mShortPressWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE;
2091 mNavBarOpacityMode = res.getInteger(
2092 com.android.internal.R.integer.config_navBarOpacityMode);
2096 public void setInitialDisplaySize(Display display, int width, int height, int density) {
2097 // This method might be called before the policy has been fully initialized
2098 // or for other displays we don't care about.
2099 // TODO(multi-display): Define policy for secondary displays.
2100 if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) {
2105 final Resources res = mContext.getResources();
2106 int shortSize, longSize;
2107 if (width > height) {
2110 mLandscapeRotation = Surface.ROTATION_0;
2111 mSeascapeRotation = Surface.ROTATION_180;
2112 if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
2113 mPortraitRotation = Surface.ROTATION_90;
2114 mUpsideDownRotation = Surface.ROTATION_270;
2116 mPortraitRotation = Surface.ROTATION_270;
2117 mUpsideDownRotation = Surface.ROTATION_90;
2122 mPortraitRotation = Surface.ROTATION_0;
2123 mUpsideDownRotation = Surface.ROTATION_180;
2124 if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
2125 mLandscapeRotation = Surface.ROTATION_270;
2126 mSeascapeRotation = Surface.ROTATION_90;
2128 mLandscapeRotation = Surface.ROTATION_90;
2129 mSeascapeRotation = Surface.ROTATION_270;
2133 // SystemUI (status bar) layout policy
2134 int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
2135 int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
2137 // Allow the navigation bar to move on non-square small devices (phones).
2138 mNavigationBarCanMove = width != height && shortSizeDp < 600;
2140 mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
2142 // Allow a system property to override this. Used by the emulator.
2143 // See also hasNavigationBar().
2144 String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
2145 if ("1".equals(navBarOverride)) {
2146 mHasNavigationBar = false;
2147 } else if ("0".equals(navBarOverride)) {
2148 mHasNavigationBar = true;
2151 // For demo purposes, allow the rotation of the HDMI display to be controlled.
2152 // By default, HDMI locks rotation to landscape.
2153 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
2154 mDemoHdmiRotation = mPortraitRotation;
2156 mDemoHdmiRotation = mLandscapeRotation;
2158 mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
2160 // For demo purposes, allow the rotation of the remote display to be controlled.
2161 // By default, remote display locks rotation to landscape.
2162 if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
2163 mDemoRotation = mPortraitRotation;
2165 mDemoRotation = mLandscapeRotation;
2167 mDemoRotationLock = SystemProperties.getBoolean(
2168 "persist.demo.rotationlock", false);
2170 // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
2171 // http://developer.android.com/guide/practices/screens_support.html#range
2172 mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 &&
2173 res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
2174 // For debug purposes the next line turns this feature off with:
2175 // $ adb shell setprop config.override_forced_orient true
2176 // $ adb shell wm size reset
2177 !"true".equals(SystemProperties.get("config.override_forced_orient"));
2181 * @return whether the navigation bar can be hidden, e.g. the device has a
2182 * navigation bar and touch exploration is not enabled
2184 private boolean canHideNavigationBar() {
2185 return mHasNavigationBar;
2189 public boolean isDefaultOrientationForced() {
2190 return mForceDefaultOrientation;
2194 public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) {
2195 // TODO(multi-display): Define policy for secondary displays.
2196 if (display.getDisplayId() == Display.DEFAULT_DISPLAY) {
2197 mOverscanLeft = left;
2199 mOverscanRight = right;
2200 mOverscanBottom = bottom;
2204 public void updateSettings() {
2205 ContentResolver resolver = mContext.getContentResolver();
2206 boolean updateRotation = false;
2207 synchronized (mLock) {
2208 mEndcallBehavior = Settings.System.getIntForUser(resolver,
2209 Settings.System.END_BUTTON_BEHAVIOR,
2210 Settings.System.END_BUTTON_BEHAVIOR_DEFAULT,
2211 UserHandle.USER_CURRENT);
2212 mIncallPowerBehavior = Settings.Secure.getIntForUser(resolver,
2213 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
2214 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT,
2215 UserHandle.USER_CURRENT);
2216 mIncallBackBehavior = Settings.Secure.getIntForUser(resolver,
2217 Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR,
2218 Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_DEFAULT,
2219 UserHandle.USER_CURRENT);
2221 // Configure wake gesture.
2222 boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver,
2223 Settings.Secure.WAKE_GESTURE_ENABLED, 0,
2224 UserHandle.USER_CURRENT) != 0;
2225 if (mWakeGestureEnabledSetting != wakeGestureEnabledSetting) {
2226 mWakeGestureEnabledSetting = wakeGestureEnabledSetting;
2227 updateWakeGestureListenerLp();
2230 // Configure rotation lock.
2231 int userRotation = Settings.System.getIntForUser(resolver,
2232 Settings.System.USER_ROTATION, Surface.ROTATION_0,
2233 UserHandle.USER_CURRENT);
2234 if (mUserRotation != userRotation) {
2235 mUserRotation = userRotation;
2236 updateRotation = true;
2238 int userRotationMode = Settings.System.getIntForUser(resolver,
2239 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
2240 WindowManagerPolicy.USER_ROTATION_FREE :
2241 WindowManagerPolicy.USER_ROTATION_LOCKED;
2242 if (mUserRotationMode != userRotationMode) {
2243 mUserRotationMode = userRotationMode;
2244 updateRotation = true;
2245 updateOrientationListenerLp();
2249 int pointerLocation = Settings.System.getIntForUser(resolver,
2250 Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT);
2251 if (mPointerLocationMode != pointerLocation) {
2252 mPointerLocationMode = pointerLocation;
2253 mHandler.sendEmptyMessage(pointerLocation != 0 ?
2254 MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
2257 // use screen off timeout setting as the timeout for the lockscreen
2258 mLockScreenTimeout = Settings.System.getIntForUser(resolver,
2259 Settings.System.SCREEN_OFF_TIMEOUT, 0, UserHandle.USER_CURRENT);
2260 String imId = Settings.Secure.getStringForUser(resolver,
2261 Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.USER_CURRENT);
2262 boolean hasSoftInput = imId != null && imId.length() > 0;
2263 if (mHasSoftInput != hasSoftInput) {
2264 mHasSoftInput = hasSoftInput;
2265 updateRotation = true;
2267 if (mImmersiveModeConfirmation != null) {
2268 mImmersiveModeConfirmation.loadSetting(mCurrentUserId);
2271 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
2272 PolicyControl.reloadFromSetting(mContext);
2274 if (updateRotation) {
2275 updateRotation(true);
2279 private void updateWakeGestureListenerLp() {
2280 if (shouldEnableWakeGestureLp()) {
2281 mWakeGestureListener.requestWakeUpTrigger();
2283 mWakeGestureListener.cancelWakeUpTrigger();
2287 private boolean shouldEnableWakeGestureLp() {
2288 return mWakeGestureEnabledSetting && !mAwake
2289 && (!mLidControlsSleep || mLidState != LID_CLOSED)
2290 && mWakeGestureListener.isSupported();
2293 private void enablePointerLocation() {
2294 if (mPointerLocationView == null) {
2295 mPointerLocationView = new PointerLocationView(mContext);
2296 mPointerLocationView.setPrintCoords(false);
2297 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
2298 WindowManager.LayoutParams.MATCH_PARENT,
2299 WindowManager.LayoutParams.MATCH_PARENT);
2300 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
2301 lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
2302 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
2303 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2304 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
2305 if (ActivityManager.isHighEndGfx()) {
2306 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
2308 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
2310 lp.format = PixelFormat.TRANSLUCENT;
2311 lp.setTitle("PointerLocation");
2312 WindowManager wm = (WindowManager) mContext.getSystemService(WINDOW_SERVICE);
2313 lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
2314 wm.addView(mPointerLocationView, lp);
2315 mWindowManagerFuncs.registerPointerEventListener(mPointerLocationView);
2319 private void disablePointerLocation() {
2320 if (mPointerLocationView != null) {
2321 mWindowManagerFuncs.unregisterPointerEventListener(mPointerLocationView);
2322 WindowManager wm = (WindowManager) mContext.getSystemService(WINDOW_SERVICE);
2323 wm.removeView(mPointerLocationView);
2324 mPointerLocationView = null;
2328 private int readRotation(int resID) {
2330 int rotation = mContext.getResources().getInteger(resID);
2333 return Surface.ROTATION_0;
2335 return Surface.ROTATION_90;
2337 return Surface.ROTATION_180;
2339 return Surface.ROTATION_270;
2341 } catch (Resources.NotFoundException e) {
2347 /** {@inheritDoc} */
2349 public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) {
2350 int type = attrs.type;
2352 outAppOp[0] = AppOpsManager.OP_NONE;
2354 if (!((type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW)
2355 || (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW)
2356 || (type >= FIRST_SYSTEM_WINDOW && type <= LAST_SYSTEM_WINDOW))) {
2357 return WindowManagerGlobal.ADD_INVALID_TYPE;
2360 if (type < FIRST_SYSTEM_WINDOW || type > LAST_SYSTEM_WINDOW) {
2361 // Window manager will make sure these are okay.
2365 if (!isSystemAlertWindowType(type)) {
2368 // Only apps that target older than O SDK can add window without a token, after
2369 // that we require a token so apps cannot add toasts directly as the token is
2370 // added by the notification system.
2371 // Window manager does the checking for this.
2372 outAppOp[0] = OP_TOAST_WINDOW;
2375 case TYPE_INPUT_METHOD:
2376 case TYPE_WALLPAPER:
2377 case TYPE_PRESENTATION:
2378 case TYPE_PRIVATE_PRESENTATION:
2379 case TYPE_VOICE_INTERACTION:
2380 case TYPE_ACCESSIBILITY_OVERLAY:
2381 case TYPE_QS_DIALOG:
2382 // The window manager will check these.
2385 return mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
2386 == PERMISSION_GRANTED ? ADD_OKAY : ADD_PERMISSION_DENIED;
2389 // Things get a little more interesting for alert windows...
2390 outAppOp[0] = OP_SYSTEM_ALERT_WINDOW;
2392 final int callingUid = Binder.getCallingUid();
2393 // system processes will be automatically granted privilege to draw
2394 if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
2398 ApplicationInfo appInfo;
2400 appInfo = mContext.getPackageManager().getApplicationInfoAsUser(
2403 UserHandle.getUserId(callingUid));
2404 } catch (PackageManager.NameNotFoundException e) {
2408 if (appInfo == null || (type != TYPE_APPLICATION_OVERLAY && appInfo.targetSdkVersion >= O)) {
2410 * Apps targeting >= {@link Build.VERSION_CODES#O} are required to hold
2411 * {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW} (system signature apps)
2412 * permission to add alert windows that aren't
2413 * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY}.
2415 return (mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
2416 == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
2419 // check if user has enabled this operation. SecurityException will be thrown if this app
2420 // has not been allowed by the user
2421 final int mode = mAppOpsManager.checkOpNoThrow(outAppOp[0], callingUid, attrs.packageName);
2423 case AppOpsManager.MODE_ALLOWED:
2424 case AppOpsManager.MODE_IGNORED:
2425 // although we return ADD_OKAY for MODE_IGNORED, the added window will
2426 // actually be hidden in WindowManagerService
2428 case AppOpsManager.MODE_ERRORED:
2429 // Don't crash legacy apps
2430 if (appInfo.targetSdkVersion < M) {
2433 return ADD_PERMISSION_DENIED;
2435 // in the default mode, we will make a decision here based on
2436 // checkCallingPermission()
2437 return (mContext.checkCallingOrSelfPermission(SYSTEM_ALERT_WINDOW)
2438 == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
2443 public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) {
2445 // If this switch statement is modified, modify the comment in the declarations of
2446 // the type in {@link WindowManager.LayoutParams} as well.
2447 switch (attrs.type) {
2449 // These are the windows that by default are shown only to the user that created
2450 // them. If this needs to be overridden, set
2451 // {@link WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS} in
2452 // {@link WindowManager.LayoutParams}. Note that permission
2453 // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well.
2454 if ((attrs.privateFlags & PRIVATE_FLAG_SHOW_FOR_ALL_USERS) == 0) {
2459 // These are the windows that by default are shown to all users. However, to
2460 // protect against spoofing, check permissions below.
2461 case TYPE_APPLICATION_STARTING:
2462 case TYPE_BOOT_PROGRESS:
2463 case TYPE_DISPLAY_OVERLAY:
2464 case TYPE_INPUT_CONSUMER:
2465 case TYPE_KEYGUARD_DIALOG:
2466 case TYPE_MAGNIFICATION_OVERLAY:
2467 case TYPE_NAVIGATION_BAR:
2468 case TYPE_NAVIGATION_BAR_PANEL:
2471 case TYPE_PRIORITY_PHONE:
2472 case TYPE_SEARCH_BAR:
2473 case TYPE_STATUS_BAR:
2474 case TYPE_STATUS_BAR_PANEL:
2475 case TYPE_STATUS_BAR_SUB_PANEL:
2476 case TYPE_SYSTEM_DIALOG:
2477 case TYPE_VOLUME_OVERLAY:
2478 case TYPE_PRESENTATION:
2479 case TYPE_PRIVATE_PRESENTATION:
2480 case TYPE_DOCK_DIVIDER:
2484 // Check if third party app has set window to system window type.
2485 return mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW) != PERMISSION_GRANTED;
2489 public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
2490 switch (attrs.type) {
2491 case TYPE_SYSTEM_OVERLAY:
2492 case TYPE_SECURE_SYSTEM_OVERLAY:
2493 // These types of windows can't receive input events.
2494 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2495 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
2496 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
2498 case TYPE_STATUS_BAR:
2500 // If the Keyguard is in a hidden state (occluded by another window), we force to
2501 // remove the wallpaper and keyguard flag so that any change in-flight after setting
2502 // the keyguard as occluded wouldn't set these flags again.
2503 // See {@link #processKeyguardSetHiddenResultLw}.
2504 if (mKeyguardOccluded) {
2505 attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
2506 attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2510 case TYPE_SCREENSHOT:
2511 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
2515 // While apps should use the dedicated toast APIs to add such windows
2516 // it possible legacy apps to add the window directly. Therefore, we
2517 // make windows added directly by the app behave as a toast as much
2518 // as possible in terms of timeout and animation.
2519 if (attrs.hideTimeoutMilliseconds < 0
2520 || attrs.hideTimeoutMilliseconds > TOAST_WINDOW_TIMEOUT) {
2521 attrs.hideTimeoutMilliseconds = TOAST_WINDOW_TIMEOUT;
2523 attrs.windowAnimations = com.android.internal.R.style.Animation_Toast;
2527 if (attrs.type != TYPE_STATUS_BAR) {
2528 // The status bar is the only window allowed to exhibit keyguard behavior.
2529 attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2532 if (ActivityManager.isHighEndGfx()) {
2533 if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
2534 attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
2536 final boolean forceWindowDrawsStatusBarBackground =
2537 (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND)
2539 if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
2540 || forceWindowDrawsStatusBarBackground
2541 && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) {
2542 attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2547 void readLidState() {
2548 mLidState = mWindowManagerFuncs.getLidState();
2551 private void readCameraLensCoverState() {
2552 mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState();
2555 private boolean isHidden(int accessibilityMode) {
2556 switch (accessibilityMode) {
2558 return mLidState == LID_CLOSED;
2560 return mLidState == LID_OPEN;
2566 /** {@inheritDoc} */
2568 public void adjustConfigurationLw(Configuration config, int keyboardPresence,
2569 int navigationPresence) {
2570 mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0;
2572 readConfigurationDependentBehaviors();
2575 if (config.keyboard == Configuration.KEYBOARD_NOKEYS
2576 || (keyboardPresence == PRESENCE_INTERNAL
2577 && isHidden(mLidKeyboardAccessibility))) {
2578 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
2579 if (!mHasSoftInput) {
2580 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
2584 if (config.navigation == Configuration.NAVIGATION_NONAV
2585 || (navigationPresence == PRESENCE_INTERNAL
2586 && isHidden(mLidNavigationAccessibility))) {
2587 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
2592 public void onConfigurationChanged() {
2593 // TODO(multi-display): Define policy for secondary displays.
2594 final Resources res = mContext.getResources();
2597 res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
2599 // Height of the navigation bar when presented horizontally at bottom
2600 mNavigationBarHeightForRotationDefault[mPortraitRotation] =
2601 mNavigationBarHeightForRotationDefault[mUpsideDownRotation] =
2602 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
2603 mNavigationBarHeightForRotationDefault[mLandscapeRotation] =
2604 mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize(
2605 com.android.internal.R.dimen.navigation_bar_height_landscape);
2607 // Width of the navigation bar when presented vertically along one side
2608 mNavigationBarWidthForRotationDefault[mPortraitRotation] =
2609 mNavigationBarWidthForRotationDefault[mUpsideDownRotation] =
2610 mNavigationBarWidthForRotationDefault[mLandscapeRotation] =
2611 mNavigationBarWidthForRotationDefault[mSeascapeRotation] =
2612 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
2614 if (ALTERNATE_CAR_MODE_NAV_SIZE) {
2615 // Height of the navigation bar when presented horizontally at bottom
2616 mNavigationBarHeightForRotationInCarMode[mPortraitRotation] =
2617 mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] =
2618 res.getDimensionPixelSize(
2619 com.android.internal.R.dimen.navigation_bar_height_car_mode);
2620 mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] =
2621 mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize(
2622 com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode);
2624 // Width of the navigation bar when presented vertically along one side
2625 mNavigationBarWidthForRotationInCarMode[mPortraitRotation] =
2626 mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] =
2627 mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] =
2628 mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] =
2629 res.getDimensionPixelSize(
2630 com.android.internal.R.dimen.navigation_bar_width_car_mode);
2635 public int getMaxWallpaperLayer() {
2636 return getWindowLayerFromTypeLw(TYPE_STATUS_BAR);
2639 private int getNavigationBarWidth(int rotation, int uiMode) {
2640 if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2641 return mNavigationBarWidthForRotationInCarMode[rotation];
2643 return mNavigationBarWidthForRotationDefault[rotation];
2648 public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
2650 // TODO(multi-display): Support navigation bar on secondary displays.
2651 if (displayId == Display.DEFAULT_DISPLAY && mHasNavigationBar) {
2652 // For a basic navigation bar, when we are in landscape mode we place
2653 // the navigation bar to the side.
2654 if (mNavigationBarCanMove && fullWidth > fullHeight) {
2655 return fullWidth - getNavigationBarWidth(rotation, uiMode);
2661 private int getNavigationBarHeight(int rotation, int uiMode) {
2662 if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2663 return mNavigationBarHeightForRotationInCarMode[rotation];
2665 return mNavigationBarHeightForRotationDefault[rotation];
2670 public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
2672 // TODO(multi-display): Support navigation bar on secondary displays.
2673 if (displayId == Display.DEFAULT_DISPLAY && mHasNavigationBar) {
2674 // For a basic navigation bar, when we are in portrait mode we place
2675 // the navigation bar to the bottom.
2676 if (!mNavigationBarCanMove || fullWidth < fullHeight) {
2677 return fullHeight - getNavigationBarHeight(rotation, uiMode);
2684 public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
2686 return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode, displayId);
2690 public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
2692 // There is a separate status bar at the top of the display. We don't count that as part
2693 // of the fixed decor, since it can hide; however, for purposes of configurations,
2694 // we do want to exclude it since applications can't generally use that part
2696 // TODO(multi-display): Support status bars on secondary displays.
2697 if (displayId == Display.DEFAULT_DISPLAY) {
2698 return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayId)
2705 public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) {
2706 return attrs.type == TYPE_STATUS_BAR;
2710 public boolean canBeHiddenByKeyguardLw(WindowState win) {
2711 switch (win.getAttrs().type) {
2712 case TYPE_STATUS_BAR:
2713 case TYPE_NAVIGATION_BAR:
2714 case TYPE_WALLPAPER:
2718 // Hide only windows below the keyguard host window.
2719 return getWindowLayerLw(win) < getWindowLayerFromTypeLw(TYPE_STATUS_BAR);
2723 private boolean shouldBeHiddenByKeyguard(WindowState win, WindowState imeTarget) {
2725 // Keyguard visibility of window from activities are determined over activity visibility.
2726 if (win.getAppToken() != null) {
2730 final LayoutParams attrs = win.getAttrs();
2731 final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleLw() &&
2732 ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0
2733 || !canBeHiddenByKeyguardLw(imeTarget));
2735 // Show IME over the keyguard if the target allows it
2736 boolean allowWhenLocked = (win.isInputMethodWindow() || imeTarget == this)
2737 && showImeOverKeyguard;;
2739 if (isKeyguardLocked() && isKeyguardOccluded()) {
2740 // Show SHOW_WHEN_LOCKED windows if Keyguard is occluded.
2741 allowWhenLocked |= (attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
2742 // Show error dialogs over apps that are shown on lockscreen
2743 || (attrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
2746 boolean keyguardLocked = isKeyguardLocked();
2747 boolean hideDockDivider = attrs.type == TYPE_DOCK_DIVIDER
2748 && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
2749 return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == Display.DEFAULT_DISPLAY)
2753 /** {@inheritDoc} */
2755 public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme,
2756 CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon,
2757 int logo, int windowFlags, Configuration overrideConfig, int displayId) {
2758 if (!SHOW_SPLASH_SCREENS) {
2761 if (packageName == null) {
2765 WindowManager wm = null;
2769 Context context = mContext;
2770 if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen " + packageName
2771 + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
2772 + Integer.toHexString(theme));
2774 // Obtain proper context to launch on the right display.
2775 final Context displayContext = getDisplayContext(context, displayId);
2776 if (displayContext == null) {
2777 // Can't show splash screen on requested display, so skip showing at all.
2780 context = displayContext;
2782 if (theme != context.getThemeResId() || labelRes != 0) {
2784 context = context.createPackageContext(packageName, 0);
2785 context.setTheme(theme);
2786 } catch (PackageManager.NameNotFoundException e) {
2791 if (overrideConfig != null && !overrideConfig.equals(EMPTY)) {
2792 if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: creating context based"
2793 + " on overrideConfig" + overrideConfig + " for splash screen");
2794 final Context overrideContext = context.createConfigurationContext(overrideConfig);
2795 overrideContext.setTheme(theme);
2796 final TypedArray typedArray = overrideContext.obtainStyledAttributes(
2797 com.android.internal.R.styleable.Window);
2798 final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
2799 if (resId != 0 && overrideContext.getDrawable(resId) != null) {
2800 // We want to use the windowBackground for the override context if it is
2801 // available, otherwise we use the default one to make sure a themed starting
2802 // window is displayed for the app.
2803 if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: apply overrideConfig"
2804 + overrideConfig + " to starting window resId=" + resId);
2805 context = overrideContext;
2809 final PhoneWindow win = new PhoneWindow(context);
2810 win.setIsStartingWindow(true);
2812 CharSequence label = context.getResources().getText(labelRes, null);
2813 // Only change the accessibility title if the label is localized
2814 if (label != null) {
2815 win.setTitle(label, true);
2817 win.setTitle(nonLocalizedLabel, false);
2821 WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
2823 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
2824 // Assumes it's safe to show starting windows of launched apps while
2825 // the keyguard is being hidden. This is okay because starting windows never show
2826 // secret information.
2827 if (mKeyguardOccluded) {
2828 windowFlags |= FLAG_SHOW_WHEN_LOCKED;
2832 // Force the window flags: this is a fake window, so it is not really
2833 // touchable or focusable by the user. We also add in the ALT_FOCUSABLE_IM
2834 // flag because we do know that the next window will take input
2835 // focus, so we want to get the IME window up on top of us right away.
2838 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2839 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2840 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
2842 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2843 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2844 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
2846 win.setDefaultIcon(icon);
2847 win.setDefaultLogo(logo);
2849 win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
2850 WindowManager.LayoutParams.MATCH_PARENT);
2852 final WindowManager.LayoutParams params = win.getAttributes();
2853 params.token = appToken;
2854 params.packageName = packageName;
2855 params.windowAnimations = win.getWindowStyle().getResourceId(
2856 com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
2857 params.privateFlags |=
2858 WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
2859 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
2861 if (!compatInfo.supportsScreen()) {
2862 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
2865 params.setTitle("Splash Screen " + packageName);
2866 wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
2867 view = win.getDecorView();
2869 if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "Adding splash screen window for "
2870 + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null));
2872 wm.addView(view, params);
2874 // Only return the view if it was successfully added to the
2875 // window manager... which we can tell by it having a parent.
2876 return view.getParent() != null ? new SplashScreenSurface(view, appToken) : null;
2877 } catch (WindowManager.BadTokenException e) {
2879 Log.w(TAG, appToken + " already running, starting window not displayed. " +
2881 } catch (RuntimeException e) {
2882 // don't crash if something else bad happens, for example a
2883 // failure loading resources because we are loading from an app
2884 // on external storage that has been unmounted.
2885 Log.w(TAG, appToken + " failed creating starting window", e);
2887 if (view != null && view.getParent() == null) {
2888 Log.w(TAG, "view not successfully added to wm, removing view");
2889 wm.removeViewImmediate(view);
2896 /** Obtain proper context for showing splash screen on the provided display. */
2897 private Context getDisplayContext(Context context, int displayId) {
2898 if (displayId == Display.DEFAULT_DISPLAY) {
2899 // The default context fits.
2903 final DisplayManager dm = (DisplayManager) context.getSystemService(DISPLAY_SERVICE);
2904 final Display targetDisplay = dm.getDisplay(displayId);
2905 if (targetDisplay == null) {
2906 // Failed to obtain the non-default display where splash screen should be shown,
2907 // lets not show at all.
2911 return context.createDisplayContext(targetDisplay);
2915 * Preflight adding a window to the system.
2917 * Currently enforces that three window types are singletons:
2919 * <li>STATUS_BAR_TYPE</li>
2920 * <li>KEYGUARD_TYPE</li>
2923 * @param win The window to be added
2924 * @param attrs Information about the window to be added
2926 * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons,
2927 * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
2930 public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
2931 switch (attrs.type) {
2932 case TYPE_STATUS_BAR:
2933 mContext.enforceCallingOrSelfPermission(
2934 android.Manifest.permission.STATUS_BAR_SERVICE,
2935 "PhoneWindowManager");
2936 if (mStatusBar != null) {
2937 if (mStatusBar.isAlive()) {
2938 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2942 mStatusBarController.setWindow(win);
2944 case TYPE_NAVIGATION_BAR:
2945 mContext.enforceCallingOrSelfPermission(
2946 android.Manifest.permission.STATUS_BAR_SERVICE,
2947 "PhoneWindowManager");
2948 if (mNavigationBar != null) {
2949 if (mNavigationBar.isAlive()) {
2950 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2953 mNavigationBar = win;
2954 mNavigationBarController.setWindow(win);
2955 mNavigationBarController.setOnBarVisibilityChangedListener(
2956 mNavBarVisibilityListener);
2957 if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
2959 case TYPE_NAVIGATION_BAR_PANEL:
2960 case TYPE_STATUS_BAR_PANEL:
2961 case TYPE_STATUS_BAR_SUB_PANEL:
2962 case TYPE_VOICE_INTERACTION_STARTING:
2963 mContext.enforceCallingOrSelfPermission(
2964 android.Manifest.permission.STATUS_BAR_SERVICE,
2965 "PhoneWindowManager");
2971 /** {@inheritDoc} */
2973 public void removeWindowLw(WindowState win) {
2974 if (mStatusBar == win) {
2976 mStatusBarController.setWindow(null);
2977 } else if (mNavigationBar == win) {
2978 mNavigationBar = null;
2979 mNavigationBarController.setWindow(null);
2983 static final boolean PRINT_ANIM = false;
2985 /** {@inheritDoc} */
2987 public int selectAnimationLw(WindowState win, int transit) {
2988 if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
2989 + ": transit=" + transit);
2990 if (win == mStatusBar) {
2991 boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
2992 if (transit == TRANSIT_EXIT
2993 || transit == TRANSIT_HIDE) {
2994 return isKeyguard ? -1 : R.anim.dock_top_exit;
2995 } else if (transit == TRANSIT_ENTER
2996 || transit == TRANSIT_SHOW) {
2997 return isKeyguard ? -1 : R.anim.dock_top_enter;
2999 } else if (win == mNavigationBar) {
3000 if (win.getAttrs().windowAnimations != 0) {
3003 // This can be on either the bottom or the right or the left.
3004 if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
3005 if (transit == TRANSIT_EXIT
3006 || transit == TRANSIT_HIDE) {
3007 if (isKeyguardShowingAndNotOccluded()) {
3008 return R.anim.dock_bottom_exit_keyguard;
3010 return R.anim.dock_bottom_exit;
3012 } else if (transit == TRANSIT_ENTER
3013 || transit == TRANSIT_SHOW) {
3014 return R.anim.dock_bottom_enter;
3016 } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
3017 if (transit == TRANSIT_EXIT
3018 || transit == TRANSIT_HIDE) {
3019 return R.anim.dock_right_exit;
3020 } else if (transit == TRANSIT_ENTER
3021 || transit == TRANSIT_SHOW) {
3022 return R.anim.dock_right_enter;
3024 } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
3025 if (transit == TRANSIT_EXIT
3026 || transit == TRANSIT_HIDE) {
3027 return R.anim.dock_left_exit;
3028 } else if (transit == TRANSIT_ENTER
3029 || transit == TRANSIT_SHOW) {
3030 return R.anim.dock_left_enter;
3033 } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) {
3034 return selectDockedDividerAnimationLw(win, transit);
3037 if (transit == TRANSIT_PREVIEW_DONE) {
3038 if (win.hasAppShownWindows()) {
3039 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
3040 return com.android.internal.R.anim.app_starting_exit;
3042 } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
3043 && transit == TRANSIT_ENTER) {
3044 // Special case: we are animating in a dream, while the keyguard
3045 // is shown. We don't want an animation on the dream, because
3046 // we need it shown immediately with the keyguard animating away
3054 private int selectDockedDividerAnimationLw(WindowState win, int transit) {
3055 int insets = mWindowManagerFuncs.getDockedDividerInsetsLw();
3057 // If the divider is behind the navigation bar, don't animate.
3058 final Rect frame = win.getFrameLw();
3059 final boolean behindNavBar = mNavigationBar != null
3060 && ((mNavigationBarPosition == NAV_BAR_BOTTOM
3061 && frame.top + insets >= mNavigationBar.getFrameLw().top)
3062 || (mNavigationBarPosition == NAV_BAR_RIGHT
3063 && frame.left + insets >= mNavigationBar.getFrameLw().left)
3064 || (mNavigationBarPosition == NAV_BAR_LEFT
3065 && frame.right - insets <= mNavigationBar.getFrameLw().right));
3066 final boolean landscape = frame.height() > frame.width();
3067 final boolean offscreenLandscape = landscape && (frame.right - insets <= 0
3068 || frame.left + insets >= win.getDisplayFrameLw().right);
3069 final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0
3070 || frame.bottom + insets >= win.getDisplayFrameLw().bottom);
3071 final boolean offscreen = offscreenLandscape || offscreenPortrait;
3072 if (behindNavBar || offscreen) {
3075 if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
3076 return R.anim.fade_in;
3077 } else if (transit == TRANSIT_EXIT) {
3078 return R.anim.fade_out;
3085 public void selectRotationAnimationLw(int anim[]) {
3086 if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
3087 + mTopFullscreenOpaqueWindowState + " rotationAnimation="
3088 + (mTopFullscreenOpaqueWindowState == null ?
3089 "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation));
3090 if (mTopFullscreenOpaqueWindowState != null) {
3091 int animationHint = mTopFullscreenOpaqueWindowState.getRotationAnimationHint();
3092 if (animationHint < 0 && mTopIsFullscreen) {
3093 animationHint = mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation;
3095 switch (animationHint) {
3096 case ROTATION_ANIMATION_CROSSFADE:
3097 case ROTATION_ANIMATION_SEAMLESS: // Crossfade is fallback for seamless.
3098 anim[0] = R.anim.rotation_animation_xfade_exit;
3099 anim[1] = R.anim.rotation_animation_enter;
3101 case ROTATION_ANIMATION_JUMPCUT:
3102 anim[0] = R.anim.rotation_animation_jump_exit;
3103 anim[1] = R.anim.rotation_animation_enter;
3105 case ROTATION_ANIMATION_ROTATE:
3107 anim[0] = anim[1] = 0;
3111 anim[0] = anim[1] = 0;
3116 public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId,
3117 boolean forceDefault) {
3118 switch (exitAnimId) {
3119 case R.anim.rotation_animation_xfade_exit:
3120 case R.anim.rotation_animation_jump_exit:
3121 // These are the only cases that matter.
3125 int anim[] = new int[2];
3126 selectRotationAnimationLw(anim);
3127 return (exitAnimId == anim[0] && enterAnimId == anim[1]);
3134 public Animation createHiddenByKeyguardExit(boolean onWallpaper,
3135 boolean goingToNotificationShade) {
3136 if (goingToNotificationShade) {
3137 return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
3140 AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ?
3141 R.anim.lock_screen_behind_enter_wallpaper :
3142 R.anim.lock_screen_behind_enter);
3144 // TODO: Use XML interpolators when we have log interpolators available in XML.
3145 final List<Animation> animations = set.getAnimations();
3146 for (int i = animations.size() - 1; i >= 0; --i) {
3147 animations.get(i).setInterpolator(mLogDecelerateInterpolator);
3155 public Animation createKeyguardWallpaperExit(boolean goingToNotificationShade) {
3156 if (goingToNotificationShade) {
3159 return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
3163 private static void awakenDreams() {
3164 IDreamManager dreamManager = getDreamManager();
3165 if (dreamManager != null) {
3167 dreamManager.awaken();
3168 } catch (RemoteException e) {
3169 // fine, stay asleep then
3174 static IDreamManager getDreamManager() {
3175 return IDreamManager.Stub.asInterface(
3176 ServiceManager.checkService(DreamService.DREAM_SERVICE));
3179 TelecomManager getTelecommService() {
3180 return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
3183 static IAudioService getAudioService() {
3184 IAudioService audioService = IAudioService.Stub.asInterface(
3185 ServiceManager.checkService(Context.AUDIO_SERVICE));
3186 if (audioService == null) {
3187 Log.w(TAG, "Unable to find IAudioService interface.");
3189 return audioService;
3192 boolean keyguardOn() {
3193 return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode();
3196 private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
3197 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
3198 WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
3201 /** {@inheritDoc} */
3203 public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
3204 final boolean keyguardOn = keyguardOn();
3205 final int keyCode = event.getKeyCode();
3206 final int repeatCount = event.getRepeatCount();
3207 final int metaState = event.getMetaState();
3208 final int flags = event.getFlags();
3209 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
3210 final boolean canceled = event.isCanceled();
3213 Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
3214 + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
3215 + " canceled=" + canceled);
3218 // If we think we might have a volume down & power key chord on the way
3219 // but we're not sure, then tell the dispatcher to wait a little while and
3220 // try again later before dispatching.
3221 if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
3222 if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
3223 final long now = SystemClock.uptimeMillis();
3224 final long timeoutTime = mScreenshotChordVolumeDownKeyTime
3225 + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
3226 if (now < timeoutTime) {
3227 return timeoutTime - now;
3230 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3231 && mScreenshotChordVolumeDownKeyConsumed) {
3233 mScreenshotChordVolumeDownKeyConsumed = false;
3239 // If an accessibility shortcut might be partially complete, hold off dispatching until we
3240 // know if it is complete or not
3241 if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable()
3242 && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
3243 if (mScreenshotChordVolumeDownKeyTriggered ^ mA11yShortcutChordVolumeUpKeyTriggered) {
3244 final long now = SystemClock.uptimeMillis();
3245 final long timeoutTime = (mScreenshotChordVolumeDownKeyTriggered
3246 ? mScreenshotChordVolumeDownKeyTime : mA11yShortcutChordVolumeUpKeyTime)
3247 + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
3248 if (now < timeoutTime) {
3249 return timeoutTime - now;
3252 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && mScreenshotChordVolumeDownKeyConsumed) {
3254 mScreenshotChordVolumeDownKeyConsumed = false;
3258 if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mA11yShortcutChordVolumeUpKeyConsumed) {
3260 mA11yShortcutChordVolumeUpKeyConsumed = false;
3266 // Cancel any pending meta actions if we see any other keys being pressed between the down
3267 // of the meta key and its corresponding up.
3268 if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
3269 mPendingMetaAction = false;
3271 // Any key that is not Alt or Meta cancels Caps Lock combo tracking.
3272 if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) {
3273 mPendingCapsLockToggle = false;
3276 // First we always handle the home key here, so applications
3277 // can never break it, although if keyguard is on, we do let
3278 // it handle it, because that gives us the correct 5 second
3280 if (keyCode == KeyEvent.KEYCODE_HOME) {
3282 // If we have released the home key, and didn't do anything else
3283 // while it was pressed, then it is time to go home!
3285 cancelPreloadRecentApps();
3287 mHomePressed = false;
3288 if (mHomeConsumed) {
3289 mHomeConsumed = false;
3294 Log.i(TAG, "Ignoring HOME; event canceled.");
3298 // Delay handling home if a double-tap is possible.
3299 if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
3300 mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
3301 mHomeDoubleTapPending = true;
3302 mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
3303 ViewConfiguration.getDoubleTapTimeout());
3307 handleShortPressOnHome();
3311 // If a system window has focus, then it doesn't make sense
3312 // right now to interact with applications.
3313 WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
3314 if (attrs != null) {
3315 final int type = attrs.type;
3316 if (type == TYPE_KEYGUARD_DIALOG
3317 || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
3318 // the "app" is keyguard, so give it the key
3321 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
3322 for (int i=0; i<typeCount; i++) {
3323 if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
3324 // don't do anything, but also don't pass it to the app
3330 // Remember that home is pressed and handle special actions.
3331 if (repeatCount == 0) {
3332 mHomePressed = true;
3333 if (mHomeDoubleTapPending) {
3334 mHomeDoubleTapPending = false;
3335 mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
3336 handleDoubleTapOnHome();
3337 } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI
3338 || mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
3339 preloadRecentApps();
3341 } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
3343 handleLongPressOnHome(event.getDeviceId());
3347 } else if (keyCode == KeyEvent.KEYCODE_MENU) {
3348 // Hijack modified menu keys for debugging features
3349 final int chordBug = KeyEvent.META_SHIFT_ON;
3351 if (down && repeatCount == 0) {
3352 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
3353 Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
3354 mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
3355 null, null, null, 0, null, null);
3359 } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
3361 if (repeatCount == 0) {
3362 mSearchKeyShortcutPending = true;
3363 mConsumeSearchKeyUp = false;
3366 mSearchKeyShortcutPending = false;
3367 if (mConsumeSearchKeyUp) {
3368 mConsumeSearchKeyUp = false;
3373 } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
3375 if (down && repeatCount == 0) {
3376 preloadRecentApps();
3382 } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) {
3384 IStatusBarService service = getStatusBarService();
3385 if (service != null) {
3387 service.expandNotificationsPanel();
3388 } catch (RemoteException e) {
3393 } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed()
3394 && event.isCtrlPressed()) {
3395 if (down && repeatCount == 0) {
3396 int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION
3397 : TAKE_SCREENSHOT_FULLSCREEN;
3398 mScreenshotRunnable.setScreenshotType(type);
3399 mHandler.post(mScreenshotRunnable);
3402 } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
3403 if (down && repeatCount == 0 && !isKeyguardLocked()) {
3404 toggleKeyboardShortcutsMenu(event.getDeviceId());
3406 } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
3408 if (repeatCount == 0) {
3409 mAssistKeyLongPressed = false;
3410 } else if (repeatCount == 1) {
3411 mAssistKeyLongPressed = true;
3413 launchAssistLongPressAction();
3417 if (mAssistKeyLongPressed) {
3418 mAssistKeyLongPressed = false;
3421 launchAssistAction(null, event.getDeviceId());
3426 } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
3430 voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
3432 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
3433 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
3436 dic.exitIdle("voice-search");
3437 } catch (RemoteException e) {
3440 voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
3441 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
3443 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
3445 } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
3446 if (down && repeatCount == 0) {
3447 mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
3448 mHandler.post(mScreenshotRunnable);
3451 } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP
3452 || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) {
3454 int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
3456 // Disable autobrightness if it's on
3457 int auto = Settings.System.getIntForUser(
3458 mContext.getContentResolver(),
3459 Settings.System.SCREEN_BRIGHTNESS_MODE,
3460 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3461 UserHandle.USER_CURRENT_OR_SELF);
3463 Settings.System.putIntForUser(mContext.getContentResolver(),
3464 Settings.System.SCREEN_BRIGHTNESS_MODE,
3465 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3466 UserHandle.USER_CURRENT_OR_SELF);
3469 int min = mPowerManager.getMinimumScreenBrightnessSetting();
3470 int max = mPowerManager.getMaximumScreenBrightnessSetting();
3471 int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction;
3472 int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
3473 Settings.System.SCREEN_BRIGHTNESS,
3474 mPowerManager.getDefaultScreenBrightnessSetting(),
3475 UserHandle.USER_CURRENT_OR_SELF);
3477 // Make sure we don't go beyond the limits.
3478 brightness = Math.min(max, brightness);
3479 brightness = Math.max(min, brightness);
3481 Settings.System.putIntForUser(mContext.getContentResolver(),
3482 Settings.System.SCREEN_BRIGHTNESS, brightness,
3483 UserHandle.USER_CURRENT_OR_SELF);
3484 startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
3485 UserHandle.CURRENT_OR_SELF);
3488 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
3489 || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3490 || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
3491 if (mUseTvRouting) {
3492 // On TVs volume keys never go to the foreground app.
3493 dispatchDirectAudioEvent(event);
3496 } else if (keyCode == KeyEvent.KEYCODE_TAB && event.isMetaPressed()) {
3497 // Pass through keyboard navigation keys.
3499 } else if (mHasFeatureLeanback && interceptBugreportGestureTv(keyCode, down)) {
3503 // Toggle Caps Lock on META-ALT.
3504 boolean actionTriggered = false;
3505 if (KeyEvent.isModifierKey(keyCode)) {
3506 if (!mPendingCapsLockToggle) {
3507 // Start tracking meta state for combo.
3508 mInitialMetaState = mMetaState;
3509 mPendingCapsLockToggle = true;
3510 } else if (event.getAction() == KeyEvent.ACTION_UP) {
3511 int altOnMask = mMetaState & KeyEvent.META_ALT_MASK;
3512 int metaOnMask = mMetaState & KeyEvent.META_META_MASK;
3514 // Check for Caps Lock toggle
3515 if ((metaOnMask != 0) && (altOnMask != 0)) {
3516 // Check if nothing else is pressed
3517 if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) {
3518 // Handle Caps Lock Toggle
3519 mInputManagerInternal.toggleCapsLock(event.getDeviceId());
3520 actionTriggered = true;
3524 // Always stop tracking when key goes up.
3525 mPendingCapsLockToggle = false;
3528 // Store current meta state to be able to evaluate it later.
3529 mMetaState = metaState;
3531 if (actionTriggered) {
3535 if (KeyEvent.isMetaKey(keyCode)) {
3537 mPendingMetaAction = true;
3538 } else if (mPendingMetaAction) {
3539 launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId());
3544 // Shortcuts are invoked through Search+key, so intercept those here
3545 // Any printing key that is chorded with Search should be consumed
3546 // even if no shortcut was invoked. This prevents text from being
3547 // inadvertently inserted when using a keyboard that has built-in macro
3548 // shortcut keys (that emit Search+x) and some of them are not registered.
3549 if (mSearchKeyShortcutPending) {
3550 final KeyCharacterMap kcm = event.getKeyCharacterMap();
3551 if (kcm.isPrintingKey(keyCode)) {
3552 mConsumeSearchKeyUp = true;
3553 mSearchKeyShortcutPending = false;
3554 if (down && repeatCount == 0 && !keyguardOn) {
3555 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
3556 if (shortcutIntent != null) {
3557 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3559 startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3560 dismissKeyboardShortcutsMenu();
3561 } catch (ActivityNotFoundException ex) {
3562 Slog.w(TAG, "Dropping shortcut key combination because "
3563 + "the activity to which it is registered was not found: "
3564 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);
3567 Slog.i(TAG, "Dropping unregistered shortcut key combination: "
3568 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));
3575 // Invoke shortcuts using Meta.
3576 if (down && repeatCount == 0 && !keyguardOn
3577 && (metaState & KeyEvent.META_META_ON) != 0) {
3578 final KeyCharacterMap kcm = event.getKeyCharacterMap();
3579 if (kcm.isPrintingKey(keyCode)) {
3580 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
3581 metaState & ~(KeyEvent.META_META_ON
3582 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
3583 if (shortcutIntent != null) {
3584 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3586 startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3587 dismissKeyboardShortcutsMenu();
3588 } catch (ActivityNotFoundException ex) {
3589 Slog.w(TAG, "Dropping shortcut key combination because "
3590 + "the activity to which it is registered was not found: "
3591 + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
3598 // Handle application launch keys.
3599 if (down && repeatCount == 0 && !keyguardOn) {
3600 String category = sApplicationLaunchKeyCategories.get(keyCode);
3601 if (category != null) {
3602 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
3603 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3605 startActivityAsUser(intent, UserHandle.CURRENT);
3606 dismissKeyboardShortcutsMenu();
3607 } catch (ActivityNotFoundException ex) {
3608 Slog.w(TAG, "Dropping application launch key because "
3609 + "the activity to which it is registered was not found: "
3610 + "keyCode=" + keyCode + ", category=" + category, ex);
3616 // Display task switcher for ALT-TAB.
3617 if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
3618 if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
3619 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
3620 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
3621 mRecentAppsHeldModifiers = shiftlessModifiers;
3622 showRecentApps(true, false);
3626 } else if (!down && mRecentAppsHeldModifiers != 0
3627 && (metaState & mRecentAppsHeldModifiers) == 0) {
3628 mRecentAppsHeldModifiers = 0;
3629 hideRecentApps(true, false);
3632 // Handle input method switching.
3633 if (down && repeatCount == 0
3634 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3635 || (keyCode == KeyEvent.KEYCODE_SPACE
3636 && (metaState & KeyEvent.META_META_MASK) != 0))) {
3637 final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0;
3638 mWindowManagerFuncs.switchInputMethod(forwardDirection);
3641 if (mLanguageSwitchKeyPressed && !down
3642 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3643 || keyCode == KeyEvent.KEYCODE_SPACE)) {
3644 mLanguageSwitchKeyPressed = false;
3648 if (isValidGlobalKey(keyCode)
3649 && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
3654 long shortcutCode = keyCode;
3655 if (event.isCtrlPressed()) {
3656 shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
3659 if (event.isAltPressed()) {
3660 shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
3663 if (event.isShiftPressed()) {
3664 shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
3667 if (event.isMetaPressed()) {
3668 shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE;
3671 IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode);
3672 if (shortcutService != null) {
3674 if (isUserSetupComplete()) {
3675 shortcutService.notifyShortcutKeyPressed(shortcutCode);
3677 } catch (RemoteException e) {
3678 mShortcutKeyServices.delete(shortcutCode);
3684 // Reserve all the META modifier combos for system behavior
3685 if ((metaState & KeyEvent.META_META_ON) != 0) {
3689 // Let the application handle the key.
3694 * TV only: recognizes a remote control gesture for capturing a bug report.
3696 private boolean interceptBugreportGestureTv(int keyCode, boolean down) {
3697 // The bugreport capture chord is a long press on DPAD CENTER and BACK simultaneously.
3698 if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
3699 mBugreportTvKey1Pressed = down;
3700 } else if (keyCode == KeyEvent.KEYCODE_BACK) {
3701 mBugreportTvKey2Pressed = down;
3704 if (mBugreportTvKey1Pressed && mBugreportTvKey2Pressed) {
3705 if (!mBugreportTvScheduled) {
3706 mBugreportTvScheduled = true;
3707 Message msg = Message.obtain(mHandler, MSG_BUGREPORT_TV);
3708 msg.setAsynchronous(true);
3709 mHandler.sendMessageDelayed(msg, BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS);
3711 } else if (mBugreportTvScheduled) {
3712 mHandler.removeMessages(MSG_BUGREPORT_TV);
3713 mBugreportTvScheduled = false;
3716 return mBugreportTvScheduled;
3719 private void takeBugreport() {
3720 if ("1".equals(SystemProperties.get("ro.debuggable"))
3721 || Settings.Global.getInt(mContext.getContentResolver(),
3722 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) == 1) {
3724 ActivityManager.getService()
3725 .requestBugReport(ActivityManager.BUGREPORT_OPTION_INTERACTIVE);
3726 } catch (RemoteException e) {
3727 Slog.e(TAG, "Error taking bugreport", e);
3732 /** {@inheritDoc} */
3734 public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
3735 // Note: This method is only called if the initial down was unhandled.
3737 Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
3738 + ", flags=" + event.getFlags()
3739 + ", keyCode=" + event.getKeyCode()
3740 + ", scanCode=" + event.getScanCode()
3741 + ", metaState=" + event.getMetaState()
3742 + ", repeatCount=" + event.getRepeatCount()
3743 + ", policyFlags=" + policyFlags);
3746 KeyEvent fallbackEvent = null;
3747 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3748 final KeyCharacterMap kcm = event.getKeyCharacterMap();
3749 final int keyCode = event.getKeyCode();
3750 final int metaState = event.getMetaState();
3751 final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
3752 && event.getRepeatCount() == 0;
3754 // Check for fallback actions specified by the key character map.
3755 final FallbackAction fallbackAction;
3757 fallbackAction = kcm.getFallbackAction(keyCode, metaState);
3759 fallbackAction = mFallbackActions.get(keyCode);
3762 if (fallbackAction != null) {
3764 Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode
3765 + " metaState=" + Integer.toHexString(fallbackAction.metaState));
3768 final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
3769 fallbackEvent = KeyEvent.obtain(
3770 event.getDownTime(), event.getEventTime(),
3771 event.getAction(), fallbackAction.keyCode,
3772 event.getRepeatCount(), fallbackAction.metaState,
3773 event.getDeviceId(), event.getScanCode(),
3774 flags, event.getSource(), null);
3776 if (!interceptFallback(win, fallbackEvent, policyFlags)) {
3777 fallbackEvent.recycle();
3778 fallbackEvent = null;
3782 mFallbackActions.put(keyCode, fallbackAction);
3783 } else if (event.getAction() == KeyEvent.ACTION_UP) {
3784 mFallbackActions.remove(keyCode);
3785 fallbackAction.recycle();
3791 if (fallbackEvent == null) {
3792 Slog.d(TAG, "No fallback.");
3794 Slog.d(TAG, "Performing fallback: " + fallbackEvent);
3797 return fallbackEvent;
3800 private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
3801 int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
3802 if ((actions & ACTION_PASS_TO_USER) != 0) {
3803 long delayMillis = interceptKeyBeforeDispatching(
3804 win, fallbackEvent, policyFlags);
3805 if (delayMillis == 0) {
3813 public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
3814 throws RemoteException {
3815 synchronized (mLock) {
3816 IShortcutService service = mShortcutKeyServices.get(shortcutCode);
3817 if (service != null && service.asBinder().pingBinder()) {
3818 throw new RemoteException("Key already exists.");
3821 mShortcutKeyServices.put(shortcutCode, shortcutService);
3826 public void onKeyguardOccludedChangedLw(boolean occluded) {
3827 if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
3828 mPendingKeyguardOccluded = occluded;
3829 mKeyguardOccludedChanged = true;
3831 setKeyguardOccludedLw(occluded);
3835 private int handleStartTransitionForKeyguardLw(int transit, @Nullable Animation anim) {
3836 if (mKeyguardOccludedChanged) {
3837 if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded="
3838 + mPendingKeyguardOccluded);
3839 mKeyguardOccludedChanged = false;
3840 if (setKeyguardOccludedLw(mPendingKeyguardOccluded)) {
3841 return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER;
3844 if (AppTransition.isKeyguardGoingAwayTransit(transit)) {
3845 if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation");
3846 final long startTime = anim != null
3847 ? SystemClock.uptimeMillis() + anim.getStartOffset()
3848 : SystemClock.uptimeMillis();
3849 final long duration = anim != null
3850 ? anim.getDuration()
3852 startKeyguardExitAnimation(startTime, duration);
3857 private void launchAssistLongPressAction() {
3858 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
3859 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
3861 // launch the search activity
3862 Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
3863 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3865 // TODO: This only stops the factory-installed search manager.
3866 // Need to formalize an API to handle others
3867 SearchManager searchManager = getSearchManager();
3868 if (searchManager != null) {
3869 searchManager.stopSearch();
3871 startActivityAsUser(intent, UserHandle.CURRENT);
3872 } catch (ActivityNotFoundException e) {
3873 Slog.w(TAG, "No activity to handle assist long press action.", e);
3877 private void launchAssistAction(String hint, int deviceId) {
3878 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
3879 if (!isUserSetupComplete()) {
3880 // Disable opening assist window during setup
3884 if (deviceId > Integer.MIN_VALUE) {
3885 args = new Bundle();
3886 args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
3888 if ((mContext.getResources().getConfiguration().uiMode
3889 & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
3890 // On TV, use legacy handling until assistants are implemented in the proper way.
3891 ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
3892 .launchLegacyAssist(hint, UserHandle.myUserId(), args);
3896 args = new Bundle();
3898 args.putBoolean(hint, true);
3900 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3901 if (statusbar != null) {
3902 statusbar.startAssist(args);
3907 private void startActivityAsUser(Intent intent, UserHandle handle) {
3908 if (isUserSetupComplete()) {
3909 mContext.startActivityAsUser(intent, handle);
3911 Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent);
3915 private SearchManager getSearchManager() {
3916 if (mSearchManager == null) {
3917 mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
3919 return mSearchManager;
3922 private void preloadRecentApps() {
3923 mPreloadedRecentApps = true;
3924 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3925 if (statusbar != null) {
3926 statusbar.preloadRecentApps();
3930 private void cancelPreloadRecentApps() {
3931 if (mPreloadedRecentApps) {
3932 mPreloadedRecentApps = false;
3933 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3934 if (statusbar != null) {
3935 statusbar.cancelPreloadRecentApps();
3940 private void toggleRecentApps() {
3941 mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3942 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3943 if (statusbar != null) {
3944 statusbar.toggleRecentApps();
3949 public void showRecentApps(boolean fromHome) {
3950 mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
3951 mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget();
3954 private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
3955 mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3956 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3957 if (statusbar != null) {
3958 statusbar.showRecentApps(triggeredFromAltTab, fromHome);
3962 private void toggleKeyboardShortcutsMenu(int deviceId) {
3963 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3964 if (statusbar != null) {
3965 statusbar.toggleKeyboardShortcutsMenu(deviceId);
3969 private void dismissKeyboardShortcutsMenu() {
3970 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3971 if (statusbar != null) {
3972 statusbar.dismissKeyboardShortcutsMenu();
3976 private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
3977 mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3978 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3979 if (statusbar != null) {
3980 statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
3984 void launchHomeFromHotKey() {
3985 launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/);
3989 * A home key -> launch home action was detected. Take the appropriate action
3990 * given the situation with the keyguard.
3992 void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) {
3993 if (respectKeyguard) {
3994 if (isKeyguardShowingAndNotOccluded()) {
3995 // don't launch home if keyguard showing
3999 if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) {
4000 // when in keyguard restricted mode, must first verify unlock
4001 // before launching home
4002 mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
4004 public void onKeyguardExitResult(boolean success) {
4007 ActivityManager.getService().stopAppSwitches();
4008 } catch (RemoteException e) {
4010 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
4011 startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
4019 // no keyguard stuff to worry about, just launch home!
4021 ActivityManager.getService().stopAppSwitches();
4022 } catch (RemoteException e) {
4024 if (mRecentsVisible) {
4025 // Hide Recents and notify it to launch Home
4026 if (awakenFromDreams) {
4029 hideRecentApps(false, true);
4031 // Otherwise, just launch Home
4032 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
4033 startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
4037 private final Runnable mClearHideNavigationFlag = new Runnable() {
4040 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
4042 mForceClearedSystemUiFlags &=
4043 ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
4045 mWindowManagerFuncs.reevaluateStatusBarVisibility();
4050 * Input handler used while nav bar is hidden. Captures any touch on the screen,
4051 * to determine when the nav bar should be shown and prevent applications from
4052 * receiving those touches.
4054 final class HideNavInputEventReceiver extends InputEventReceiver {
4055 public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
4056 super(inputChannel, looper);
4060 public void onInputEvent(InputEvent event) {
4061 boolean handled = false;
4063 if (event instanceof MotionEvent
4064 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
4065 final MotionEvent motionEvent = (MotionEvent)event;
4066 if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
4067 // When the user taps down, we re-show the nav bar.
4068 boolean changed = false;
4069 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
4070 if (mInputConsumer == null) {
4073 // Any user activity always causes us to show the
4074 // navigation controls, if they had been hidden.
4075 // We also clear the low profile and only content
4076 // flags so that tapping on the screen will atomically
4077 // restore all currently hidden screen decorations.
4078 int newVal = mResettingSystemUiFlags |
4079 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
4080 View.SYSTEM_UI_FLAG_LOW_PROFILE |
4081 View.SYSTEM_UI_FLAG_FULLSCREEN;
4082 if (mResettingSystemUiFlags != newVal) {
4083 mResettingSystemUiFlags = newVal;
4086 // We don't allow the system's nav bar to be hidden
4087 // again for 1 second, to prevent applications from
4088 // spamming us and keeping it from being shown.
4089 newVal = mForceClearedSystemUiFlags |
4090 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
4091 if (mForceClearedSystemUiFlags != newVal) {
4092 mForceClearedSystemUiFlags = newVal;
4094 mHandler.postDelayed(mClearHideNavigationFlag, 1000);
4098 mWindowManagerFuncs.reevaluateStatusBarVisibility();
4103 finishInputEvent(event, handled);
4109 public void setRecentsVisibilityLw(boolean visible) {
4110 mRecentsVisible = visible;
4114 public void setTvPipVisibilityLw(boolean visible) {
4115 mTvPictureInPictureVisible = visible;
4119 public int adjustSystemUiVisibilityLw(int visibility) {
4120 mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4121 mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4123 // Reset any bits in mForceClearingStatusBarVisibility that
4125 mResettingSystemUiFlags &= visibility;
4126 // Clear any bits in the new visibility that are currently being
4127 // force cleared, before reporting it.
4128 return visibility & ~mResettingSystemUiFlags
4129 & ~mForceClearedSystemUiFlags;
4133 public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
4134 int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets,
4135 Rect outStableInsets, Rect outOutsets) {
4136 final int fl = PolicyControl.getWindowFlags(null, attrs);
4137 final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
4138 final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
4140 final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
4142 int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
4144 if (displayRotation == Surface.ROTATION_0) {
4145 outOutsets.bottom += outset;
4146 } else if (displayRotation == Surface.ROTATION_90) {
4147 outOutsets.right += outset;
4148 } else if (displayRotation == Surface.ROTATION_180) {
4149 outOutsets.top += outset;
4150 } else if (displayRotation == Surface.ROTATION_270) {
4151 outOutsets.left += outset;
4156 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4157 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4158 int availRight, availBottom;
4159 if (canHideNavigationBar() &&
4160 (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
4161 availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4162 availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4164 availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
4165 availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4167 if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4168 if ((fl & FLAG_FULLSCREEN) != 0) {
4169 outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop,
4170 availRight - mStableFullscreenRight,
4171 availBottom - mStableFullscreenBottom);
4173 outContentInsets.set(mStableLeft, mStableTop,
4174 availRight - mStableRight, availBottom - mStableBottom);
4176 } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
4177 outContentInsets.setEmpty();
4178 } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
4179 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
4180 outContentInsets.set(mCurLeft, mCurTop,
4181 availRight - mCurRight, availBottom - mCurBottom);
4183 outContentInsets.set(mCurLeft, mCurTop,
4184 availRight - mCurRight, availBottom - mCurBottom);
4187 outStableInsets.set(mStableLeft, mStableTop,
4188 availRight - mStableRight, availBottom - mStableBottom);
4189 if (taskBounds != null) {
4190 calculateRelevantTaskInsets(taskBounds, outContentInsets,
4191 displayWidth, displayHeight);
4192 calculateRelevantTaskInsets(taskBounds, outStableInsets,
4193 displayWidth, displayHeight);
4195 return mForceShowSystemBars;
4197 outContentInsets.setEmpty();
4198 outStableInsets.setEmpty();
4199 return mForceShowSystemBars;
4203 * For any given task bounds, the insets relevant for these bounds given the insets relevant
4204 * for the entire display.
4206 private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth,
4207 int displayHeight) {
4208 mTmpRect.set(0, 0, displayWidth, displayHeight);
4209 mTmpRect.inset(inOutInsets);
4210 mTmpRect.intersect(taskBounds);
4211 int leftInset = mTmpRect.left - taskBounds.left;
4212 int topInset = mTmpRect.top - taskBounds.top;
4213 int rightInset = taskBounds.right - mTmpRect.right;
4214 int bottomInset = taskBounds.bottom - mTmpRect.bottom;
4215 inOutInsets.set(leftInset, topInset, rightInset, bottomInset);
4218 private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
4219 return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
4220 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
4223 /** {@inheritDoc} */
4225 public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
4226 int displayRotation, int uiMode) {
4227 mDisplayRotation = displayRotation;
4228 final int overscanLeft, overscanTop, overscanRight, overscanBottom;
4229 if (isDefaultDisplay) {
4230 switch (displayRotation) {
4231 case Surface.ROTATION_90:
4232 overscanLeft = mOverscanTop;
4233 overscanTop = mOverscanRight;
4234 overscanRight = mOverscanBottom;
4235 overscanBottom = mOverscanLeft;
4237 case Surface.ROTATION_180:
4238 overscanLeft = mOverscanRight;
4239 overscanTop = mOverscanBottom;
4240 overscanRight = mOverscanLeft;
4241 overscanBottom = mOverscanTop;
4243 case Surface.ROTATION_270:
4244 overscanLeft = mOverscanBottom;
4245 overscanTop = mOverscanLeft;
4246 overscanRight = mOverscanTop;
4247 overscanBottom = mOverscanRight;
4250 overscanLeft = mOverscanLeft;
4251 overscanTop = mOverscanTop;
4252 overscanRight = mOverscanRight;
4253 overscanBottom = mOverscanBottom;
4262 mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0;
4263 mOverscanScreenTop = mRestrictedOverscanScreenTop = 0;
4264 mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth;
4265 mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight;
4268 mSystemRight = displayWidth;
4269 mSystemBottom = displayHeight;
4270 mUnrestrictedScreenLeft = overscanLeft;
4271 mUnrestrictedScreenTop = overscanTop;
4272 mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight;
4273 mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom;
4274 mRestrictedScreenLeft = mUnrestrictedScreenLeft;
4275 mRestrictedScreenTop = mUnrestrictedScreenTop;
4276 mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth;
4277 mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight;
4278 mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft
4279 = mCurLeft = mUnrestrictedScreenLeft;
4280 mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop
4281 = mCurTop = mUnrestrictedScreenTop;
4282 mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight
4283 = mCurRight = displayWidth - overscanRight;
4284 mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom
4285 = mCurBottom = displayHeight - overscanBottom;
4286 mDockLayer = 0x10000000;
4287 mStatusBarLayer = -1;
4289 // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
4290 final Rect pf = mTmpParentFrame;
4291 final Rect df = mTmpDisplayFrame;
4292 final Rect of = mTmpOverscanFrame;
4293 final Rect vf = mTmpVisibleFrame;
4294 final Rect dcf = mTmpDecorFrame;
4295 pf.left = df.left = of.left = vf.left = mDockLeft;
4296 pf.top = df.top = of.top = vf.top = mDockTop;
4297 pf.right = df.right = of.right = vf.right = mDockRight;
4298 pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom;
4299 dcf.setEmpty(); // Decor frame N/A for system bars.
4301 if (isDefaultDisplay) {
4302 // For purposes of putting out fake window up to steal focus, we will
4303 // drive nav being hidden only by whether it is requested.
4304 final int sysui = mLastSystemUiFlags;
4305 boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
4306 boolean navTranslucent = (sysui
4307 & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
4308 boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
4309 boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
4310 boolean navAllowedHidden = immersive || immersiveSticky;
4311 navTranslucent &= !immersiveSticky; // transient trumps translucent
4312 boolean isKeyguardShowing = isStatusBarKeyguard() && !mKeyguardOccluded;
4313 if (!isKeyguardShowing) {
4314 navTranslucent &= areTranslucentBarsAllowed();
4316 boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null
4317 && mStatusBar.getAttrs().height == MATCH_PARENT
4318 && mStatusBar.getAttrs().width == MATCH_PARENT;
4320 // When the navigation bar isn't visible, we put up a fake
4321 // input window to catch all touch events. This way we can
4322 // detect when the user presses anywhere to bring back the nav
4323 // bar and ensure the application doesn't see the event.
4324 if (navVisible || navAllowedHidden) {
4325 if (mInputConsumer != null) {
4326 mHandler.sendMessage(
4327 mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
4328 mInputConsumer = null;
4330 } else if (mInputConsumer == null) {
4331 mInputConsumer = mWindowManagerFuncs.createInputConsumer(mHandler.getLooper(),
4332 INPUT_CONSUMER_NAVIGATION,
4333 (channel, looper) -> new HideNavInputEventReceiver(channel, looper));
4334 // As long as mInputConsumer is active, hover events are not dispatched to the app
4335 // and the pointer icon is likely to become stale. Hide it to avoid confusion.
4336 InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL);
4339 // For purposes of positioning and showing the nav bar, if we have
4340 // decided that it can't be hidden (because of the screen aspect ratio),
4341 // then take that into account.
4342 navVisible |= !canHideNavigationBar();
4344 boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight,
4345 displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom, dcf, navVisible, navTranslucent,
4346 navAllowedHidden, statusBarExpandedNotKeyguard);
4347 if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
4348 mDockLeft, mDockTop, mDockRight, mDockBottom));
4349 updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing);
4350 if (updateSysUiVisibility) {
4351 updateSystemUiVisibilityLw();
4356 private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui,
4357 boolean isKeyguardShowing) {
4358 // decide where the status bar goes ahead of time
4359 if (mStatusBar != null) {
4360 // apply any navigation bar insets
4361 pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4362 pf.top = df.top = of.top = mUnrestrictedScreenTop;
4363 pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4364 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
4365 + mUnrestrictedScreenTop;
4366 vf.left = mStableLeft;
4367 vf.top = mStableTop;
4368 vf.right = mStableRight;
4369 vf.bottom = mStableBottom;
4371 mStatusBarLayer = mStatusBar.getSurfaceLayer();
4373 // Let the status bar determine its size.
4374 mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
4375 vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
4376 dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */);
4378 // For layout, the status bar is always at the top with our fixed height.
4379 mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
4381 boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
4382 boolean statusBarTranslucent = (sysui
4383 & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
4384 if (!isKeyguardShowing) {
4385 statusBarTranslucent &= areTranslucentBarsAllowed();
4388 // If the status bar is hidden, we don't want to cause
4389 // windows behind it to scroll.
4390 if (mStatusBar.isVisibleLw() && !statusBarTransient) {
4391 // Status bar may go away, so the screen area it occupies
4392 // is available to apps but just covering them when the
4393 // status bar is visible.
4394 mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
4396 mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4397 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4398 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4399 mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4401 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " +
4403 "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
4404 mDockLeft, mDockTop, mDockRight, mDockBottom,
4405 mContentLeft, mContentTop, mContentRight, mContentBottom,
4406 mCurLeft, mCurTop, mCurRight, mCurBottom));
4408 if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
4409 && !statusBarTransient && !statusBarTranslucent
4410 && !mStatusBarController.wasRecentlyTranslucent()) {
4411 // If the opaque status bar is currently requested to be visible,
4412 // and not in the process of animating on or off, then
4413 // we can tell the app that it is covered by it.
4414 mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
4416 if (mStatusBarController.checkHiddenLw()) {
4423 private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation,
4424 int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf,
4425 boolean navVisible, boolean navTranslucent, boolean navAllowedHidden,
4426 boolean statusBarExpandedNotKeyguard) {
4427 if (mNavigationBar != null) {
4428 boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
4429 // Force the navigation bar to its appropriate place and
4430 // size. We need to do this directly, instead of relying on
4431 // it to bubble up from the nav bar, because this needs to
4432 // change atomically with screen rotations.
4433 mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight,
4435 if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
4436 // It's a system nav bar or a portrait screen; nav bar goes on bottom.
4437 int top = displayHeight - overscanBottom
4438 - getNavigationBarHeight(displayRotation, uiMode);
4439 mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
4440 mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
4441 if (transientNavBarShowing) {
4442 mNavigationBarController.setBarShowingLw(true);
4443 } else if (navVisible) {
4444 mNavigationBarController.setBarShowingLw(true);
4445 mDockBottom = mTmpNavigationFrame.top;
4446 mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
4447 mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
4449 // We currently want to hide the navigation UI - unless we expanded the status
4451 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4453 if (navVisible && !navTranslucent && !navAllowedHidden
4454 && !mNavigationBar.isAnimatingLw()
4455 && !mNavigationBarController.wasRecentlyTranslucent()) {
4456 // If the opaque nav bar is currently requested to be visible,
4457 // and not in the process of animating on or off, then
4458 // we can tell the app that it is covered by it.
4459 mSystemBottom = mTmpNavigationFrame.top;
4461 } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4462 // Landscape screen; nav bar goes to the right.
4463 int left = displayWidth - overscanRight
4464 - getNavigationBarWidth(displayRotation, uiMode);
4465 mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
4466 mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
4467 if (transientNavBarShowing) {
4468 mNavigationBarController.setBarShowingLw(true);
4469 } else if (navVisible) {
4470 mNavigationBarController.setBarShowingLw(true);
4471 mDockRight = mTmpNavigationFrame.left;
4472 mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4473 mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4475 // We currently want to hide the navigation UI - unless we expanded the status
4477 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4479 if (navVisible && !navTranslucent && !navAllowedHidden
4480 && !mNavigationBar.isAnimatingLw()
4481 && !mNavigationBarController.wasRecentlyTranslucent()) {
4482 // If the nav bar is currently requested to be visible,
4483 // and not in the process of animating on or off, then
4484 // we can tell the app that it is covered by it.
4485 mSystemRight = mTmpNavigationFrame.left;
4487 } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4488 // Seascape screen; nav bar goes to the left.
4489 int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode);
4490 mTmpNavigationFrame.set(overscanLeft, 0, right, displayHeight);
4491 mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right;
4492 if (transientNavBarShowing) {
4493 mNavigationBarController.setBarShowingLw(true);
4494 } else if (navVisible) {
4495 mNavigationBarController.setBarShowingLw(true);
4496 mDockLeft = mTmpNavigationFrame.right;
4497 // TODO: not so sure about those:
4498 mRestrictedScreenLeft = mRestrictedOverscanScreenLeft = mDockLeft;
4499 mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4500 mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4502 // We currently want to hide the navigation UI - unless we expanded the status
4504 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4506 if (navVisible && !navTranslucent && !navAllowedHidden
4507 && !mNavigationBar.isAnimatingLw()
4508 && !mNavigationBarController.wasRecentlyTranslucent()) {
4509 // If the nav bar is currently requested to be visible,
4510 // and not in the process of animating on or off, then
4511 // we can tell the app that it is covered by it.
4512 mSystemLeft = mTmpNavigationFrame.right;
4515 // Make sure the content and current rectangles are updated to
4516 // account for the restrictions from the navigation bar.
4517 mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4518 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4519 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4520 mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4521 mStatusBarLayer = mNavigationBar.getSurfaceLayer();
4522 // And compute the final frame.
4523 mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
4524 mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
4525 mTmpNavigationFrame, mTmpNavigationFrame);
4526 if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
4527 if (mNavigationBarController.checkHiddenLw()) {
4534 private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
4535 if (mNavigationBarCanMove && displayWidth > displayHeight) {
4536 if (displayRotation == Surface.ROTATION_270) {
4537 return NAV_BAR_LEFT;
4539 return NAV_BAR_RIGHT;
4542 return NAV_BAR_BOTTOM;
4545 /** {@inheritDoc} */
4547 public int getSystemDecorLayerLw() {
4548 if (mStatusBar != null && mStatusBar.isVisibleLw()) {
4549 return mStatusBar.getSurfaceLayer();
4552 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) {
4553 return mNavigationBar.getSurfaceLayer();
4560 public void getContentRectLw(Rect r) {
4561 r.set(mContentLeft, mContentTop, mContentRight, mContentBottom);
4564 void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
4565 boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
4566 if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
4567 // Here's a special case: if this attached window is a panel that is
4568 // above the dock window, and the window it is attached to is below
4569 // the dock window, then the frames we computed for the window it is
4570 // attached to can not be used because the dock is effectively part
4571 // of the underlying window and the attached window is floating on top
4572 // of the whole thing. So, we ignore the attached window and explicitly
4573 // compute the frames that would be appropriate without the dock.
4574 df.left = of.left = cf.left = vf.left = mDockLeft;
4575 df.top = of.top = cf.top = vf.top = mDockTop;
4576 df.right = of.right = cf.right = vf.right = mDockRight;
4577 df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom;
4579 // The effective display frame of the attached window depends on
4580 // whether it is taking care of insetting its content. If not,
4581 // we need to use the parent's content frame so that the entire
4582 // window is positioned within that content. Otherwise we can use
4583 // the overscan frame and let the attached window take care of
4584 // positioning its content appropriately.
4585 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4586 // Set the content frame of the attached window to the parent's decor frame
4587 // (same as content frame when IME isn't present) if specifically requested by
4588 // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
4589 // Otherwise, use the overscan frame.
4590 cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
4591 ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
4593 // If the window is resizing, then we want to base the content
4594 // frame on our attached content frame to resize... however,
4595 // things can be tricky if the attached window is NOT in resize
4596 // mode, in which case its content frame will be larger.
4597 // Ungh. So to deal with that, make sure the content frame
4598 // we end up using is not covering the IM dock.
4599 cf.set(attached.getContentFrameLw());
4600 if (attached.isVoiceInteraction()) {
4601 if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft;
4602 if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop;
4603 if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight;
4604 if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom;
4605 } else if (attached.getSurfaceLayer() < mDockLayer) {
4606 if (cf.left < mContentLeft) cf.left = mContentLeft;
4607 if (cf.top < mContentTop) cf.top = mContentTop;
4608 if (cf.right > mContentRight) cf.right = mContentRight;
4609 if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
4612 df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
4613 of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
4614 vf.set(attached.getVisibleFrameLw());
4616 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
4617 // window should be positioned relative to its parent or the entire
4619 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
4620 ? attached.getFrameLw() : df);
4623 private void applyStableConstraints(int sysui, int fl, Rect r) {
4624 if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4625 // If app is requesting a stable layout, don't let the
4626 // content insets go below the stable values.
4627 if ((fl & FLAG_FULLSCREEN) != 0) {
4628 if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft;
4629 if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop;
4630 if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight;
4631 if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom;
4633 if (r.left < mStableLeft) r.left = mStableLeft;
4634 if (r.top < mStableTop) r.top = mStableTop;
4635 if (r.right > mStableRight) r.right = mStableRight;
4636 if (r.bottom > mStableBottom) r.bottom = mStableBottom;
4641 private boolean canReceiveInput(WindowState win) {
4642 boolean notFocusable =
4643 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
4644 boolean altFocusableIm =
4645 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
4646 boolean notFocusableForIm = notFocusable ^ altFocusableIm;
4647 return !notFocusableForIm;
4650 /** {@inheritDoc} */
4652 public void layoutWindowLw(WindowState win, WindowState attached) {
4653 // We've already done the navigation bar and status bar. If the status bar can receive
4654 // input, we need to layout it again to accomodate for the IME window.
4655 if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) {
4658 final WindowManager.LayoutParams attrs = win.getAttrs();
4659 final boolean isDefaultDisplay = win.isDefaultDisplay();
4660 final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
4661 (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
4662 if (needsToOffsetInputMethodTarget) {
4663 if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
4664 offsetInputMethodWindowLw(mLastInputMethodWindow);
4667 final int fl = PolicyControl.getWindowFlags(win, attrs);
4668 final int pfl = attrs.privateFlags;
4669 final int sim = attrs.softInputMode;
4670 final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
4672 final Rect pf = mTmpParentFrame;
4673 final Rect df = mTmpDisplayFrame;
4674 final Rect of = mTmpOverscanFrame;
4675 final Rect cf = mTmpContentFrame;
4676 final Rect vf = mTmpVisibleFrame;
4677 final Rect dcf = mTmpDecorFrame;
4678 final Rect sf = mTmpStableFrame;
4682 final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
4683 && mNavigationBar != null && mNavigationBar.isVisibleLw());
4685 final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
4687 if (isDefaultDisplay) {
4688 sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom);
4690 sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom);
4693 if (!isDefaultDisplay) {
4694 if (attached != null) {
4695 // If this window is attached to another, our display
4696 // frame is the same as the one we are attached to.
4697 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4699 // Give the window full screen.
4700 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4701 pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4702 pf.right = df.right = of.right = cf.right
4703 = mOverscanScreenLeft + mOverscanScreenWidth;
4704 pf.bottom = df.bottom = of.bottom = cf.bottom
4705 = mOverscanScreenTop + mOverscanScreenHeight;
4707 } else if (attrs.type == TYPE_INPUT_METHOD) {
4708 pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
4709 pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
4710 pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
4711 // IM dock windows layout below the nav bar...
4712 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4713 // ...with content insets above the nav bar
4714 cf.bottom = vf.bottom = mStableBottom;
4715 if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
4716 // The status bar forces the navigation bar while it's visible. Make sure the IME
4717 // avoids the navigation bar in that case.
4718 if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4719 pf.right = df.right = of.right = cf.right = vf.right = mStableRight;
4720 } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4721 pf.left = df.left = of.left = cf.left = vf.left = mStableLeft;
4724 // IM dock windows always go to the bottom of the screen.
4725 attrs.gravity = Gravity.BOTTOM;
4726 mDockLayer = win.getSurfaceLayer();
4727 } else if (attrs.type == TYPE_VOICE_INTERACTION) {
4728 pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4729 pf.top = df.top = of.top = mUnrestrictedScreenTop;
4730 pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4731 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4732 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4733 cf.left = mDockLeft;
4735 cf.right = mDockRight;
4736 cf.bottom = mDockBottom;
4738 cf.left = mContentLeft;
4739 cf.top = mContentTop;
4740 cf.right = mContentRight;
4741 cf.bottom = mContentBottom;
4743 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4746 vf.right = mCurRight;
4747 vf.bottom = mCurBottom;
4751 } else if (attrs.type == TYPE_WALLPAPER) {
4752 layoutWallpaper(win, pf, df, of, cf);
4753 } else if (win == mStatusBar) {
4754 pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4755 pf.top = df.top = of.top = mUnrestrictedScreenTop;
4756 pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4757 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop;
4758 cf.left = vf.left = mStableLeft;
4759 cf.top = vf.top = mStableTop;
4760 cf.right = vf.right = mStableRight;
4761 vf.bottom = mStableBottom;
4763 if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
4764 cf.bottom = mContentBottom;
4766 cf.bottom = mDockBottom;
4767 vf.bottom = mContentBottom;
4771 // Default policy decor for the default display
4772 dcf.left = mSystemLeft;
4773 dcf.top = mSystemTop;
4774 dcf.right = mSystemRight;
4775 dcf.bottom = mSystemBottom;
4776 final boolean inheritTranslucentDecor = (attrs.privateFlags
4777 & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0;
4778 final boolean isAppWindow =
4779 attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW &&
4780 attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
4781 final boolean topAtRest =
4782 win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
4783 if (isAppWindow && !inheritTranslucentDecor && !topAtRest) {
4784 if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
4785 && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0
4786 && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
4787 && (fl & WindowManager.LayoutParams.
4788 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
4789 && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) {
4790 // Ensure policy decor includes status bar
4791 dcf.top = mStableTop;
4793 if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0
4794 && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
4795 && (fl & WindowManager.LayoutParams.
4796 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
4797 // Ensure policy decor includes navigation bar
4798 dcf.bottom = mStableBottom;
4799 dcf.right = mStableRight;
4803 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4804 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4805 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
4806 + "): IN_SCREEN, INSET_DECOR");
4807 // This is the case for a normal activity window: we want it
4808 // to cover all of the screen space, and it can take care of
4809 // moving its contents to account for screen decorations that
4810 // intrude into that space.
4811 if (attached != null) {
4812 // If this window is attached to another, our display
4813 // frame is the same as the one we are attached to.
4814 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4816 if (attrs.type == TYPE_STATUS_BAR_PANEL
4817 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
4818 // Status bar panels are the only windows who can go on top of
4819 // the status bar. They are protected by the STATUS_BAR_SERVICE
4820 // permission, so they have the same privileges as the status
4823 // However, they should still dodge the navigation bar if it exists.
4825 pf.left = df.left = of.left = hasNavBar
4826 ? mDockLeft : mUnrestrictedScreenLeft;
4827 pf.top = df.top = of.top = mUnrestrictedScreenTop;
4828 pf.right = df.right = of.right = hasNavBar
4829 ? mRestrictedScreenLeft+mRestrictedScreenWidth
4830 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4831 pf.bottom = df.bottom = of.bottom = hasNavBar
4832 ? mRestrictedScreenTop+mRestrictedScreenHeight
4833 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4835 if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4836 "Laying out status bar window: (%d,%d - %d,%d)",
4837 pf.left, pf.top, pf.right, pf.bottom));
4838 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4839 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4840 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4841 // Asking to layout into the overscan region, so give it that pure
4842 // unrestricted area.
4843 pf.left = df.left = of.left = mOverscanScreenLeft;
4844 pf.top = df.top = of.top = mOverscanScreenTop;
4845 pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth;
4846 pf.bottom = df.bottom = of.bottom = mOverscanScreenTop
4847 + mOverscanScreenHeight;
4848 } else if (canHideNavigationBar()
4849 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4850 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4851 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4852 // Asking for layout as if the nav bar is hidden, lets the
4853 // application extend into the unrestricted overscan screen area. We
4854 // only do this for application windows to ensure no window that
4855 // can be above the nav bar can do this.
4856 pf.left = df.left = mOverscanScreenLeft;
4857 pf.top = df.top = mOverscanScreenTop;
4858 pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
4859 pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
4860 // We need to tell the app about where the frame inside the overscan
4861 // is, so it can inset its content by that amount -- it didn't ask
4862 // to actually extend itself into the overscan region.
4863 of.left = mUnrestrictedScreenLeft;
4864 of.top = mUnrestrictedScreenTop;
4865 of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4866 of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4868 pf.left = df.left = mRestrictedOverscanScreenLeft;
4869 pf.top = df.top = mRestrictedOverscanScreenTop;
4870 pf.right = df.right = mRestrictedOverscanScreenLeft
4871 + mRestrictedOverscanScreenWidth;
4872 pf.bottom = df.bottom = mRestrictedOverscanScreenTop
4873 + mRestrictedOverscanScreenHeight;
4874 // We need to tell the app about where the frame inside the overscan
4875 // is, so it can inset its content by that amount -- it didn't ask
4876 // to actually extend itself into the overscan region.
4877 of.left = mUnrestrictedScreenLeft;
4878 of.top = mUnrestrictedScreenTop;
4879 of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4880 of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4883 if ((fl & FLAG_FULLSCREEN) == 0) {
4884 if (win.isVoiceInteraction()) {
4885 cf.left = mVoiceContentLeft;
4886 cf.top = mVoiceContentTop;
4887 cf.right = mVoiceContentRight;
4888 cf.bottom = mVoiceContentBottom;
4890 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4891 cf.left = mDockLeft;
4893 cf.right = mDockRight;
4894 cf.bottom = mDockBottom;
4896 cf.left = mContentLeft;
4897 cf.top = mContentTop;
4898 cf.right = mContentRight;
4899 cf.bottom = mContentBottom;
4903 // Full screen windows are always given a layout that is as if the
4904 // status bar and other transient decors are gone. This is to avoid
4905 // bad states when moving from a window that is not hding the
4906 // status bar to one that is.
4907 cf.left = mRestrictedScreenLeft;
4908 cf.top = mRestrictedScreenTop;
4909 cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
4910 cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4912 applyStableConstraints(sysUiFl, fl, cf);
4913 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4916 vf.right = mCurRight;
4917 vf.bottom = mCurBottom;
4922 } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
4923 & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
4924 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
4925 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4927 // A window that has requested to fill the entire screen just
4928 // gets everything, period.
4929 if (attrs.type == TYPE_STATUS_BAR_PANEL
4930 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL
4931 || attrs.type == TYPE_VOLUME_OVERLAY) {
4932 pf.left = df.left = of.left = cf.left = hasNavBar
4933 ? mDockLeft : mUnrestrictedScreenLeft;
4934 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
4935 pf.right = df.right = of.right = cf.right = hasNavBar
4936 ? mRestrictedScreenLeft+mRestrictedScreenWidth
4937 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4938 pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar
4939 ? mRestrictedScreenTop+mRestrictedScreenHeight
4940 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4941 if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4942 "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
4943 pf.left, pf.top, pf.right, pf.bottom));
4944 } else if (attrs.type == TYPE_NAVIGATION_BAR
4945 || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
4946 // The navigation bar has Real Ultimate Power.
4947 pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4948 pf.top = df.top = of.top = mUnrestrictedScreenTop;
4949 pf.right = df.right = of.right = mUnrestrictedScreenLeft
4950 + mUnrestrictedScreenWidth;
4951 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop
4952 + mUnrestrictedScreenHeight;
4953 if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4954 "Laying out navigation bar window: (%d,%d - %d,%d)",
4955 pf.left, pf.top, pf.right, pf.bottom));
4956 } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
4957 || attrs.type == TYPE_BOOT_PROGRESS
4958 || attrs.type == TYPE_SCREENSHOT)
4959 && ((fl & FLAG_FULLSCREEN) != 0)) {
4960 // Fullscreen secure system overlays get what they ask for. Screenshot region
4961 // selection overlay should also expand to full screen.
4962 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4963 pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4964 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
4965 + mOverscanScreenWidth;
4966 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
4967 + mOverscanScreenHeight;
4968 } else if (attrs.type == TYPE_BOOT_PROGRESS) {
4969 // Boot progress screen always covers entire display.
4970 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4971 pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4972 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
4973 + mOverscanScreenWidth;
4974 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
4975 + mOverscanScreenHeight;
4976 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4977 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4978 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4979 // Asking to layout into the overscan region, so give it that pure
4980 // unrestricted area.
4981 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4982 pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4983 pf.right = df.right = of.right = cf.right
4984 = mOverscanScreenLeft + mOverscanScreenWidth;
4985 pf.bottom = df.bottom = of.bottom = cf.bottom
4986 = mOverscanScreenTop + mOverscanScreenHeight;
4987 } else if (canHideNavigationBar()
4988 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4989 && (attrs.type == TYPE_STATUS_BAR
4990 || attrs.type == TYPE_TOAST
4991 || attrs.type == TYPE_DOCK_DIVIDER
4992 || attrs.type == TYPE_VOICE_INTERACTION_STARTING
4993 || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4994 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
4995 // Asking for layout as if the nav bar is hidden, lets the
4996 // application extend into the unrestricted screen area. We
4997 // only do this for application windows (or toasts) to ensure no window that
4998 // can be above the nav bar can do this.
4999 // XXX This assumes that an app asking for this will also
5000 // ask for layout in only content. We can't currently figure out
5001 // what the screen would be if only laying out to hide the nav bar.
5002 pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
5003 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
5004 pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft
5005 + mUnrestrictedScreenWidth;
5006 pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
5007 + mUnrestrictedScreenHeight;
5008 } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
5009 pf.left = df.left = of.left = mRestrictedScreenLeft;
5010 pf.top = df.top = of.top = mRestrictedScreenTop;
5011 pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
5012 pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop
5013 + mRestrictedScreenHeight;
5014 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5015 cf.left = mDockLeft;
5017 cf.right = mDockRight;
5018 cf.bottom = mDockBottom;
5020 cf.left = mContentLeft;
5021 cf.top = mContentTop;
5022 cf.right = mContentRight;
5023 cf.bottom = mContentBottom;
5026 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
5027 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
5028 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
5029 + mRestrictedScreenWidth;
5030 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
5031 + mRestrictedScreenHeight;
5034 applyStableConstraints(sysUiFl, fl, cf);
5036 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5039 vf.right = mCurRight;
5040 vf.bottom = mCurBottom;
5044 } else if (attached != null) {
5045 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5046 "): attached to " + attached);
5047 // A child window should be placed inside of the same visible
5048 // frame that its parent had.
5049 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf);
5051 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5052 "): normal window");
5053 // Otherwise, a normal window must be placed inside the content
5054 // of all screen decorations.
5055 if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) {
5056 // Status bar panels and the volume dialog are the only windows who can go on
5057 // top of the status bar. They are protected by the STATUS_BAR_SERVICE
5058 // permission, so they have the same privileges as the status
5060 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
5061 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
5062 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
5063 + mRestrictedScreenWidth;
5064 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
5065 + mRestrictedScreenHeight;
5066 } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) {
5067 // These dialogs are stable to interim decor changes.
5068 pf.left = df.left = of.left = cf.left = mStableLeft;
5069 pf.top = df.top = of.top = cf.top = mStableTop;
5070 pf.right = df.right = of.right = cf.right = mStableRight;
5071 pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom;
5073 pf.left = mContentLeft;
5074 pf.top = mContentTop;
5075 pf.right = mContentRight;
5076 pf.bottom = mContentBottom;
5077 if (win.isVoiceInteraction()) {
5078 df.left = of.left = cf.left = mVoiceContentLeft;
5079 df.top = of.top = cf.top = mVoiceContentTop;
5080 df.right = of.right = cf.right = mVoiceContentRight;
5081 df.bottom = of.bottom = cf.bottom = mVoiceContentBottom;
5082 } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5083 df.left = of.left = cf.left = mDockLeft;
5084 df.top = of.top = cf.top = mDockTop;
5085 df.right = of.right = cf.right = mDockRight;
5086 df.bottom = of.bottom = cf.bottom = mDockBottom;
5088 df.left = of.left = cf.left = mContentLeft;
5089 df.top = of.top = cf.top = mContentTop;
5090 df.right = of.right = cf.right = mContentRight;
5091 df.bottom = of.bottom = cf.bottom = mContentBottom;
5093 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5096 vf.right = mCurRight;
5097 vf.bottom = mCurBottom;
5105 // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
5106 // Also, we don't allow windows in multi-window mode to extend out of the screen.
5107 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR
5108 && !win.isInMultiWindowMode()) {
5109 df.left = df.top = -10000;
5110 df.right = df.bottom = 10000;
5111 if (attrs.type != TYPE_WALLPAPER) {
5112 of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
5113 of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
5117 // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we
5118 // need to provide information to the clients that want to pretend that you can draw there.
5119 // We only want to apply outsets to certain types of windows. For example, we never want to
5120 // apply the outsets to floating dialogs, because they wouldn't make sense there.
5121 final boolean useOutsets = shouldUseOutsets(attrs, fl);
5122 if (isDefaultDisplay && useOutsets) {
5123 osf = mTmpOutsetFrame;
5124 osf.set(cf.left, cf.top, cf.right, cf.bottom);
5125 int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
5127 int rotation = mDisplayRotation;
5128 if (rotation == Surface.ROTATION_0) {
5129 osf.bottom += outset;
5130 } else if (rotation == Surface.ROTATION_90) {
5131 osf.right += outset;
5132 } else if (rotation == Surface.ROTATION_180) {
5134 } else if (rotation == Surface.ROTATION_270) {
5137 if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset
5138 + " with rotation " + rotation + ", result: " + osf);
5142 if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
5143 + ": sim=#" + Integer.toHexString(sim)
5144 + " attach=" + attached + " type=" + attrs.type
5145 + String.format(" flags=0x%08x", fl)
5146 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
5147 + " of=" + of.toShortString()
5148 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
5149 + " dcf=" + dcf.toShortString()
5150 + " sf=" + sf.toShortString()
5151 + " osf=" + (osf == null ? "null" : osf.toShortString()));
5153 win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf);
5155 // Dock windows carve out the bottom of the screen, so normal windows
5156 // can't appear underneath them.
5157 if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleLw()
5158 && !win.getGivenInsetsPendingLw()) {
5159 setLastInputMethodWindowLw(null, null);
5160 offsetInputMethodWindowLw(win);
5162 if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleLw()
5163 && !win.getGivenInsetsPendingLw()) {
5164 offsetVoiceInputWindowLw(win);
5168 private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) {
5170 // The wallpaper also has Real Ultimate Power, but we want to tell
5171 // it about the overscan area.
5172 pf.left = df.left = mOverscanScreenLeft;
5173 pf.top = df.top = mOverscanScreenTop;
5174 pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
5175 pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
5176 of.left = cf.left = mUnrestrictedScreenLeft;
5177 of.top = cf.top = mUnrestrictedScreenTop;
5178 of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5179 of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5182 private void offsetInputMethodWindowLw(WindowState win) {
5183 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5184 top += win.getGivenContentInsetsLw().top;
5185 if (mContentBottom > top) {
5186 mContentBottom = top;
5188 if (mVoiceContentBottom > top) {
5189 mVoiceContentBottom = top;
5191 top = win.getVisibleFrameLw().top;
5192 top += win.getGivenVisibleInsetsLw().top;
5193 if (mCurBottom > top) {
5196 if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
5197 + mDockBottom + " mContentBottom="
5198 + mContentBottom + " mCurBottom=" + mCurBottom);
5201 private void offsetVoiceInputWindowLw(WindowState win) {
5202 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5203 top += win.getGivenContentInsetsLw().top;
5204 if (mVoiceContentBottom > top) {
5205 mVoiceContentBottom = top;
5209 /** {@inheritDoc} */
5211 public void finishLayoutLw() {
5215 /** {@inheritDoc} */
5217 public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
5218 mTopFullscreenOpaqueWindowState = null;
5219 mTopFullscreenOpaqueOrDimmingWindowState = null;
5220 mTopDockedOpaqueWindowState = null;
5221 mTopDockedOpaqueOrDimmingWindowState = null;
5222 mForceStatusBar = false;
5223 mForceStatusBarFromKeyguard = false;
5224 mForceStatusBarTransparent = false;
5225 mForcingShowNavBar = false;
5226 mForcingShowNavBarLayer = -1;
5228 mAllowLockscreenWhenOn = false;
5229 mShowingDream = false;
5232 /** {@inheritDoc} */
5234 public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
5235 WindowState attached, WindowState imeTarget) {
5236 final boolean visible = !win.isGoneForLayoutLw();
5237 if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisible=" + visible);
5238 applyKeyguardPolicyLw(win, imeTarget);
5239 final int fl = PolicyControl.getWindowFlags(win, attrs);
5240 if (mTopFullscreenOpaqueWindowState == null && visible && attrs.type == TYPE_INPUT_METHOD) {
5241 mForcingShowNavBar = true;
5242 mForcingShowNavBarLayer = win.getSurfaceLayer();
5244 if (attrs.type == TYPE_STATUS_BAR) {
5245 if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
5246 mForceStatusBarFromKeyguard = true;
5248 if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
5249 mForceStatusBarTransparent = true;
5253 // Don't allow snapshots to influence SystemUI visibility flags.
5254 // TODO: Revisit this once SystemUI flags for snapshots are handled correctly
5255 boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
5256 && attrs.type < FIRST_SYSTEM_WINDOW
5257 && (attrs.privateFlags & PRIVATE_FLAG_TASK_SNAPSHOT) == 0;
5258 final int stackId = win.getStackId();
5259 if (mTopFullscreenOpaqueWindowState == null && visible) {
5260 if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
5261 mForceStatusBar = true;
5263 if (attrs.type == TYPE_DREAM) {
5264 // If the lockscreen was showing when the dream started then wait
5265 // for the dream to draw before hiding the lockscreen.
5266 if (!mDreamingLockscreen
5267 || (win.isVisibleLw() && win.hasDrawnLw())) {
5268 mShowingDream = true;
5273 // For app windows that are not attached, we decide if all windows in the app they
5274 // represent should be hidden or if we should hide the lockscreen. For attached app
5275 // windows we defer the decision to the window it is attached to.
5276 if (appWindow && attached == null) {
5277 if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
5278 if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
5279 mTopFullscreenOpaqueWindowState = win;
5280 if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5281 mTopFullscreenOpaqueOrDimmingWindowState = win;
5283 if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
5284 mAllowLockscreenWhenOn = true;
5290 // Voice interaction overrides both top fullscreen and top docked.
5291 if (visible && win.getAttrs().type == TYPE_VOICE_INTERACTION) {
5292 if (mTopFullscreenOpaqueWindowState == null) {
5293 mTopFullscreenOpaqueWindowState = win;
5294 if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5295 mTopFullscreenOpaqueOrDimmingWindowState = win;
5298 if (mTopDockedOpaqueWindowState == null) {
5299 mTopDockedOpaqueWindowState = win;
5300 if (mTopDockedOpaqueOrDimmingWindowState == null) {
5301 mTopDockedOpaqueOrDimmingWindowState = win;
5306 // Keep track of the window if it's dimming but not necessarily fullscreen.
5307 if (mTopFullscreenOpaqueOrDimmingWindowState == null && visible
5308 && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
5309 mTopFullscreenOpaqueOrDimmingWindowState = win;
5312 // We need to keep track of the top "fullscreen" opaque window for the docked stack
5313 // separately, because both the "real fullscreen" opaque window and the one for the docked
5314 // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
5315 if (mTopDockedOpaqueWindowState == null && visible && appWindow && attached == null
5316 && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
5317 mTopDockedOpaqueWindowState = win;
5318 if (mTopDockedOpaqueOrDimmingWindowState == null) {
5319 mTopDockedOpaqueOrDimmingWindowState = win;
5323 // Also keep track of any windows that are dimming but not necessarily fullscreen in the
5325 if (mTopDockedOpaqueOrDimmingWindowState == null && visible && win.isDimming()
5326 && stackId == DOCKED_STACK_ID) {
5327 mTopDockedOpaqueOrDimmingWindowState = win;
5331 private void applyKeyguardPolicyLw(WindowState win, WindowState imeTarget) {
5332 if (canBeHiddenByKeyguardLw(win)) {
5333 if (shouldBeHiddenByKeyguard(win, imeTarget)) {
5334 win.hideLw(false /* doAnimation */);
5336 win.showLw(false /* doAnimation */);
5341 private boolean isFullscreen(WindowManager.LayoutParams attrs) {
5342 return attrs.x == 0 && attrs.y == 0
5343 && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
5344 && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
5347 /** {@inheritDoc} */
5349 public int finishPostLayoutPolicyLw() {
5351 boolean topIsFullscreen = false;
5353 final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
5354 ? mTopFullscreenOpaqueWindowState.getAttrs()
5357 // If we are not currently showing a dream then remember the current
5358 // lockscreen state. We will use this to determine whether the dream
5359 // started while the lockscreen was showing and remember this state
5360 // while the dream is showing.
5361 if (!mShowingDream) {
5362 mDreamingLockscreen = isKeyguardShowingAndNotOccluded();
5363 if (mDreamingSleepTokenNeeded) {
5364 mDreamingSleepTokenNeeded = false;
5365 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
5368 if (!mDreamingSleepTokenNeeded) {
5369 mDreamingSleepTokenNeeded = true;
5370 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget();
5374 if (mStatusBar != null) {
5375 if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
5376 + " forcefkg=" + mForceStatusBarFromKeyguard
5377 + " top=" + mTopFullscreenOpaqueWindowState);
5378 boolean shouldBeTransparent = mForceStatusBarTransparent
5380 && !mForceStatusBarFromKeyguard;
5381 if (!shouldBeTransparent) {
5382 mStatusBarController.setShowTransparent(false /* transparent */);
5383 } else if (!mStatusBar.isVisibleLw()) {
5384 mStatusBarController.setShowTransparent(true /* transparent */);
5387 WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs();
5388 boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT
5389 && statusBarAttrs.width == MATCH_PARENT;
5390 if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
5391 || statusBarExpanded) {
5392 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
5393 if (mStatusBarController.setBarShowingLw(true)) {
5394 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5396 // Maintain fullscreen layout until incoming animation is complete.
5397 topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
5398 // Transient status bar on the lockscreen is not allowed
5399 if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) {
5400 mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
5401 mLastSystemUiFlags, mLastSystemUiFlags);
5403 if (statusBarExpanded && mNavigationBar != null) {
5404 if (mNavigationBarController.setBarShowingLw(true)) {
5405 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5408 } else if (mTopFullscreenOpaqueWindowState != null) {
5409 final int fl = PolicyControl.getWindowFlags(null, lp);
5411 Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
5412 + " shown position: "
5413 + mTopFullscreenOpaqueWindowState.getShownPositionLw());
5414 Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
5415 + " lp.flags=0x" + Integer.toHexString(fl));
5417 topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
5418 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
5419 // The subtle difference between the window for mTopFullscreenOpaqueWindowState
5420 // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
5421 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the
5423 if (mStatusBarController.isTransientShowing()) {
5424 if (mStatusBarController.setBarShowingLw(true)) {
5425 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5427 } else if (topIsFullscreen
5428 && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)
5429 && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) {
5430 if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
5431 if (mStatusBarController.setBarShowingLw(false)) {
5432 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5434 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
5437 if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
5438 if (mStatusBarController.setBarShowingLw(true)) {
5439 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5445 if (mTopIsFullscreen != topIsFullscreen) {
5446 if (!topIsFullscreen) {
5447 // Force another layout when status bar becomes fully shown.
5448 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5450 mTopIsFullscreen = topIsFullscreen;
5453 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5454 // If the navigation bar has been hidden or shown, we need to do another
5455 // layout pass to update that window.
5456 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5459 if (mShowingDream != mLastShowingDream) {
5460 mLastShowingDream = mShowingDream;
5461 mWindowManagerFuncs.notifyShowingDreamChanged();
5464 // update since mAllowLockscreenWhenOn might have changed
5465 updateLockScreenTimeout();
5470 * Updates the occluded state of the Keyguard.
5472 * @return Whether the flags have changed and we have to redo the layout.
5474 private boolean setKeyguardOccludedLw(boolean isOccluded) {
5475 if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded);
5476 boolean wasOccluded = mKeyguardOccluded;
5477 boolean showing = mKeyguardDelegate.isShowing();
5478 if (wasOccluded && !isOccluded && showing) {
5479 mKeyguardOccluded = false;
5480 mKeyguardDelegate.setOccluded(false, true /* animate */);
5481 mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
5482 if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
5483 mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5486 } else if (!wasOccluded && isOccluded && showing) {
5487 mKeyguardOccluded = true;
5488 mKeyguardDelegate.setOccluded(true, false /* animate */);
5489 mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
5490 mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
5492 } else if (wasOccluded != isOccluded) {
5493 mKeyguardOccluded = isOccluded;
5494 mKeyguardDelegate.setOccluded(isOccluded, false /* animate */);
5501 private boolean isStatusBarKeyguard() {
5502 return mStatusBar != null
5503 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
5507 public boolean allowAppAnimationsLw() {
5508 if (mShowingDream) {
5509 // If keyguard or dreams is currently visible, no reason to animate behind it.
5516 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
5517 mFocusedWindow = newFocus;
5518 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5519 // If the navigation bar has been hidden or shown, we need to do another
5520 // layout pass to update that window.
5521 return FINISH_LAYOUT_REDO_LAYOUT;
5526 /** {@inheritDoc} */
5528 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
5529 // lid changed state
5530 final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
5531 if (newLidState == mLidState) {
5535 mLidState = newLidState;
5536 applyLidSwitchState();
5537 updateRotation(true);
5540 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
5541 "android.policy:LID");
5542 } else if (!mLidControlsSleep) {
5543 mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
5548 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
5549 int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
5550 if (mCameraLensCoverState == lensCoverState) {
5553 if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
5554 lensCoverState == CAMERA_LENS_UNCOVERED) {
5556 final boolean keyguardActive = mKeyguardDelegate == null ? false :
5557 mKeyguardDelegate.isShowing();
5558 if (keyguardActive) {
5559 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
5561 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
5563 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
5564 "android.policy:CAMERA_COVER");
5565 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
5567 mCameraLensCoverState = lensCoverState;
5570 void setHdmiPlugged(boolean plugged) {
5571 if (mHdmiPlugged != plugged) {
5572 mHdmiPlugged = plugged;
5573 updateRotation(true, true);
5574 Intent intent = new Intent(ACTION_HDMI_PLUGGED);
5575 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
5576 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
5577 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
5581 void initializeHdmiState() {
5582 boolean plugged = false;
5583 // watch for HDMI plug messages if the hdmi switch exists
5584 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
5585 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
5587 final String filename = "/sys/class/switch/hdmi/state";
5588 FileReader reader = null;
5590 reader = new FileReader(filename);
5591 char[] buf = new char[15];
5592 int n = reader.read(buf);
5594 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
5596 } catch (IOException ex) {
5597 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5598 } catch (NumberFormatException ex) {
5599 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5601 if (reader != null) {
5604 } catch (IOException ex) {
5609 // This dance forces the code in setHdmiPlugged to run.
5610 // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
5611 mHdmiPlugged = !plugged;
5612 setHdmiPlugged(!mHdmiPlugged);
5615 final Object mScreenshotLock = new Object();
5616 ServiceConnection mScreenshotConnection = null;
5618 final Runnable mScreenshotTimeout = new Runnable() {
5619 @Override public void run() {
5620 synchronized (mScreenshotLock) {
5621 if (mScreenshotConnection != null) {
5622 mContext.unbindService(mScreenshotConnection);
5623 mScreenshotConnection = null;
5624 notifyScreenshotError();
5630 // Assume this is called from the Handler thread.
5631 private void takeScreenshot(final int screenshotType) {
5632 synchronized (mScreenshotLock) {
5633 if (mScreenshotConnection != null) {
5636 final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
5637 SYSUI_SCREENSHOT_SERVICE);
5638 final Intent serviceIntent = new Intent();
5639 serviceIntent.setComponent(serviceComponent);
5640 ServiceConnection conn = new ServiceConnection() {
5642 public void onServiceConnected(ComponentName name, IBinder service) {
5643 synchronized (mScreenshotLock) {
5644 if (mScreenshotConnection != this) {
5647 Messenger messenger = new Messenger(service);
5648 Message msg = Message.obtain(null, screenshotType);
5649 final ServiceConnection myConn = this;
5650 Handler h = new Handler(mHandler.getLooper()) {
5652 public void handleMessage(Message msg) {
5653 synchronized (mScreenshotLock) {
5654 if (mScreenshotConnection == myConn) {
5655 mContext.unbindService(mScreenshotConnection);
5656 mScreenshotConnection = null;
5657 mHandler.removeCallbacks(mScreenshotTimeout);
5662 msg.replyTo = new Messenger(h);
5663 msg.arg1 = msg.arg2 = 0;
5664 if (mStatusBar != null && mStatusBar.isVisibleLw())
5666 if (mNavigationBar != null && mNavigationBar.isVisibleLw())
5669 messenger.send(msg);
5670 } catch (RemoteException e) {
5676 public void onServiceDisconnected(ComponentName name) {
5677 synchronized (mScreenshotLock) {
5678 if (mScreenshotConnection != null) {
5679 mContext.unbindService(mScreenshotConnection);
5680 mScreenshotConnection = null;
5681 mHandler.removeCallbacks(mScreenshotTimeout);
5682 notifyScreenshotError();
5687 if (mContext.bindServiceAsUser(serviceIntent, conn,
5688 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
5689 UserHandle.CURRENT)) {
5690 mScreenshotConnection = conn;
5691 mHandler.postDelayed(mScreenshotTimeout, 10000);
5697 * Notifies the screenshot service to show an error.
5699 private void notifyScreenshotError() {
5700 // If the service process is killed, then ask it to clean up after itself
5701 final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
5702 SYSUI_SCREENSHOT_ERROR_RECEIVER);
5703 Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
5704 errorIntent.setComponent(errorComponent);
5705 errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
5706 Intent.FLAG_RECEIVER_FOREGROUND);
5707 mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT);
5710 /** {@inheritDoc} */
5712 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
5713 if (!mSystemBooted) {
5714 // If we have not yet booted, don't let key events do anything.
5718 final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
5719 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
5720 final boolean canceled = event.isCanceled();
5721 final int keyCode = event.getKeyCode();
5723 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
5725 // If screen is off then we treat the case where the keyguard is open but hidden
5726 // the same as if it were open and in front.
5727 // This will prevent any keys other than the power button from waking the screen
5728 // when the keyguard is hidden by another activity.
5729 final boolean keyguardActive = (mKeyguardDelegate == null ? false :
5731 isKeyguardShowingAndNotOccluded() :
5732 mKeyguardDelegate.isShowing()));
5735 Log.d(TAG, "interceptKeyTq keycode=" + keyCode
5736 + " interactive=" + interactive + " keyguardActive=" + keyguardActive
5737 + " policyFlags=" + Integer.toHexString(policyFlags));
5740 // Basic policy based on interactive state.
5742 boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
5743 || event.isWakeKey();
5744 if (interactive || (isInjected && !isWakeKey)) {
5745 // When the device is interactive or the key is injected pass the
5746 // key to the application.
5747 result = ACTION_PASS_TO_USER;
5751 // If the screen is awake, but the button pressed was the one that woke the device
5752 // then don't pass it to the application
5753 if (keyCode == mPendingWakeKey && !down) {
5756 // Reset the pending key
5757 mPendingWakeKey = PENDING_KEY_NULL;
5759 } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
5760 // If we're currently dozing with the screen on and the keyguard showing, pass the key
5761 // to the application but preserve its wake key status to make sure we still move
5762 // from dozing to fully interactive if we would normally go from off to fully
5764 result = ACTION_PASS_TO_USER;
5765 // Since we're dispatching the input, reset the pending key
5766 mPendingWakeKey = PENDING_KEY_NULL;
5768 // When the screen is off and the key is not injected, determine whether
5769 // to wake the device but don't pass the key to the application.
5771 if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
5774 // Cache the wake key on down event so we can also avoid sending the up event to the app
5775 if (isWakeKey && down) {
5776 mPendingWakeKey = keyCode;
5780 // If the key would be handled globally, just return the result, don't worry about special
5782 if (isValidGlobalKey(keyCode)
5783 && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
5785 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5790 boolean useHapticFeedback = down
5791 && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
5792 && event.getRepeatCount() == 0;
5794 // Handle special keys.
5796 case KeyEvent.KEYCODE_BACK: {
5798 interceptBackKeyDown();
5800 boolean handled = interceptBackKeyUp(event);
5802 // Don't pass back press to app if we've already handled it via long press
5804 result &= ~ACTION_PASS_TO_USER;
5810 case KeyEvent.KEYCODE_VOLUME_DOWN:
5811 case KeyEvent.KEYCODE_VOLUME_UP:
5812 case KeyEvent.KEYCODE_VOLUME_MUTE: {
5813 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
5815 if (interactive && !mScreenshotChordVolumeDownKeyTriggered
5816 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5817 mScreenshotChordVolumeDownKeyTriggered = true;
5818 mScreenshotChordVolumeDownKeyTime = event.getDownTime();
5819 mScreenshotChordVolumeDownKeyConsumed = false;
5820 cancelPendingPowerKeyAction();
5821 interceptScreenshotChord();
5822 if (!isKeyguardLocked()) {
5823 interceptAccessibilityShortcutChord();
5827 mScreenshotChordVolumeDownKeyTriggered = false;
5828 cancelPendingScreenshotChordAction();
5829 cancelPendingAccessibilityShortcutAction();
5831 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
5833 if (interactive && !mA11yShortcutChordVolumeUpKeyTriggered
5834 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5835 mA11yShortcutChordVolumeUpKeyTriggered = true;
5836 mA11yShortcutChordVolumeUpKeyTime = event.getDownTime();
5837 mA11yShortcutChordVolumeUpKeyConsumed = false;
5838 cancelPendingPowerKeyAction();
5839 cancelPendingScreenshotChordAction();
5840 if (!isKeyguardLocked()) {
5841 interceptAccessibilityShortcutChord();
5845 mA11yShortcutChordVolumeUpKeyTriggered = false;
5846 cancelPendingScreenshotChordAction();
5847 cancelPendingAccessibilityShortcutAction();
5851 TelecomManager telecomManager = getTelecommService();
5852 if (telecomManager != null) {
5853 if (telecomManager.isRinging()) {
5854 // If an incoming call is ringing, either VOLUME key means
5855 // "silence ringer". We handle these keys here, rather than
5856 // in the InCallScreen, to make sure we'll respond to them
5857 // even if the InCallScreen hasn't come to the foreground yet.
5858 // Look for the DOWN event here, to agree with the "fallback"
5859 // behavior in the InCallScreen.
5860 Log.i(TAG, "interceptKeyBeforeQueueing:"
5861 + " VOLUME key-down while ringing: Silence ringer!");
5863 // Silence the ringer. (It's safe to call this
5864 // even if the ringer has already been silenced.)
5865 telecomManager.silenceRinger();
5867 // And *don't* pass this key thru to the current activity
5868 // (which is probably the InCallScreen.)
5869 result &= ~ACTION_PASS_TO_USER;
5872 if (telecomManager.isInCall()
5873 && (result & ACTION_PASS_TO_USER) == 0) {
5874 // If we are in call but we decided not to pass the key to
5875 // the application, just pass it to the session service.
5876 MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
5877 event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
5882 if (mUseTvRouting) {
5883 // On TVs, defer special key handlings to
5884 // {@link interceptKeyBeforeDispatching()}.
5885 result |= ACTION_PASS_TO_USER;
5886 } else if ((result & ACTION_PASS_TO_USER) == 0) {
5887 // If we aren't passing to the user and no one else
5888 // handled it send it to the session manager to
5890 MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
5891 event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
5896 case KeyEvent.KEYCODE_ENDCALL: {
5897 result &= ~ACTION_PASS_TO_USER;
5899 TelecomManager telecomManager = getTelecommService();
5900 boolean hungUp = false;
5901 if (telecomManager != null) {
5902 hungUp = telecomManager.endCall();
5904 if (interactive && !hungUp) {
5905 mEndCallKeyHandled = false;
5906 mHandler.postDelayed(mEndCallLongPress,
5907 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
5909 mEndCallKeyHandled = true;
5912 if (!mEndCallKeyHandled) {
5913 mHandler.removeCallbacks(mEndCallLongPress);
5915 if ((mEndcallBehavior
5916 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
5921 if ((mEndcallBehavior
5922 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
5923 mPowerManager.goToSleep(event.getEventTime(),
5924 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
5933 case KeyEvent.KEYCODE_POWER: {
5934 // Any activity on the power button stops the accessibility shortcut
5935 cancelPendingAccessibilityShortcutAction();
5936 result &= ~ACTION_PASS_TO_USER;
5937 isWakeKey = false; // wake-up will be handled separately
5939 interceptPowerKeyDown(event, interactive);
5941 interceptPowerKeyUp(event, interactive, canceled);
5946 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
5948 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
5950 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
5952 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
5953 result &= ~ACTION_PASS_TO_USER;
5954 interceptSystemNavigationKey(event);
5958 case KeyEvent.KEYCODE_SLEEP: {
5959 result &= ~ACTION_PASS_TO_USER;
5961 if (!mPowerManager.isInteractive()) {
5962 useHapticFeedback = false; // suppress feedback if already non-interactive
5965 sleepPress(event.getEventTime());
5967 sleepRelease(event.getEventTime());
5972 case KeyEvent.KEYCODE_SOFT_SLEEP: {
5973 result &= ~ACTION_PASS_TO_USER;
5976 mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
5981 case KeyEvent.KEYCODE_WAKEUP: {
5982 result &= ~ACTION_PASS_TO_USER;
5987 case KeyEvent.KEYCODE_MEDIA_PLAY:
5988 case KeyEvent.KEYCODE_MEDIA_PAUSE:
5989 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
5990 case KeyEvent.KEYCODE_HEADSETHOOK:
5991 case KeyEvent.KEYCODE_MUTE:
5992 case KeyEvent.KEYCODE_MEDIA_STOP:
5993 case KeyEvent.KEYCODE_MEDIA_NEXT:
5994 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
5995 case KeyEvent.KEYCODE_MEDIA_REWIND:
5996 case KeyEvent.KEYCODE_MEDIA_RECORD:
5997 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
5998 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
5999 if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
6000 // If the global session is active pass all media keys to it
6001 // instead of the active window.
6002 result &= ~ACTION_PASS_TO_USER;
6004 if ((result & ACTION_PASS_TO_USER) == 0) {
6005 // Only do this if we would otherwise not pass it to the user. In that
6006 // case, the PhoneWindow class will do the same thing, except it will
6007 // only do it if the showing app doesn't process the key on its own.
6008 // Note that we need to make a copy of the key event here because the
6009 // original key event will be recycled when we return.
6010 mBroadcastWakeLock.acquire();
6011 Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
6012 new KeyEvent(event));
6013 msg.setAsynchronous(true);
6019 case KeyEvent.KEYCODE_CALL: {
6021 TelecomManager telecomManager = getTelecommService();
6022 if (telecomManager != null) {
6023 if (telecomManager.isRinging()) {
6024 Log.i(TAG, "interceptKeyBeforeQueueing:"
6025 + " CALL key-down while ringing: Answer the call!");
6026 telecomManager.acceptRingingCall();
6028 // And *don't* pass this key thru to the current activity
6029 // (which is presumably the InCallScreen.)
6030 result &= ~ACTION_PASS_TO_USER;
6036 case KeyEvent.KEYCODE_VOICE_ASSIST: {
6037 // Only do this if we would otherwise not pass it to the user. In that case,
6038 // interceptKeyBeforeDispatching would apply a similar but different policy in
6039 // order to invoke voice assist actions. Note that we need to make a copy of the
6040 // key event here because the original key event will be recycled when we return.
6041 if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
6042 mBroadcastWakeLock.acquire();
6043 Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
6044 keyguardActive ? 1 : 0, 0);
6045 msg.setAsynchronous(true);
6050 case KeyEvent.KEYCODE_WINDOW: {
6051 if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
6052 if (mTvPictureInPictureVisible) {
6053 // Consumes the key only if picture-in-picture is visible
6054 // to show picture-in-picture control menu.
6055 // This gives a chance to the foreground activity
6056 // to customize PIP key behavior.
6058 showTvPictureInPictureMenu(event);
6060 result &= ~ACTION_PASS_TO_USER;
6067 if (useHapticFeedback) {
6068 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
6072 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
6079 * Handle statusbar expansion events.
6082 private void interceptSystemNavigationKey(KeyEvent event) {
6083 if (event.getAction() == KeyEvent.ACTION_UP) {
6084 if (!mAccessibilityManager.isEnabled()
6085 || !mAccessibilityManager.sendFingerprintGesture(event.getKeyCode())) {
6086 if (areSystemNavigationKeysEnabled()) {
6087 IStatusBarService sbar = getStatusBarService();
6090 sbar.handleSystemNavigationKey(event.getKeyCode());
6091 } catch (RemoteException e1) {
6092 // oops, no statusbar. Ignore event.
6101 * Returns true if the key can have global actions attached to it.
6102 * We reserve all power management keys for the system since they require
6103 * very careful handling.
6105 private static boolean isValidGlobalKey(int keyCode) {
6107 case KeyEvent.KEYCODE_POWER:
6108 case KeyEvent.KEYCODE_WAKEUP:
6109 case KeyEvent.KEYCODE_SLEEP:
6117 * When the screen is off we ignore some keys that might otherwise typically
6118 * be considered wake keys. We filter them out here.
6120 * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
6121 * is always considered a wake key.
6123 private boolean isWakeKeyWhenScreenOff(int keyCode) {
6125 // ignore volume keys unless docked
6126 case KeyEvent.KEYCODE_VOLUME_UP:
6127 case KeyEvent.KEYCODE_VOLUME_DOWN:
6128 case KeyEvent.KEYCODE_VOLUME_MUTE:
6129 return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
6131 // ignore media and camera keys
6132 case KeyEvent.KEYCODE_MUTE:
6133 case KeyEvent.KEYCODE_HEADSETHOOK:
6134 case KeyEvent.KEYCODE_MEDIA_PLAY:
6135 case KeyEvent.KEYCODE_MEDIA_PAUSE:
6136 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6137 case KeyEvent.KEYCODE_MEDIA_STOP:
6138 case KeyEvent.KEYCODE_MEDIA_NEXT:
6139 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6140 case KeyEvent.KEYCODE_MEDIA_REWIND:
6141 case KeyEvent.KEYCODE_MEDIA_RECORD:
6142 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6143 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
6144 case KeyEvent.KEYCODE_CAMERA:
6151 /** {@inheritDoc} */
6153 public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
6154 if ((policyFlags & FLAG_WAKE) != 0) {
6155 if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
6156 "android.policy:MOTION")) {
6161 if (shouldDispatchInputWhenNonInteractive(null)) {
6162 return ACTION_PASS_TO_USER;
6165 // If we have not passed the action up and we are in theater mode without dreaming,
6166 // there will be no dream to intercept the touch and wake into ambient. The device should
6167 // wake up in this case.
6168 if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
6169 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
6170 "android.policy:MOTION");
6176 private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
6177 final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
6179 if (displayOff && !mHasFeatureWatch) {
6183 // Send events to keyguard while the screen is on and it's showing.
6184 if (isKeyguardShowingAndNotOccluded() && !displayOff) {
6188 // Watches handle BACK specially
6189 if (mHasFeatureWatch
6191 && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
6192 || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
6196 // Send events to a dozing dream even if the screen is off since the dream
6197 // is in control of the state of the screen.
6198 IDreamManager dreamManager = getDreamManager();
6201 if (dreamManager != null && dreamManager.isDreaming()) {
6204 } catch (RemoteException e) {
6205 Slog.e(TAG, "RemoteException when checking if dreaming", e);
6208 // Otherwise, consume events since the user can't see what is being
6213 private void dispatchDirectAudioEvent(KeyEvent event) {
6214 if (event.getAction() != KeyEvent.ACTION_DOWN) {
6217 int keyCode = event.getKeyCode();
6218 int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
6219 | AudioManager.FLAG_FROM_KEY;
6220 String pkgName = mContext.getOpPackageName();
6222 case KeyEvent.KEYCODE_VOLUME_UP:
6224 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
6225 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6226 } catch (RemoteException e) {
6227 Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
6230 case KeyEvent.KEYCODE_VOLUME_DOWN:
6232 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
6233 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6234 } catch (RemoteException e) {
6235 Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
6238 case KeyEvent.KEYCODE_VOLUME_MUTE:
6240 if (event.getRepeatCount() == 0) {
6241 getAudioService().adjustSuggestedStreamVolume(
6242 AudioManager.ADJUST_TOGGLE_MUTE,
6243 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6245 } catch (RemoteException e) {
6246 Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
6252 void dispatchMediaKeyWithWakeLock(KeyEvent event) {
6254 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
6257 if (mHavePendingMediaKeyRepeatWithWakeLock) {
6259 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
6262 mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
6263 mHavePendingMediaKeyRepeatWithWakeLock = false;
6264 mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
6267 dispatchMediaKeyWithWakeLockToAudioService(event);
6269 if (event.getAction() == KeyEvent.ACTION_DOWN
6270 && event.getRepeatCount() == 0) {
6271 mHavePendingMediaKeyRepeatWithWakeLock = true;
6273 Message msg = mHandler.obtainMessage(
6274 MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
6275 msg.setAsynchronous(true);
6276 mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
6278 mBroadcastWakeLock.release();
6282 void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
6283 mHavePendingMediaKeyRepeatWithWakeLock = false;
6285 KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
6286 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6288 Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
6291 dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
6292 mBroadcastWakeLock.release();
6295 void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
6296 if (mActivityManagerInternal.isSystemReady()) {
6297 MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
6301 void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
6302 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
6303 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
6306 dic.exitIdle("voice-search");
6307 } catch (RemoteException e) {
6310 Intent voiceIntent =
6311 new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
6312 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
6313 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
6314 mBroadcastWakeLock.release();
6317 BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
6319 public void onReceive(Context context, Intent intent) {
6320 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
6321 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6322 Intent.EXTRA_DOCK_STATE_UNDOCKED);
6325 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
6326 ServiceManager.getService(Context.UI_MODE_SERVICE));
6327 mUiMode = uiModeService.getCurrentModeType();
6328 } catch (RemoteException e) {
6331 updateRotation(true);
6332 synchronized (mLock) {
6333 updateOrientationListenerLp();
6338 BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
6340 public void onReceive(Context context, Intent intent) {
6341 if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
6342 if (mKeyguardDelegate != null) {
6343 mKeyguardDelegate.onDreamingStarted();
6345 } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
6346 if (mKeyguardDelegate != null) {
6347 mKeyguardDelegate.onDreamingStopped();
6353 BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
6355 public void onReceive(Context context, Intent intent) {
6356 if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
6357 // tickle the settings observer: this first ensures that we're
6358 // observing the relevant settings for the newly-active user,
6359 // and then updates our own bookkeeping based on the now-
6361 mSettingsObserver.onChange(false);
6363 // force a re-application of focused window sysui visibility.
6364 // the window may never have been shown for this user
6365 // e.g. the keyguard when going through the new-user setup flow
6366 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6367 mLastSystemUiFlags = 0;
6368 updateSystemUiVisibilityLw();
6374 private final Runnable mHiddenNavPanic = new Runnable() {
6377 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6378 if (!isUserSetupComplete()) {
6379 // Swipe-up for navigation bar is disabled during setup
6382 mPendingPanicGestureUptime = SystemClock.uptimeMillis();
6383 if (!isNavBarEmpty(mLastSystemUiFlags)) {
6384 mNavigationBarController.showTransient();
6390 private void requestTransientBars(WindowState swipeTarget) {
6391 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6392 if (!isUserSetupComplete()) {
6393 // Swipe-up for navigation bar is disabled during setup
6396 boolean sb = mStatusBarController.checkShowTransientBarLw();
6397 boolean nb = mNavigationBarController.checkShowTransientBarLw()
6398 && !isNavBarEmpty(mLastSystemUiFlags);
6400 // Don't show status bar when swiping on already visible navigation bar
6401 if (!nb && swipeTarget == mNavigationBar) {
6402 if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
6405 if (sb) mStatusBarController.showTransient();
6406 if (nb) mNavigationBarController.showTransient();
6407 mImmersiveModeConfirmation.confirmCurrentPrompt();
6408 updateSystemUiVisibilityLw();
6413 // Called on the PowerManager's Notifier thread.
6415 public void startedGoingToSleep(int why) {
6416 if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
6417 mCameraGestureTriggeredDuringGoingToSleep = false;
6418 mGoingToSleep = true;
6419 if (mKeyguardDelegate != null) {
6420 mKeyguardDelegate.onStartedGoingToSleep(why);
6424 // Called on the PowerManager's Notifier thread.
6426 public void finishedGoingToSleep(int why) {
6427 EventLog.writeEvent(70000, 0);
6428 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
6429 MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
6431 mGoingToSleep = false;
6433 // We must get this work done here because the power manager will drop
6434 // the wake lock and let the system suspend once this function returns.
6435 synchronized (mLock) {
6437 updateWakeGestureListenerLp();
6438 updateOrientationListenerLp();
6439 updateLockScreenTimeout();
6441 if (mKeyguardDelegate != null) {
6442 mKeyguardDelegate.onFinishedGoingToSleep(why,
6443 mCameraGestureTriggeredDuringGoingToSleep);
6445 mCameraGestureTriggeredDuringGoingToSleep = false;
6448 // Called on the PowerManager's Notifier thread.
6450 public void startedWakingUp() {
6451 EventLog.writeEvent(70000, 1);
6452 if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
6454 // Since goToSleep performs these functions synchronously, we must
6455 // do the same here. We cannot post this work to a handler because
6456 // that might cause it to become reordered with respect to what
6457 // may happen in a future call to goToSleep.
6458 synchronized (mLock) {
6461 updateWakeGestureListenerLp();
6462 updateOrientationListenerLp();
6463 updateLockScreenTimeout();
6466 if (mKeyguardDelegate != null) {
6467 mKeyguardDelegate.onStartedWakingUp();
6471 // Called on the PowerManager's Notifier thread.
6473 public void finishedWakingUp() {
6474 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
6477 private void wakeUpFromPowerKey(long eventTime) {
6478 wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
6481 private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
6482 final boolean theaterModeEnabled = isTheaterModeEnabled();
6483 if (!wakeInTheaterMode && theaterModeEnabled) {
6487 if (theaterModeEnabled) {
6488 Settings.Global.putInt(mContext.getContentResolver(),
6489 Settings.Global.THEATER_MODE_ON, 0);
6492 mPowerManager.wakeUp(wakeTime, reason);
6496 private void finishKeyguardDrawn() {
6497 synchronized (mLock) {
6498 if (!mScreenOnEarly || mKeyguardDrawComplete) {
6499 return; // We are not awake yet or we have already informed of this event.
6502 mKeyguardDrawComplete = true;
6503 if (mKeyguardDelegate != null) {
6504 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6506 mWindowManagerDrawComplete = false;
6509 // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
6510 // as well as enabling the orientation change logic/sensor.
6511 mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
6512 WAITING_FOR_DRAWN_TIMEOUT);
6515 // Called on the DisplayManager's DisplayPowerController thread.
6517 public void screenTurnedOff() {
6518 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
6520 updateScreenOffSleepToken(true);
6521 synchronized (mLock) {
6522 mScreenOnEarly = false;
6523 mScreenOnFully = false;
6524 mKeyguardDrawComplete = false;
6525 mWindowManagerDrawComplete = false;
6526 mScreenOnListener = null;
6527 updateOrientationListenerLp();
6529 if (mKeyguardDelegate != null) {
6530 mKeyguardDelegate.onScreenTurnedOff();
6533 reportScreenStateToVrManager(false);
6536 // Called on the DisplayManager's DisplayPowerController thread.
6538 public void screenTurningOn(final ScreenOnListener screenOnListener) {
6539 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
6541 updateScreenOffSleepToken(false);
6542 synchronized (mLock) {
6543 mScreenOnEarly = true;
6544 mScreenOnFully = false;
6545 mKeyguardDrawComplete = false;
6546 mWindowManagerDrawComplete = false;
6547 mScreenOnListener = screenOnListener;
6549 if (mKeyguardDelegate != null) {
6550 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6551 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
6552 mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
6554 if (DEBUG_WAKEUP) Slog.d(TAG,
6555 "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
6556 finishKeyguardDrawn();
6561 // Called on the DisplayManager's DisplayPowerController thread.
6563 public void screenTurnedOn() {
6564 synchronized (mLock) {
6565 if (mKeyguardDelegate != null) {
6566 mKeyguardDelegate.onScreenTurnedOn();
6569 reportScreenStateToVrManager(true);
6572 private void reportScreenStateToVrManager(boolean isScreenOn) {
6573 if (mVrManagerInternal == null) {
6576 mVrManagerInternal.onScreenStateChanged(isScreenOn);
6579 private void exitPersistentVrMode() {
6580 if (mVrManagerInternal == null) {
6583 mVrManagerInternal.setPersistentVrModeEnabled(false);
6586 private void finishWindowsDrawn() {
6587 synchronized (mLock) {
6588 if (!mScreenOnEarly || mWindowManagerDrawComplete) {
6589 return; // Screen is not turned on or we did already handle this case earlier.
6592 mWindowManagerDrawComplete = true;
6595 finishScreenTurningOn();
6598 private void finishScreenTurningOn() {
6599 synchronized (mLock) {
6600 // We have just finished drawing screen content. Since the orientation listener
6601 // gets only installed when all windows are drawn, we try to install it again.
6602 updateOrientationListenerLp();
6604 final ScreenOnListener listener;
6605 final boolean enableScreen;
6606 synchronized (mLock) {
6607 if (DEBUG_WAKEUP) Slog.d(TAG,
6608 "finishScreenTurningOn: mAwake=" + mAwake
6609 + ", mScreenOnEarly=" + mScreenOnEarly
6610 + ", mScreenOnFully=" + mScreenOnFully
6611 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
6612 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
6614 if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
6615 || (mAwake && !mKeyguardDrawComplete)) {
6616 return; // spurious or not ready yet
6619 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
6620 listener = mScreenOnListener;
6621 mScreenOnListener = null;
6622 mScreenOnFully = true;
6624 // Remember the first time we draw the keyguard so we know when we're done with
6625 // the main part of booting and can enable the screen and hide boot messages.
6626 if (!mKeyguardDrawnOnce && mAwake) {
6627 mKeyguardDrawnOnce = true;
6628 enableScreen = true;
6629 if (mBootMessageNeedsHiding) {
6630 mBootMessageNeedsHiding = false;
6634 enableScreen = false;
6638 if (listener != null) {
6639 listener.onScreenOn();
6644 mWindowManager.enableScreenIfNeeded();
6645 } catch (RemoteException unhandled) {
6650 private void handleHideBootMessage() {
6651 synchronized (mLock) {
6652 if (!mKeyguardDrawnOnce) {
6653 mBootMessageNeedsHiding = true;
6654 return; // keyguard hasn't drawn the first time yet, not done booting
6658 if (mBootMsgDialog != null) {
6659 if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
6660 mBootMsgDialog.dismiss();
6661 mBootMsgDialog = null;
6666 public boolean isScreenOn() {
6667 return mScreenOnFully;
6670 /** {@inheritDoc} */
6672 public void enableKeyguard(boolean enabled) {
6673 if (mKeyguardDelegate != null) {
6674 mKeyguardDelegate.setKeyguardEnabled(enabled);
6678 /** {@inheritDoc} */
6680 public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
6681 if (mKeyguardDelegate != null) {
6682 mKeyguardDelegate.verifyUnlock(callback);
6687 public boolean isKeyguardShowingAndNotOccluded() {
6688 if (mKeyguardDelegate == null) return false;
6689 return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
6693 public boolean isKeyguardTrustedLw() {
6694 if (mKeyguardDelegate == null) return false;
6695 return mKeyguardDelegate.isTrusted();
6698 /** {@inheritDoc} */
6700 public boolean isKeyguardLocked() {
6701 return keyguardOn();
6704 /** {@inheritDoc} */
6706 public boolean isKeyguardSecure(int userId) {
6707 if (mKeyguardDelegate == null) return false;
6708 return mKeyguardDelegate.isSecure(userId);
6711 /** {@inheritDoc} */
6713 public boolean isKeyguardOccluded() {
6714 if (mKeyguardDelegate == null) return false;
6715 return mKeyguardOccluded;
6718 /** {@inheritDoc} */
6720 public boolean inKeyguardRestrictedKeyInputMode() {
6721 if (mKeyguardDelegate == null) return false;
6722 return mKeyguardDelegate.isInputRestricted();
6726 public void dismissKeyguardLw(IKeyguardDismissCallback callback) {
6727 if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
6728 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
6730 // ask the keyguard to prompt the user to authenticate if necessary
6731 mKeyguardDelegate.dismiss(callback);
6732 } else if (callback != null) {
6734 callback.onDismissError();
6735 } catch (RemoteException e) {
6736 Slog.w(TAG, "Failed to call callback", e);
6742 public boolean isKeyguardDrawnLw() {
6743 synchronized (mLock) {
6744 return mKeyguardDrawnOnce;
6749 public boolean isShowingDreamLw() {
6750 return mShowingDream;
6754 public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
6755 if (mKeyguardDelegate != null) {
6756 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
6757 mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
6762 public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6764 outInsets.setEmpty();
6766 // Navigation bar and status bar.
6767 getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
6768 outInsets.top = mStatusBarHeight;
6772 public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6774 outInsets.setEmpty();
6776 // Only navigation bar
6777 if (mHasNavigationBar) {
6778 int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
6779 if (position == NAV_BAR_BOTTOM) {
6780 outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
6781 } else if (position == NAV_BAR_RIGHT) {
6782 outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
6783 } else if (position == NAV_BAR_LEFT) {
6784 outInsets.left = getNavigationBarWidth(displayRotation, mUiMode);
6790 public boolean isNavBarForcedShownLw(WindowState windowState) {
6791 return mForceShowSystemBars;
6795 public boolean isDockSideAllowed(int dockSide) {
6797 // We do not allow all dock sides at which the navigation bar touches the docked stack.
6798 if (!mNavigationBarCanMove) {
6799 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT;
6801 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT;
6805 void sendCloseSystemWindows() {
6806 PhoneWindow.sendCloseSystemWindows(mContext, null);
6809 void sendCloseSystemWindows(String reason) {
6810 PhoneWindow.sendCloseSystemWindows(mContext, reason);
6814 public int rotationForOrientationLw(int orientation, int lastRotation) {
6816 Slog.v(TAG, "rotationForOrientationLw(orient="
6817 + orientation + ", last=" + lastRotation
6818 + "); user=" + mUserRotation + " "
6819 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
6820 ? "USER_ROTATION_LOCKED" : "")
6824 if (mForceDefaultOrientation) {
6825 return Surface.ROTATION_0;
6828 synchronized (mLock) {
6829 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
6830 if (sensorRotation < 0) {
6831 sensorRotation = lastRotation;
6834 final int preferredRotation;
6835 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
6836 // Ignore sensor when lid switch is open and rotation is forced.
6837 preferredRotation = mLidOpenRotation;
6838 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
6839 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
6840 // Ignore sensor when in car dock unless explicitly enabled.
6841 // This case can override the behavior of NOSENSOR, and can also
6842 // enable 180 degree rotation while docked.
6843 preferredRotation = mCarDockEnablesAccelerometer
6844 ? sensorRotation : mCarDockRotation;
6845 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
6846 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
6847 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
6848 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
6849 // Ignore sensor when in desk dock unless explicitly enabled.
6850 // This case can override the behavior of NOSENSOR, and can also
6851 // enable 180 degree rotation while docked.
6852 preferredRotation = mDeskDockEnablesAccelerometer
6853 ? sensorRotation : mDeskDockRotation;
6854 } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
6855 // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
6856 // Note that the dock orientation overrides the HDMI orientation.
6857 preferredRotation = mDemoHdmiRotation;
6858 } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
6859 && mUndockedHdmiRotation >= 0) {
6860 // Ignore sensor when plugged into HDMI and an undocked orientation has
6861 // been specified in the configuration (only for legacy devices without
6862 // full multi-display support).
6863 // Note that the dock orientation overrides the HDMI orientation.
6864 preferredRotation = mUndockedHdmiRotation;
6865 } else if (mDemoRotationLock) {
6866 // Ignore sensor when demo rotation lock is enabled.
6867 // Note that the dock orientation and HDMI rotation lock override this.
6868 preferredRotation = mDemoRotation;
6869 } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
6870 // Application just wants to remain locked in the last rotation.
6871 preferredRotation = lastRotation;
6872 } else if (!mSupportAutoRotation) {
6873 // If we don't support auto-rotation then bail out here and ignore
6874 // the sensor and any rotation lock settings.
6875 preferredRotation = -1;
6876 } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
6877 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
6878 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
6879 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
6880 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
6881 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
6882 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
6883 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6884 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
6885 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
6886 // Otherwise, use sensor only if requested by the application or enabled
6887 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR.
6888 if (mAllowAllRotations < 0) {
6889 // Can't read this during init() because the context doesn't
6890 // have display metrics at that time so we cannot determine
6891 // tablet vs. phone then.
6892 mAllowAllRotations = mContext.getResources().getBoolean(
6893 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
6895 if (sensorRotation != Surface.ROTATION_180
6896 || mAllowAllRotations == 1
6897 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6898 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
6899 preferredRotation = sensorRotation;
6901 preferredRotation = lastRotation;
6903 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
6904 && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
6905 // Apply rotation lock. Does not apply to NOSENSOR.
6906 // The idea is that the user rotation expresses a weak preference for the direction
6907 // of gravity and as NOSENSOR is never affected by gravity, then neither should
6908 // NOSENSOR be affected by rotation lock (although it will be affected by docks).
6909 preferredRotation = mUserRotation;
6911 // No overriding preference.
6912 // We will do exactly what the application asked us to do.
6913 preferredRotation = -1;
6916 switch (orientation) {
6917 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6918 // Return portrait unless overridden.
6919 if (isAnyPortrait(preferredRotation)) {
6920 return preferredRotation;
6922 return mPortraitRotation;
6924 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6925 // Return landscape unless overridden.
6926 if (isLandscapeOrSeascape(preferredRotation)) {
6927 return preferredRotation;
6929 return mLandscapeRotation;
6931 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6932 // Return reverse portrait unless overridden.
6933 if (isAnyPortrait(preferredRotation)) {
6934 return preferredRotation;
6936 return mUpsideDownRotation;
6938 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6939 // Return seascape unless overridden.
6940 if (isLandscapeOrSeascape(preferredRotation)) {
6941 return preferredRotation;
6943 return mSeascapeRotation;
6945 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6946 case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
6947 // Return either landscape rotation.
6948 if (isLandscapeOrSeascape(preferredRotation)) {
6949 return preferredRotation;
6951 if (isLandscapeOrSeascape(lastRotation)) {
6952 return lastRotation;
6954 return mLandscapeRotation;
6956 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6957 case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
6958 // Return either portrait rotation.
6959 if (isAnyPortrait(preferredRotation)) {
6960 return preferredRotation;
6962 if (isAnyPortrait(lastRotation)) {
6963 return lastRotation;
6965 return mPortraitRotation;
6968 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
6969 // just return the preferred orientation we already calculated.
6970 if (preferredRotation >= 0) {
6971 return preferredRotation;
6973 return Surface.ROTATION_0;
6979 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
6980 switch (orientation) {
6981 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6982 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6983 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6984 return isAnyPortrait(rotation);
6986 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6987 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6988 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6989 return isLandscapeOrSeascape(rotation);
6997 public void setRotationLw(int rotation) {
6998 mOrientationListener.setCurrentRotation(rotation);
7001 private boolean isLandscapeOrSeascape(int rotation) {
7002 return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
7005 private boolean isAnyPortrait(int rotation) {
7006 return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
7010 public int getUserRotationMode() {
7011 return Settings.System.getIntForUser(mContext.getContentResolver(),
7012 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
7013 WindowManagerPolicy.USER_ROTATION_FREE :
7014 WindowManagerPolicy.USER_ROTATION_LOCKED;
7017 // User rotation: to be used when all else fails in assigning an orientation to the device
7019 public void setUserRotationMode(int mode, int rot) {
7020 ContentResolver res = mContext.getContentResolver();
7022 // mUserRotationMode and mUserRotation will be assigned by the content observer
7023 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
7024 Settings.System.putIntForUser(res,
7025 Settings.System.USER_ROTATION,
7027 UserHandle.USER_CURRENT);
7028 Settings.System.putIntForUser(res,
7029 Settings.System.ACCELEROMETER_ROTATION,
7031 UserHandle.USER_CURRENT);
7033 Settings.System.putIntForUser(res,
7034 Settings.System.ACCELEROMETER_ROTATION,
7036 UserHandle.USER_CURRENT);
7041 public void setSafeMode(boolean safeMode) {
7042 mSafeMode = safeMode;
7043 performHapticFeedbackLw(null, safeMode
7044 ? HapticFeedbackConstants.SAFE_MODE_ENABLED
7045 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
7048 static long[] getLongIntArray(Resources r, int resid) {
7049 int[] ar = r.getIntArray(resid);
7053 long[] out = new long[ar.length];
7054 for (int i=0; i<ar.length; i++) {
7060 /** {@inheritDoc} */
7062 public void systemReady() {
7063 mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
7064 new StateCallback() {
7066 public void onTrustedChanged() {
7067 mWindowManagerFuncs.notifyKeyguardTrustedChanged();
7070 mKeyguardDelegate.onSystemReady();
7072 mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
7073 if (mVrManagerInternal != null) {
7074 mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
7077 readCameraLensCoverState();
7079 boolean bindKeyguardNow;
7080 synchronized (mLock) {
7081 updateOrientationListenerLp();
7082 mSystemReady = true;
7083 mHandler.post(new Runnable() {
7090 bindKeyguardNow = mDeferBindKeyguard;
7091 if (bindKeyguardNow) {
7092 // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now.
7093 mDeferBindKeyguard = false;
7097 if (bindKeyguardNow) {
7098 mKeyguardDelegate.bindService(mContext);
7099 mKeyguardDelegate.onBootCompleted();
7101 mSystemGestures.systemReady();
7102 mImmersiveModeConfirmation.systemReady();
7105 /** {@inheritDoc} */
7107 public void systemBooted() {
7108 boolean bindKeyguardNow = false;
7109 synchronized (mLock) {
7110 // Time to bind Keyguard; take care to only bind it once, either here if ready or
7111 // in systemReady if not.
7112 if (mKeyguardDelegate != null) {
7113 bindKeyguardNow = true;
7115 // Because mKeyguardDelegate is null, we know that the synchronized block in
7116 // systemReady didn't run yet and setting this will actually have an effect.
7117 mDeferBindKeyguard = true;
7120 if (bindKeyguardNow) {
7121 mKeyguardDelegate.bindService(mContext);
7122 mKeyguardDelegate.onBootCompleted();
7124 synchronized (mLock) {
7125 mSystemBooted = true;
7128 screenTurningOn(null);
7132 ProgressDialog mBootMsgDialog = null;
7134 /** {@inheritDoc} */
7136 public void showBootMessage(final CharSequence msg, final boolean always) {
7137 mHandler.post(new Runnable() {
7138 @Override public void run() {
7139 if (mBootMsgDialog == null) {
7141 if (mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK)) {
7142 theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
7147 mBootMsgDialog = new ProgressDialog(mContext, theme) {
7148 // This dialog will consume all events coming in to
7149 // it, to avoid it trying to do things too early in boot.
7150 @Override public boolean dispatchKeyEvent(KeyEvent event) {
7153 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7156 @Override public boolean dispatchTouchEvent(MotionEvent ev) {
7159 @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
7162 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
7165 @Override public boolean dispatchPopulateAccessibilityEvent(
7166 AccessibilityEvent event) {
7170 if (mContext.getPackageManager().isUpgrade()) {
7171 mBootMsgDialog.setTitle(R.string.android_upgrading_title);
7173 mBootMsgDialog.setTitle(R.string.android_start_title);
7175 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
7176 mBootMsgDialog.setIndeterminate(true);
7177 mBootMsgDialog.getWindow().setType(
7178 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
7179 mBootMsgDialog.getWindow().addFlags(
7180 WindowManager.LayoutParams.FLAG_DIM_BEHIND
7181 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
7182 mBootMsgDialog.getWindow().setDimAmount(1);
7183 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
7184 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
7185 mBootMsgDialog.getWindow().setAttributes(lp);
7186 mBootMsgDialog.setCancelable(false);
7187 mBootMsgDialog.show();
7189 mBootMsgDialog.setMessage(msg);
7194 /** {@inheritDoc} */
7196 public void hideBootMessages() {
7197 mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
7200 /** {@inheritDoc} */
7202 public void userActivity() {
7203 // ***************************************
7204 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
7205 // ***************************************
7206 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
7207 // WITH ITS LOCKS HELD.
7209 // This code must be VERY careful about the locks
7211 // In fact, the current code acquires way too many,
7212 // and probably has lurking deadlocks.
7214 synchronized (mScreenLockTimeout) {
7215 if (mLockScreenTimerActive) {
7217 mHandler.removeCallbacks(mScreenLockTimeout);
7218 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7223 class ScreenLockTimeout implements Runnable {
7228 synchronized (this) {
7229 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
7230 if (mKeyguardDelegate != null) {
7231 mKeyguardDelegate.doKeyguardTimeout(options);
7233 mLockScreenTimerActive = false;
7238 public void setLockOptions(Bundle options) {
7239 this.options = options;
7243 ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
7246 public void lockNow(Bundle options) {
7247 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
7248 mHandler.removeCallbacks(mScreenLockTimeout);
7249 if (options != null) {
7250 // In case multiple calls are made to lockNow, we don't wipe out the options
7251 // until the runnable actually executes.
7252 mScreenLockTimeout.setLockOptions(options);
7254 mHandler.post(mScreenLockTimeout);
7257 private void updateLockScreenTimeout() {
7258 synchronized (mScreenLockTimeout) {
7259 boolean enable = (mAllowLockscreenWhenOn && mAwake &&
7260 mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
7261 if (mLockScreenTimerActive != enable) {
7263 if (localLOGV) Log.v(TAG, "setting lockscreen timer");
7264 mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
7265 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7267 if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
7268 mHandler.removeCallbacks(mScreenLockTimeout);
7270 mLockScreenTimerActive = enable;
7275 private void updateDreamingSleepToken(boolean acquire) {
7277 if (mDreamingSleepToken == null) {
7278 mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream");
7281 if (mDreamingSleepToken != null) {
7282 mDreamingSleepToken.release();
7283 mDreamingSleepToken = null;
7288 private void updateScreenOffSleepToken(boolean acquire) {
7290 if (mScreenOffSleepToken == null) {
7291 mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff");
7294 if (mScreenOffSleepToken != null) {
7295 mScreenOffSleepToken.release();
7296 mScreenOffSleepToken = null;
7301 /** {@inheritDoc} */
7303 public void enableScreenAfterBoot() {
7305 applyLidSwitchState();
7306 updateRotation(true);
7309 private void applyLidSwitchState() {
7310 if (mLidState == LID_CLOSED && mLidControlsSleep) {
7311 mPowerManager.goToSleep(SystemClock.uptimeMillis(),
7312 PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
7313 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
7314 } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
7315 mWindowManagerFuncs.lockDeviceNow();
7318 synchronized (mLock) {
7319 updateWakeGestureListenerLp();
7323 void updateUiMode() {
7324 if (mUiModeManager == null) {
7325 mUiModeManager = IUiModeManager.Stub.asInterface(
7326 ServiceManager.getService(Context.UI_MODE_SERVICE));
7329 mUiMode = mUiModeManager.getCurrentModeType();
7330 } catch (RemoteException e) {
7334 void updateRotation(boolean alwaysSendConfiguration) {
7336 //set orientation on WindowManager
7337 mWindowManager.updateRotation(alwaysSendConfiguration, false);
7338 } catch (RemoteException e) {
7343 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
7345 //set orientation on WindowManager
7346 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
7347 } catch (RemoteException e) {
7353 * Return an Intent to launch the currently active dock app as home. Returns
7354 * null if the standard home should be launched, which is the case if any of the following is
7357 * <li>The device is not in either car mode or desk mode
7358 * <li>The device is in car mode but mEnableCarDockHomeCapture is false
7359 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
7360 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
7361 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
7363 * @return A dock intent.
7365 Intent createHomeDockIntent() {
7366 Intent intent = null;
7368 // What home does is based on the mode, not the dock state. That
7369 // is, when in car mode you should be taken to car home regardless
7370 // of whether we are actually in a car dock.
7371 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
7372 if (mEnableCarDockHomeCapture) {
7373 intent = mCarDockIntent;
7375 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
7376 if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
7377 intent = mDeskDockIntent;
7379 } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
7380 && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7381 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
7382 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
7383 // Always launch dock home from home when watch is docked, if it exists.
7384 intent = mDeskDockIntent;
7385 } else if (mUiMode == Configuration.UI_MODE_TYPE_VR_HEADSET) {
7386 if (ENABLE_VR_HEADSET_HOME_CAPTURE) {
7387 intent = mVrHeadsetHomeIntent;
7391 if (intent == null) {
7395 ActivityInfo ai = null;
7396 ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
7398 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
7401 ai = info.activityInfo;
7404 && ai.metaData != null
7405 && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
7406 intent = new Intent(intent);
7407 intent.setClassName(ai.packageName, ai.name);
7414 void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
7415 if (awakenFromDreams) {
7419 Intent dock = createHomeDockIntent();
7423 dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7425 startActivityAsUser(dock, UserHandle.CURRENT);
7427 } catch (ActivityNotFoundException e) {
7434 intent = new Intent(mHomeIntent);
7435 intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7437 intent = mHomeIntent;
7440 startActivityAsUser(intent, UserHandle.CURRENT);
7444 * goes to the home screen
7445 * @return whether it did anything
7448 if (!isUserSetupComplete()) {
7449 Slog.i(TAG, "Not going home because user setup is in progress.");
7453 // This code always brings home to the front.
7455 ActivityManager.getService().stopAppSwitches();
7456 } catch (RemoteException e) {
7458 sendCloseSystemWindows();
7459 startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
7461 // This code brings home to the front or, if it is already
7462 // at the front, puts the device to sleep.
7464 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
7465 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
7466 Log.d(TAG, "UTS-TEST-MODE");
7468 ActivityManager.getService().stopAppSwitches();
7469 sendCloseSystemWindows();
7470 Intent dock = createHomeDockIntent();
7472 int result = ActivityManager.getService()
7473 .startActivityAsUser(null, null, dock,
7474 dock.resolveTypeIfNeeded(mContext.getContentResolver()),
7476 ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7477 null, null, UserHandle.USER_CURRENT);
7478 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7483 int result = ActivityManager.getService()
7484 .startActivityAsUser(null, null, mHomeIntent,
7485 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
7487 ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7488 null, null, UserHandle.USER_CURRENT);
7489 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7492 } catch (RemoteException ex) {
7493 // bummer, the activity manager, which is in this process, is dead
7500 public void setCurrentOrientationLw(int newOrientation) {
7501 synchronized (mLock) {
7502 if (newOrientation != mCurrentAppOrientation) {
7503 mCurrentAppOrientation = newOrientation;
7504 updateOrientationListenerLp();
7509 private boolean isTheaterModeEnabled() {
7510 return Settings.Global.getInt(mContext.getContentResolver(),
7511 Settings.Global.THEATER_MODE_ON, 0) == 1;
7514 private boolean areSystemNavigationKeysEnabled() {
7515 return Settings.Secure.getIntForUser(mContext.getContentResolver(),
7516 Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
7520 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
7521 if (!mVibrator.hasVibrator()) {
7524 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
7525 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
7526 if (hapticsDisabled && !always) {
7529 long[] pattern = null;
7531 case HapticFeedbackConstants.LONG_PRESS:
7532 pattern = mLongPressVibePattern;
7534 case HapticFeedbackConstants.VIRTUAL_KEY:
7535 pattern = mVirtualKeyVibePattern;
7537 case HapticFeedbackConstants.KEYBOARD_TAP:
7538 pattern = mKeyboardTapVibePattern;
7540 case HapticFeedbackConstants.CLOCK_TICK:
7541 pattern = mClockTickVibePattern;
7543 case HapticFeedbackConstants.CALENDAR_DATE:
7544 pattern = mCalendarDateVibePattern;
7546 case HapticFeedbackConstants.SAFE_MODE_DISABLED:
7547 pattern = mSafeModeDisabledVibePattern;
7549 case HapticFeedbackConstants.SAFE_MODE_ENABLED:
7550 pattern = mSafeModeEnabledVibePattern;
7552 case HapticFeedbackConstants.CONTEXT_CLICK:
7553 pattern = mContextClickVibePattern;
7559 String owningPackage;
7561 owningUid = win.getOwningUid();
7562 owningPackage = win.getOwningPackage();
7564 owningUid = android.os.Process.myUid();
7565 owningPackage = mContext.getOpPackageName();
7567 if (pattern.length == 1) {
7568 // One-shot vibration
7569 mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES);
7571 // Pattern vibration
7572 mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES);
7578 public void keepScreenOnStartedLw() {
7582 public void keepScreenOnStoppedLw() {
7583 if (isKeyguardShowingAndNotOccluded()) {
7584 mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
7588 private int updateSystemUiVisibilityLw() {
7589 // If there is no window focused, there will be nobody to handle the events
7590 // anyway, so just hang on in whatever state we're in until things settle down.
7591 WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
7592 : mTopFullscreenOpaqueWindowState;
7593 if (winCandidate == null) {
7596 if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
7597 // The immersive mode confirmation should never affect the system bar visibility,
7598 // otherwise it will unhide the navigation bar and hide itself.
7599 winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState;
7600 if (winCandidate == null) {
7604 final WindowState win = winCandidate;
7605 if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mKeyguardOccluded) {
7606 // We are updating at a point where the keyguard has gotten
7607 // focus, but we were last in a state where the top window is
7608 // hiding it. This is probably because the keyguard as been
7609 // shown while the top window was displayed, so we want to ignore
7610 // it here because this is just a very transient change and it
7611 // will quickly lose focus once it correctly gets hidden.
7615 int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
7616 & ~mResettingSystemUiFlags
7617 & ~mForceClearedSystemUiFlags;
7618 if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
7619 tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
7622 final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
7623 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
7624 final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
7625 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
7626 mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);
7627 mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);
7628 final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
7629 final int diff = visibility ^ mLastSystemUiFlags;
7630 final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
7631 final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
7632 final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
7633 if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
7634 && mFocusedApp == win.getAppToken()
7635 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
7636 && mLastDockedStackBounds.equals(mDockedStackBounds)) {
7639 mLastSystemUiFlags = visibility;
7640 mLastFullscreenStackSysUiFlags = fullscreenVisibility;
7641 mLastDockedStackSysUiFlags = dockedVisibility;
7642 mLastFocusNeedsMenu = needsMenu;
7643 mFocusedApp = win.getAppToken();
7644 final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
7645 final Rect dockedStackBounds = new Rect(mDockedStackBounds);
7646 mHandler.post(new Runnable() {
7649 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
7650 if (statusbar != null) {
7651 statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
7652 dockedVisibility, 0xffffffff, fullscreenStackBounds,
7653 dockedStackBounds, win.toString());
7654 statusbar.topAppWindowChanged(needsMenu);
7661 private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
7662 WindowState statusColorWin = isStatusBarKeyguard() && !mKeyguardOccluded
7666 if (statusColorWin != null) {
7667 if (statusColorWin == opaque) {
7668 // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7670 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7671 vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
7672 & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7673 } else if (statusColorWin != null && statusColorWin.isDimming()) {
7674 // Otherwise if it's dimming, clear the light flag.
7675 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7681 private int updateLightNavigationBarLw(int vis, WindowState opaque,
7682 WindowState opaqueOrDimming) {
7683 final WindowState imeWin = mWindowManagerFuncs.getInputMethodWindowLw();
7685 final WindowState navColorWin;
7686 if (imeWin != null && imeWin.isVisibleLw()) {
7687 navColorWin = imeWin;
7689 navColorWin = opaqueOrDimming;
7692 if (navColorWin != null) {
7693 if (navColorWin == opaque) {
7694 // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7696 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7697 vis |= PolicyControl.getSystemUiVisibility(navColorWin, null)
7698 & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7699 } else if (navColorWin.isDimming() || navColorWin == imeWin) {
7700 // Otherwise if it's dimming or it's the IME window, clear the light flag.
7701 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7707 private boolean drawsSystemBarBackground(WindowState win) {
7708 return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
7711 private boolean forcesDrawStatusBarBackground(WindowState win) {
7712 return win == null || (win.getAttrs().privateFlags
7713 & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
7716 private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
7717 final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
7718 final boolean freeformStackVisible =
7719 mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
7720 final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
7722 // We need to force system bars when the docked stack is visible, when the freeform stack
7723 // is visible but also when we are resizing for the transitions when docked stack
7724 // visibility changes.
7725 mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
7726 final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
7728 // apply translucent bar vis flags
7729 WindowState fullscreenTransWin = isStatusBarKeyguard() && !mKeyguardOccluded
7731 : mTopFullscreenOpaqueWindowState;
7732 vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7733 vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7734 final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
7735 mTopDockedOpaqueWindowState, 0, 0);
7737 final boolean fullscreenDrawsStatusBarBackground =
7738 (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
7739 && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
7740 || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
7741 final boolean dockedDrawsStatusBarBackground =
7742 (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
7743 && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
7744 || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
7746 // prevent status bar interaction from clearing certain flags
7747 int type = win.getAttrs().type;
7748 boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
7749 if (statusBarHasFocus && !isStatusBarKeyguard()) {
7750 int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
7751 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
7752 | View.SYSTEM_UI_FLAG_IMMERSIVE
7753 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
7754 | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7755 if (mKeyguardOccluded) {
7756 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
7758 vis = (vis & ~flags) | (oldVis & flags);
7761 if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
7762 vis |= View.STATUS_BAR_TRANSPARENT;
7763 vis &= ~View.STATUS_BAR_TRANSLUCENT;
7764 } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
7765 || forceOpaqueStatusBar) {
7766 vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
7769 vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
7771 // update status bar
7772 boolean immersiveSticky =
7773 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7774 final boolean hideStatusBarWM =
7775 mTopFullscreenOpaqueWindowState != null
7776 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
7777 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
7778 final boolean hideStatusBarSysui =
7779 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
7780 final boolean hideNavBarSysui =
7781 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
7783 final boolean transientStatusBarAllowed = mStatusBar != null
7784 && (statusBarHasFocus || (!mForceShowSystemBars
7785 && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
7787 final boolean transientNavBarAllowed = mNavigationBar != null
7788 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
7790 final long now = SystemClock.uptimeMillis();
7791 final boolean pendingPanic = mPendingPanicGestureUptime != 0
7792 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
7793 if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
7794 // The user performed the panic gesture recently, we're about to hide the bars,
7795 // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
7796 mPendingPanicGestureUptime = 0;
7797 mStatusBarController.showTransient();
7798 if (!isNavBarEmpty(vis)) {
7799 mNavigationBarController.showTransient();
7803 final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
7804 && !transientStatusBarAllowed && hideStatusBarSysui;
7805 final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
7806 && !transientNavBarAllowed;
7807 if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
7808 // clear the clearable flags instead
7809 clearClearableFlagsLw();
7810 vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
7813 final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
7814 immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7815 final boolean navAllowedHidden = immersive || immersiveSticky;
7817 if (hideNavBarSysui && !navAllowedHidden
7818 && getWindowLayerLw(win) > getWindowLayerFromTypeLw(TYPE_INPUT_CONSUMER)) {
7819 // We can't hide the navbar from this window otherwise the input consumer would not get
7820 // the input events.
7821 vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
7824 vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
7826 // update navigation bar
7827 boolean oldImmersiveMode = isImmersiveMode(oldVis);
7828 boolean newImmersiveMode = isImmersiveMode(vis);
7829 if (win != null && oldImmersiveMode != newImmersiveMode) {
7830 final String pkg = win.getOwningPackage();
7831 mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
7832 isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility()));
7835 vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
7837 vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState,
7838 mTopFullscreenOpaqueOrDimmingWindowState);
7844 * @return the current visibility flags with the nav-bar opacity related flags toggled based
7845 * on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
7847 private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
7848 boolean freeformStackVisible, boolean isDockedDividerResizing) {
7849 if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
7850 if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
7851 visibility = setNavBarOpaqueFlag(visibility);
7853 } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
7854 if (isDockedDividerResizing) {
7855 visibility = setNavBarOpaqueFlag(visibility);
7856 } else if (freeformStackVisible) {
7857 visibility = setNavBarTranslucentFlag(visibility);
7859 visibility = setNavBarOpaqueFlag(visibility);
7863 if (!areTranslucentBarsAllowed()) {
7864 visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
7869 private int setNavBarOpaqueFlag(int visibility) {
7870 return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
7873 private int setNavBarTranslucentFlag(int visibility) {
7874 visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
7875 return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
7878 private void clearClearableFlagsLw() {
7879 int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
7880 if (newVal != mResettingSystemUiFlags) {
7881 mResettingSystemUiFlags = newVal;
7882 mWindowManagerFuncs.reevaluateStatusBarVisibility();
7886 private boolean isImmersiveMode(int vis) {
7887 final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
7888 return mNavigationBar != null
7889 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
7890 && (vis & flags) != 0
7891 && canHideNavigationBar();
7894 private static boolean isNavBarEmpty(int systemUiFlags) {
7895 final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
7896 | View.STATUS_BAR_DISABLE_BACK
7897 | View.STATUS_BAR_DISABLE_RECENT);
7899 return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
7903 * @return whether the navigation or status bar can be made translucent
7905 * This should return true unless touch exploration is not enabled or
7906 * R.boolean.config_enableTranslucentDecor is false.
7908 private boolean areTranslucentBarsAllowed() {
7909 return mTranslucentDecorEnabled;
7912 // Use this instead of checking config_showNavigationBar so that it can be consistently
7913 // overridden by qemu.hw.mainkeys in the emulator.
7915 public boolean hasNavigationBar() {
7916 return mHasNavigationBar;
7920 public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
7921 mLastInputMethodWindow = ime;
7922 mLastInputMethodTargetWindow = target;
7926 public int getInputMethodWindowVisibleHeightLw() {
7927 return mDockBottom - mCurBottom;
7931 public void setCurrentUserLw(int newUserId) {
7932 mCurrentUserId = newUserId;
7933 if (mKeyguardDelegate != null) {
7934 mKeyguardDelegate.setCurrentUser(newUserId);
7936 StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
7937 if (statusBar != null) {
7938 statusBar.setCurrentUser(newUserId);
7940 setLastInputMethodWindowLw(null, null);
7944 public void setSwitchingUser(boolean switching) {
7945 mKeyguardDelegate.setSwitchingUser(switching);
7949 public boolean canMagnifyWindow(int windowType) {
7950 switch (windowType) {
7951 case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
7952 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
7953 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
7954 case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
7962 public boolean isTopLevelWindow(int windowType) {
7963 if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
7964 && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
7965 return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
7971 public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
7972 // For the upside down rotation we don't rotate seamlessly as the navigation
7973 // bar moves position.
7974 // Note most apps (using orientation:sensor or user as opposed to fullSensor)
7975 // will not enter the reverse portrait orientation, so actually the
7976 // orientation won't change at all.
7977 if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
7980 // If the navigation bar can't change sides, then it will
7981 // jump when we change orientations and we don't rotate
7983 if (!mNavigationBarCanMove) {
7986 int delta = newRotation - oldRotation;
7987 if (delta < 0) delta += 4;
7988 // Likewise we don't rotate seamlessly for 180 degree rotations
7989 // in this case the surfaces never resize, and our logic to
7990 // revert the transformations on size change will fail. We could
7991 // fix this in the future with the "tagged" frames idea.
7992 if (delta == Surface.ROTATION_180) {
7996 final WindowState w = mTopFullscreenOpaqueWindowState;
7997 if (w != mFocusedWindow) {
8001 // We only enable seamless rotation if the top window has requested
8002 // it and is in the fullscreen opaque state. Seamless rotation
8003 // requires freezing various Surface states and won't work well
8004 // with animations, so we disable it in the animation case for now.
8005 if (w != null && !w.isAnimatingLw() &&
8006 ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) ||
8007 (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) {
8014 public void dump(String prefix, PrintWriter pw, String[] args) {
8015 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
8016 pw.print(" mSystemReady="); pw.print(mSystemReady);
8017 pw.print(" mSystemBooted="); pw.println(mSystemBooted);
8018 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
8019 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
8020 pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
8021 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
8022 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
8023 || mForceClearedSystemUiFlags != 0) {
8024 pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
8025 pw.print(Integer.toHexString(mLastSystemUiFlags));
8026 pw.print(" mResettingSystemUiFlags=0x");
8027 pw.print(Integer.toHexString(mResettingSystemUiFlags));
8028 pw.print(" mForceClearedSystemUiFlags=0x");
8029 pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
8031 if (mLastFocusNeedsMenu) {
8032 pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
8033 pw.println(mLastFocusNeedsMenu);
8035 pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
8036 pw.println(mWakeGestureEnabledSetting);
8038 pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
8039 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
8040 pw.print(" mDockMode="); pw.print(mDockMode);
8041 pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
8042 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
8043 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
8044 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
8045 pw.print(" mUserRotation="); pw.print(mUserRotation);
8046 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
8047 pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
8048 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
8049 pw.print(mCarDockEnablesAccelerometer);
8050 pw.print(" mDeskDockEnablesAccelerometer=");
8051 pw.println(mDeskDockEnablesAccelerometer);
8052 pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
8053 pw.print(mLidKeyboardAccessibility);
8054 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
8055 pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
8056 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
8058 pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
8060 pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
8061 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
8063 pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
8064 pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
8065 pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
8066 pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
8067 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
8068 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
8069 pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
8070 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
8071 pw.print(prefix); pw.print("mOrientationSensorEnabled=");
8072 pw.println(mOrientationSensorEnabled);
8073 pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
8074 pw.print(","); pw.print(mOverscanScreenTop);
8075 pw.print(") "); pw.print(mOverscanScreenWidth);
8076 pw.print("x"); pw.println(mOverscanScreenHeight);
8077 if (mOverscanLeft != 0 || mOverscanTop != 0
8078 || mOverscanRight != 0 || mOverscanBottom != 0) {
8079 pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
8080 pw.print(" top="); pw.print(mOverscanTop);
8081 pw.print(" right="); pw.print(mOverscanRight);
8082 pw.print(" bottom="); pw.println(mOverscanBottom);
8084 pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
8085 pw.print(mRestrictedOverscanScreenLeft);
8086 pw.print(","); pw.print(mRestrictedOverscanScreenTop);
8087 pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
8088 pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
8089 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
8090 pw.print(","); pw.print(mUnrestrictedScreenTop);
8091 pw.print(") "); pw.print(mUnrestrictedScreenWidth);
8092 pw.print("x"); pw.println(mUnrestrictedScreenHeight);
8093 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
8094 pw.print(","); pw.print(mRestrictedScreenTop);
8095 pw.print(") "); pw.print(mRestrictedScreenWidth);
8096 pw.print("x"); pw.println(mRestrictedScreenHeight);
8097 pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
8098 pw.print(","); pw.print(mStableFullscreenTop);
8099 pw.print(")-("); pw.print(mStableFullscreenRight);
8100 pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
8101 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
8102 pw.print(","); pw.print(mStableTop);
8103 pw.print(")-("); pw.print(mStableRight);
8104 pw.print(","); pw.print(mStableBottom); pw.println(")");
8105 pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
8106 pw.print(","); pw.print(mSystemTop);
8107 pw.print(")-("); pw.print(mSystemRight);
8108 pw.print(","); pw.print(mSystemBottom); pw.println(")");
8109 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
8110 pw.print(","); pw.print(mCurTop);
8111 pw.print(")-("); pw.print(mCurRight);
8112 pw.print(","); pw.print(mCurBottom); pw.println(")");
8113 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
8114 pw.print(","); pw.print(mContentTop);
8115 pw.print(")-("); pw.print(mContentRight);
8116 pw.print(","); pw.print(mContentBottom); pw.println(")");
8117 pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft);
8118 pw.print(","); pw.print(mVoiceContentTop);
8119 pw.print(")-("); pw.print(mVoiceContentRight);
8120 pw.print(","); pw.print(mVoiceContentBottom); pw.println(")");
8121 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
8122 pw.print(","); pw.print(mDockTop);
8123 pw.print(")-("); pw.print(mDockRight);
8124 pw.print(","); pw.print(mDockBottom); pw.println(")");
8125 pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
8126 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
8127 pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
8128 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
8129 pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
8130 if (mLastInputMethodWindow != null) {
8131 pw.print(prefix); pw.print("mLastInputMethodWindow=");
8132 pw.println(mLastInputMethodWindow);
8134 if (mLastInputMethodTargetWindow != null) {
8135 pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
8136 pw.println(mLastInputMethodTargetWindow);
8138 if (mStatusBar != null) {
8139 pw.print(prefix); pw.print("mStatusBar=");
8140 pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
8141 pw.println(isStatusBarKeyguard());
8143 if (mNavigationBar != null) {
8144 pw.print(prefix); pw.print("mNavigationBar=");
8145 pw.println(mNavigationBar);
8147 if (mFocusedWindow != null) {
8148 pw.print(prefix); pw.print("mFocusedWindow=");
8149 pw.println(mFocusedWindow);
8151 if (mFocusedApp != null) {
8152 pw.print(prefix); pw.print("mFocusedApp=");
8153 pw.println(mFocusedApp);
8155 if (mTopFullscreenOpaqueWindowState != null) {
8156 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
8157 pw.println(mTopFullscreenOpaqueWindowState);
8159 if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
8160 pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
8161 pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
8163 if (mForcingShowNavBar) {
8164 pw.print(prefix); pw.print("mForcingShowNavBar=");
8165 pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
8166 pw.println(mForcingShowNavBarLayer);
8168 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
8169 pw.print(" mKeyguardOccluded="); pw.println(mKeyguardOccluded);
8170 pw.print(" mKeyguardOccludedChanged="); pw.println(mKeyguardOccludedChanged);
8171 pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded);
8172 pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
8173 pw.print(" mForceStatusBarFromKeyguard=");
8174 pw.println(mForceStatusBarFromKeyguard);
8175 pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
8176 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
8177 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
8178 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
8179 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
8180 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
8181 pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior);
8182 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
8183 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
8184 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
8185 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
8186 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
8187 pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
8188 pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
8189 pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
8191 mGlobalKeyManager.dump(prefix, pw);
8192 mStatusBarController.dump(pw, prefix);
8193 mNavigationBarController.dump(pw, prefix);
8194 PolicyControl.dump(prefix, pw);
8196 if (mWakeGestureListener != null) {
8197 mWakeGestureListener.dump(pw, prefix);
8199 if (mOrientationListener != null) {
8200 mOrientationListener.dump(pw, prefix);
8202 if (mBurnInProtectionHelper != null) {
8203 mBurnInProtectionHelper.dump(prefix, pw);
8205 if (mKeyguardDelegate != null) {
8206 mKeyguardDelegate.dump(prefix, pw);