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.app.ActivityManager.StackId.DOCKED_STACK_ID;
20 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
21 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
22 import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
23 import static android.content.pm.PackageManager.FEATURE_TELEVISION;
24 import static android.content.pm.PackageManager.FEATURE_WATCH;
25 import static android.content.res.Configuration.EMPTY;
26 import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
27 import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
28 import static android.view.WindowManager.DOCKED_TOP;
29 import static android.view.WindowManager.DOCKED_LEFT;
30 import static android.view.WindowManager.DOCKED_RIGHT;
31 import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
32 import static android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION;
33 import static android.view.WindowManager.LayoutParams.*;
34 import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
35 import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
36 import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
37 import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
38 import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
39 import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
41 import android.app.ActivityManager;
42 import android.app.ActivityManager.StackId;
43 import android.app.ActivityManagerInternal;
44 import android.app.ActivityManagerInternal.SleepToken;
45 import android.app.ActivityManager.RunningAppProcessInfo;
46 import android.app.ActivityManagerNative;
47 import android.app.IActivityManager;
48 import android.app.AppOpsManager;
49 import android.app.IUiModeManager;
50 import android.app.ProgressDialog;
51 import android.app.SearchManager;
52 import android.app.StatusBarManager;
53 import android.app.UiModeManager;
54 import android.content.ActivityNotFoundException;
55 import android.content.BroadcastReceiver;
56 import android.content.ComponentName;
57 import android.content.ContentResolver;
58 import android.content.Context;
59 import android.content.ContextWrapper;
60 import android.content.Intent;
61 import android.content.IntentFilter;
62 import android.content.ServiceConnection;
63 import android.content.pm.ActivityInfo;
64 import android.content.pm.ApplicationInfo;
65 import android.content.pm.PackageManager;
66 import android.content.pm.ResolveInfo;
67 import android.content.res.CompatibilityInfo;
68 import android.content.res.Configuration;
69 import android.content.res.Resources;
70 import android.content.res.TypedArray;
71 import android.database.ContentObserver;
72 import android.graphics.PixelFormat;
73 import android.graphics.Rect;
74 import android.hardware.hdmi.HdmiControlManager;
75 import android.hardware.hdmi.HdmiPlaybackClient;
76 import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback;
77 import android.hardware.input.InputManagerInternal;
78 import android.hardware.input.InputManager;
79 import android.media.AudioAttributes;
80 import android.media.AudioManager;
81 import android.media.AudioSystem;
82 import android.media.IAudioService;
83 import android.media.Ringtone;
84 import android.media.RingtoneManager;
85 import android.media.session.MediaSessionLegacyHelper;
86 import android.os.Binder;
87 import android.os.Build;
88 import android.os.Bundle;
89 import android.os.Debug;
90 import android.os.FactoryTest;
91 import android.os.Handler;
92 import android.os.IBinder;
93 import android.os.IDeviceIdleController;
94 import android.os.Looper;
95 import android.os.Message;
96 import android.os.Messenger;
97 import android.os.PowerManager;
98 import android.os.PowerManagerInternal;
99 import android.os.Process;
100 import android.os.RemoteException;
101 import android.os.ServiceManager;
102 import android.os.SystemClock;
103 import android.os.SystemProperties;
104 import android.os.UEventObserver;
105 import android.os.UserHandle;
106 import android.os.Vibrator;
107 import android.provider.MediaStore;
108 import android.provider.Settings;
109 import android.service.dreams.DreamManagerInternal;
110 import android.service.dreams.DreamService;
111 import android.service.dreams.IDreamManager;
112 import android.speech.RecognizerIntent;
113 import android.telecom.TelecomManager;
115 import cyanogenmod.hardware.CMHardwareManager;
116 import cyanogenmod.providers.CMSettings;
117 import android.util.DisplayMetrics;
118 import android.util.EventLog;
119 import android.util.Log;
120 import android.util.MutableBoolean;
121 import android.util.Slog;
122 import android.util.SparseArray;
123 import android.util.LongSparseArray;
124 import android.view.Display;
125 import android.view.Gravity;
126 import android.view.HapticFeedbackConstants;
127 import android.view.IApplicationToken;
128 import android.view.IWindowManager;
129 import android.view.InputChannel;
130 import android.view.InputDevice;
131 import android.view.InputEvent;
132 import android.view.InputEventReceiver;
133 import android.view.KeyCharacterMap;
134 import android.view.KeyCharacterMap.FallbackAction;
135 import android.view.KeyEvent;
136 import android.view.MotionEvent;
137 import android.view.Surface;
138 import android.view.View;
139 import android.view.ViewConfiguration;
140 import android.view.WindowManager;
141 import android.view.WindowManagerGlobal;
142 import android.view.WindowManagerInternal;
143 import android.view.WindowManagerPolicy;
144 import android.view.accessibility.AccessibilityEvent;
145 import android.view.accessibility.AccessibilityManager;
146 import android.view.animation.Animation;
147 import android.view.animation.AnimationSet;
148 import android.view.animation.AnimationUtils;
149 import android.widget.Toast;
151 import com.android.internal.R;
152 import com.android.internal.logging.MetricsLogger;
153 import com.android.internal.os.DeviceKeyHandler;
154 import com.android.internal.policy.PhoneWindow;
155 import com.android.internal.policy.IKeyguardService;
156 import com.android.internal.policy.IShortcutService;
157 import com.android.internal.statusbar.IStatusBarService;
158 import com.android.internal.util.ScreenShapeHelper;
159 import com.android.internal.view.RotationPolicy;
160 import com.android.internal.widget.PointerLocationView;
161 import com.android.server.GestureLauncherService;
162 import com.android.server.LocalServices;
163 import com.android.server.policy.keyguard.KeyguardServiceDelegate;
164 import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener;
165 import com.android.server.statusbar.StatusBarManagerInternal;
168 import java.io.FileReader;
169 import java.io.IOException;
170 import java.io.PrintWriter;
171 import java.util.HashSet;
172 import java.util.List;
173 import java.lang.reflect.Constructor;
175 import cyanogenmod.providers.CMSettings;
176 import dalvik.system.PathClassLoader;
179 * WindowManagerPolicy implementation for the Android phone UI. This
180 * introduces a new method suffix, Lp, for an internal lock of the
181 * PhoneWindowManager. This is used to protect some internal state, and
182 * can be acquired with either the Lw and Li lock held, so has the restrictions
183 * of both of those when held.
185 public class PhoneWindowManager implements WindowManagerPolicy {
186 static final String TAG = "WindowManager";
187 static final boolean DEBUG = false;
188 static final boolean localLOGV = false;
189 static final boolean DEBUG_INPUT = false;
190 static final boolean DEBUG_KEYGUARD = false;
191 static final boolean DEBUG_LAYOUT = false;
192 static final boolean DEBUG_STARTING_WINDOW = false;
193 static final boolean DEBUG_WAKEUP = false;
194 static final boolean SHOW_STARTING_ANIMATIONS = true;
195 static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
197 // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
198 // No longer recommended for desk docks;
199 static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
201 static final int SHORT_PRESS_POWER_NOTHING = 0;
202 static final int SHORT_PRESS_POWER_GO_TO_SLEEP = 1;
203 static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2;
204 static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3;
205 static final int SHORT_PRESS_POWER_GO_HOME = 4;
207 static final int LONG_PRESS_POWER_NOTHING = 0;
208 static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
209 static final int LONG_PRESS_POWER_SHUT_OFF = 2;
210 static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
212 static final int LONG_PRESS_BACK_NOTHING = 0;
213 static final int LONG_PRESS_BACK_GO_TO_VOICE_ASSIST = 1;
215 static final int MULTI_PRESS_POWER_NOTHING = 0;
216 static final int MULTI_PRESS_POWER_THEATER_MODE = 1;
217 static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2;
219 // These need to match the documentation/constant in
220 // core/res/res/values/config.xml
221 static final int LONG_PRESS_HOME_NOTHING = 0;
222 static final int LONG_PRESS_HOME_RECENT_SYSTEM_UI = 1;
223 static final int LONG_PRESS_HOME_ASSIST = 2;
224 static final int LAST_LONG_PRESS_HOME_BEHAVIOR = LONG_PRESS_HOME_ASSIST;
226 static final int DOUBLE_TAP_HOME_NOTHING = 0;
227 static final int DOUBLE_TAP_HOME_RECENT_SYSTEM_UI = 1;
229 static final int SHORT_PRESS_WINDOW_NOTHING = 0;
230 static final int SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE = 1;
232 static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP = 0;
233 static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME = 1;
235 // Controls navigation bar opacity depending on which workspace stacks are currently
237 // Nav bar is always opaque when either the freeform stack or docked stack is visible.
238 static final int NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED = 0;
239 // Nav bar is always translucent when the freeform stack is visible, otherwise always opaque.
240 static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1;
242 static final int APPLICATION_MEDIA_SUBLAYER = -2;
243 static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
244 static final int APPLICATION_PANEL_SUBLAYER = 1;
245 static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
246 static final int APPLICATION_ABOVE_SUB_PANEL_SUBLAYER = 3;
248 static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
249 static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
250 static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
251 static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
252 static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";
254 // Available custom actions to perform on a key press.
255 // Must match values for KEY_HOME_LONG_PRESS_ACTION in:
256 // core/java/android/provider/Settings.java
257 private static final int KEY_ACTION_NOTHING = 0;
258 private static final int KEY_ACTION_MENU = 1;
259 private static final int KEY_ACTION_APP_SWITCH = 2;
260 private static final int KEY_ACTION_SEARCH = 3;
261 private static final int KEY_ACTION_VOICE_SEARCH = 4;
262 private static final int KEY_ACTION_IN_APP_SEARCH = 5;
263 private static final int KEY_ACTION_LAUNCH_CAMERA = 6;
264 private static final int KEY_ACTION_SLEEP = 7;
266 // Masks for checking presence of hardware keys.
267 // Must match values in core/res/res/values/config.xml
268 private static final int KEY_MASK_HOME = 0x01;
269 private static final int KEY_MASK_BACK = 0x02;
270 private static final int KEY_MASK_MENU = 0x04;
271 private static final int KEY_MASK_ASSIST = 0x08;
272 private static final int KEY_MASK_APP_SWITCH = 0x10;
273 private static final int KEY_MASK_CAMERA = 0x20;
274 private static final int KEY_MASK_VOLUME = 0x40;
278 * These are the system UI flags that, when changing, can cause the layout
279 * of the screen to change.
281 static final int SYSTEM_UI_CHANGING_LAYOUT =
282 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
283 | View.SYSTEM_UI_FLAG_FULLSCREEN
284 | View.STATUS_BAR_TRANSLUCENT
285 | View.NAVIGATION_BAR_TRANSLUCENT
286 | View.STATUS_BAR_TRANSPARENT
287 | View.NAVIGATION_BAR_TRANSPARENT;
289 private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
290 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
291 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
295 * Broadcast Action: WiFi Display video is enabled or disabled
297 * <p>The intent will have the following extra values:</p>
299 * <li><em>state</em> - 0 for disabled, 1 for enabled. </li>
303 private static final String ACTION_WIFI_DISPLAY_VIDEO =
304 "org.codeaurora.intent.action.WIFI_DISPLAY_VIDEO";
307 // The panic gesture may become active only after the keyguard is dismissed and the immersive
308 // app shows again. If that doesn't happen for 30s we drop the gesture.
309 private static final long PANIC_GESTURE_EXPIRATION = 30000;
311 private static final String SYSUI_PACKAGE = "com.android.systemui";
312 private static final String SYSUI_SCREENSHOT_SERVICE =
313 "com.android.systemui.screenshot.TakeScreenshotService";
314 private static final String SYSUI_SCREENSHOT_ERROR_RECEIVER =
315 "com.android.systemui.screenshot.ScreenshotServiceErrorReceiver";
320 private WindowState mKeyguardScrim;
321 private boolean mKeyguardHidden;
322 private boolean mKeyguardDrawnOnce;
324 /* Table of Application Launch keys. Maps from key codes to intent categories.
326 * These are special keys that are used to launch particular kinds of applications,
327 * such as a web browser. HID defines nearly a hundred of them in the Consumer (0x0C)
328 * usage page. We don't support quite that many yet...
330 static SparseArray<String> sApplicationLaunchKeyCategories;
332 sApplicationLaunchKeyCategories = new SparseArray<String>();
333 sApplicationLaunchKeyCategories.append(
334 KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER);
335 sApplicationLaunchKeyCategories.append(
336 KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL);
337 sApplicationLaunchKeyCategories.append(
338 KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS);
339 sApplicationLaunchKeyCategories.append(
340 KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR);
341 sApplicationLaunchKeyCategories.append(
342 KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC);
343 sApplicationLaunchKeyCategories.append(
344 KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
347 /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
348 static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;
350 private DeviceKeyHandler mDeviceKeyHandler;
353 * Lock protecting internal state. Must not call out into window
354 * manager with lock held. (This lock will be acquired in places
355 * where the window manager is calling in with its own lock held.)
357 private final Object mLock = new Object();
360 IWindowManager mWindowManager;
361 WindowManagerFuncs mWindowManagerFuncs;
362 WindowManagerInternal mWindowManagerInternal;
363 PowerManager mPowerManager;
364 ActivityManagerInternal mActivityManagerInternal;
365 InputManagerInternal mInputManagerInternal;
366 DreamManagerInternal mDreamManagerInternal;
367 PowerManagerInternal mPowerManagerInternal;
368 IStatusBarService mStatusBarService;
369 StatusBarManagerInternal mStatusBarManagerInternal;
370 boolean mPreloadedRecentApps;
371 final Object mServiceAquireLock = new Object();
372 Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
373 SearchManager mSearchManager;
374 AccessibilityManager mAccessibilityManager;
375 BurnInProtectionHelper mBurnInProtectionHelper;
376 AppOpsManager mAppOpsManager;
377 private boolean mHasFeatureWatch;
379 // Vibrator pattern for haptic feedback of a long press.
380 long[] mLongPressVibePattern;
382 // Vibrator pattern for haptic feedback of virtual key press.
383 long[] mVirtualKeyVibePattern;
385 // Vibrator pattern for a short vibration.
386 long[] mKeyboardTapVibePattern;
388 // Vibrator pattern for a short vibration when tapping on an hour/minute tick of a Clock.
389 long[] mClockTickVibePattern;
391 // Vibrator pattern for a short vibration when tapping on a day/month/year date of a Calendar.
392 long[] mCalendarDateVibePattern;
394 // Vibrator pattern for haptic feedback during boot when safe mode is disabled.
395 long[] mSafeModeDisabledVibePattern;
397 // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
398 long[] mSafeModeEnabledVibePattern;
400 // Vibrator pattern for haptic feedback of a context click.
401 long[] mContextClickVibePattern;
403 /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
404 boolean mEnableShiftMenuBugReports = false;
407 WindowState mStatusBar = null;
408 int mStatusBarHeight;
409 WindowState mNavigationBar = null;
410 boolean mHasNavigationBar = false;
411 boolean mCanHideNavigationBar = false;
412 boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?
413 boolean mNavigationBarOnBottom = true; // is the navigation bar on the bottom *right now*?
414 int[] mNavigationBarHeightForRotationDefault = new int[4];
415 int[] mNavigationBarWidthForRotationDefault = new int[4];
416 int[] mNavigationBarHeightForRotationInCarMode = new int[4];
417 int[] mNavigationBarWidthForRotationInCarMode = new int[4];
419 private LongSparseArray<IShortcutService> mShortcutKeyServices = new LongSparseArray<>();
421 // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
422 // This is for car dock and this is updated from resource.
423 private boolean mEnableCarDockHomeCapture = true;
425 boolean mNavigationBarLeftInLandscape = false; // Navigation bar left handed?
427 boolean mBootMessageNeedsHiding;
428 KeyguardServiceDelegate mKeyguardDelegate;
429 final Runnable mWindowManagerDrawCallback = new Runnable() {
432 if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!");
433 mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);
436 final DrawnListener mKeyguardDrawnCallback = new DrawnListener() {
438 public void onDrawn() {
439 if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn.");
440 mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
444 GlobalActions mGlobalActions;
446 WindowState mLastInputMethodWindow = null;
447 WindowState mLastInputMethodTargetWindow = null;
449 // FIXME This state is shared between the input reader and handler thread.
450 // Technically it's broken and buggy but it has been like this for many years
451 // and we have not yet seen any problems. Someday we'll rewrite this logic
452 // so that only one thread is involved in handling input policy. Unfortunately
453 // it's on a critical path for power management so we can't just post the work to the
454 // handler thread. We'll need to resolve this someday by teaching the input dispatcher
455 // to hold wakelocks during dispatch and eliminating the critical path.
456 volatile boolean mPowerKeyHandled;
457 volatile boolean mBackKeyHandled;
458 volatile boolean mBeganFromNonInteractive;
459 volatile int mPowerKeyPressCounter;
460 volatile boolean mEndCallKeyHandled;
461 volatile boolean mCameraGestureTriggeredDuringGoingToSleep;
462 volatile boolean mGoingToSleep;
463 volatile boolean mRecentsVisible;
464 volatile boolean mTvPictureInPictureVisible;
466 int mRecentAppsHeldModifiers;
467 boolean mLanguageSwitchKeyPressed;
469 int mLidState = LID_ABSENT;
470 int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT;
471 boolean mHaveBuiltInKeyboard;
473 boolean mSystemReady;
474 boolean mSystemBooted;
475 private boolean mDeferBindKeyguard;
476 boolean mHdmiPlugged;
477 HdmiControl mHdmiControl;
478 IUiModeManager mUiModeManager;
480 int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
481 int mLidOpenRotation;
482 int mCarDockRotation;
483 int mDeskDockRotation;
484 int mUndockedHdmiRotation;
485 int mDemoHdmiRotation;
486 boolean mDemoHdmiRotationLock;
488 boolean mDemoRotationLock;
490 boolean mWakeGestureEnabledSetting;
491 MyWakeGestureListener mWakeGestureListener;
493 // Default display does not rotate, apps that require non-default orientation will have to
494 // have the orientation emulated.
495 private boolean mForceDefaultOrientation = false;
497 int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
498 int mUserRotation = Surface.ROTATION_0;
499 int mUserRotationAngles = -1;
500 boolean mAccelerometerDefault;
502 boolean mSupportAutoRotation;
503 int mAllowAllRotations = -1;
504 boolean mCarDockEnablesAccelerometer;
505 boolean mDeskDockEnablesAccelerometer;
506 int mLidKeyboardAccessibility;
507 int mLidNavigationAccessibility;
508 boolean mLidControlsScreenLock;
509 boolean mLidControlsSleep;
510 int mShortPressOnPowerBehavior;
511 int mLongPressOnPowerBehavior;
512 int mDoublePressOnPowerBehavior;
513 int mTriplePressOnPowerBehavior;
514 int mLongPressOnBackBehavior;
515 int mShortPressOnSleepBehavior;
516 int mShortPressWindowBehavior;
518 boolean mScreenOnEarly;
519 boolean mScreenOnFully;
520 ScreenOnListener mScreenOnListener;
521 boolean mKeyguardDrawComplete;
522 boolean mWindowManagerDrawComplete;
523 boolean mOrientationSensorEnabled = false;
524 int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
525 boolean mHasSoftInput = false;
526 boolean mTranslucentDecorEnabled = true;
527 boolean mUseTvRouting;
528 int mBackKillTimeout;
530 int mDeviceHardwareKeys;
532 // Button wake control flags
533 boolean mHomeWakeScreen;
534 boolean mBackWakeScreen;
535 boolean mMenuWakeScreen;
536 boolean mAssistWakeScreen;
537 boolean mAppSwitchWakeScreen;
538 boolean mCameraWakeScreen;
539 boolean mVolumeWakeScreen;
541 // Camera button control flags and actions
542 boolean mCameraSleepOnRelease;
543 boolean mIsFocusPressed;
544 boolean mCameraLaunch;
546 // During wakeup by volume keys, we still need to capture subsequent events
547 // until the key is released. This is required since the beep sound is produced
549 boolean mVolumeDownWakeTriggered;
550 boolean mVolumeUpWakeTriggered;
551 boolean mVolumeMuteWakeTriggered;
553 int mPointerLocationMode = 0; // guarded by mLock
555 // The last window we were told about in focusChanged.
556 WindowState mFocusedWindow;
557 IApplicationToken mFocusedApp;
559 // Behavior of volbtn music controls
560 boolean mVolBtnMusicControls;
561 boolean mIsLongPress;
563 PointerLocationView mPointerLocationView;
565 // The current size of the screen; really; extends into the overscan area of
566 // the screen and doesn't account for any system elements like the status bar.
567 int mOverscanScreenLeft, mOverscanScreenTop;
568 int mOverscanScreenWidth, mOverscanScreenHeight;
569 // The current visible size of the screen; really; (ir)regardless of whether the status
570 // bar can be hidden but not extending into the overscan area.
571 int mUnrestrictedScreenLeft, mUnrestrictedScreenTop;
572 int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight;
573 // Like mOverscanScreen*, but allowed to move into the overscan region where appropriate.
574 int mRestrictedOverscanScreenLeft, mRestrictedOverscanScreenTop;
575 int mRestrictedOverscanScreenWidth, mRestrictedOverscanScreenHeight;
576 // The current size of the screen; these may be different than (0,0)-(dw,dh)
577 // if the status bar can't be hidden; in that case it effectively carves out
578 // that area of the display from all other windows.
579 int mRestrictedScreenLeft, mRestrictedScreenTop;
580 int mRestrictedScreenWidth, mRestrictedScreenHeight;
581 // During layout, the current screen borders accounting for any currently
582 // visible system UI elements.
583 int mSystemLeft, mSystemTop, mSystemRight, mSystemBottom;
584 // For applications requesting stable content insets, these are them.
585 int mStableLeft, mStableTop, mStableRight, mStableBottom;
586 // For applications requesting stable content insets but have also set the
587 // fullscreen window flag, these are the stable dimensions without the status bar.
588 int mStableFullscreenLeft, mStableFullscreenTop;
589 int mStableFullscreenRight, mStableFullscreenBottom;
590 // During layout, the current screen borders with all outer decoration
591 // (status bar, input method dock) accounted for.
592 int mCurLeft, mCurTop, mCurRight, mCurBottom;
593 // During layout, the frame in which content should be displayed
594 // to the user, accounting for all screen decoration except for any
595 // space they deem as available for other content. This is usually
596 // the same as mCur*, but may be larger if the screen decor has supplied
598 int mContentLeft, mContentTop, mContentRight, mContentBottom;
599 // During layout, the frame in which voice content should be displayed
600 // to the user, accounting for all screen decoration except for any
601 // space they deem as available for other content.
602 int mVoiceContentLeft, mVoiceContentTop, mVoiceContentRight, mVoiceContentBottom;
603 // During layout, the current screen borders along which input method
604 // windows are placed.
605 int mDockLeft, mDockTop, mDockRight, mDockBottom;
606 // During layout, the layer at which the doc window is placed.
608 // During layout, this is the layer of the status bar.
610 int mLastSystemUiFlags;
611 // Bits that we are in the process of clearing, so we want to prevent
612 // them from being set by applications until everything has been updated
613 // to have them clear.
614 int mResettingSystemUiFlags = 0;
615 // Bits that we are currently always keeping cleared.
616 int mForceClearedSystemUiFlags = 0;
617 int mLastFullscreenStackSysUiFlags;
618 int mLastDockedStackSysUiFlags;
619 final Rect mNonDockedStackBounds = new Rect();
620 final Rect mDockedStackBounds = new Rect();
621 final Rect mLastNonDockedStackBounds = new Rect();
622 final Rect mLastDockedStackBounds = new Rect();
624 // What we last reported to system UI about whether the compatibility
625 // menu needs to be displayed.
626 boolean mLastFocusNeedsMenu = false;
627 // If nonzero, a panic gesture was performed at that time in uptime millis and is still pending.
628 private long mPendingPanicGestureUptime;
630 InputConsumer mInputConsumer = null;
632 static final Rect mTmpParentFrame = new Rect();
633 static final Rect mTmpDisplayFrame = new Rect();
634 static final Rect mTmpOverscanFrame = new Rect();
635 static final Rect mTmpContentFrame = new Rect();
636 static final Rect mTmpVisibleFrame = new Rect();
637 static final Rect mTmpDecorFrame = new Rect();
638 static final Rect mTmpStableFrame = new Rect();
639 static final Rect mTmpNavigationFrame = new Rect();
640 static final Rect mTmpOutsetFrame = new Rect();
641 private static final Rect mTmpRect = new Rect();
643 WindowState mTopFullscreenOpaqueWindowState;
644 WindowState mTopFullscreenOpaqueOrDimmingWindowState;
645 WindowState mTopDockedOpaqueWindowState;
646 WindowState mTopDockedOpaqueOrDimmingWindowState;
647 HashSet<IApplicationToken> mAppsToBeHidden = new HashSet<IApplicationToken>();
648 HashSet<IApplicationToken> mAppsThatDismissKeyguard = new HashSet<IApplicationToken>();
649 boolean mTopIsFullscreen;
650 boolean mForceStatusBar;
651 boolean mForceStatusBarFromKeyguard;
652 private boolean mForceStatusBarTransparent;
653 int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
654 boolean mHideLockScreen;
655 boolean mForcingShowNavBar;
656 int mForcingShowNavBarLayer;
658 boolean mDevForceNavbar = false;
660 // States of keyguard dismiss.
661 private static final int DISMISS_KEYGUARD_NONE = 0; // Keyguard not being dismissed.
662 private static final int DISMISS_KEYGUARD_START = 1; // Keyguard needs to be dismissed.
663 private static final int DISMISS_KEYGUARD_CONTINUE = 2; // Keyguard has been dismissed.
664 int mDismissKeyguard = DISMISS_KEYGUARD_NONE;
666 /** The window that is currently dismissing the keyguard. Dismissing the keyguard must only
667 * be done once per window. */
668 private WindowState mWinDismissingKeyguard;
670 /** When window is currently dismissing the keyguard, dismissing the keyguard must handle
671 * the keygaurd secure state change instantly case, e.g. the use case of inserting a PIN
672 * lock SIM card. This variable is used to record the previous keyguard secure state for
673 * monitoring secure state change on window dismissing keyguard. */
674 private boolean mSecureDismissingKeyguard;
676 /** The window that is currently showing "over" the keyguard. If there is an app window
677 * belonging to another app on top of this the keyguard shows. If there is a fullscreen
678 * app window under this, still dismiss the keyguard but don't show the app underneath. Show
680 private WindowState mWinShowWhenLocked;
682 boolean mShowingLockscreen;
683 boolean mShowingDream;
684 boolean mDreamingLockscreen;
685 boolean mDreamingSleepTokenNeeded;
686 SleepToken mDreamingSleepToken;
687 SleepToken mScreenOffSleepToken;
688 boolean mKeyguardSecure;
689 boolean mKeyguardSecureIncludingHidden;
690 volatile boolean mKeyguardOccluded;
691 boolean mHomePressed;
692 boolean mHomeConsumed;
693 boolean mHomeDoubleTapPending;
694 boolean mMenuPressed;
695 boolean mAppSwitchLongPressed;
697 Intent mCarDockIntent;
698 Intent mDeskDockIntent;
699 boolean mSearchKeyShortcutPending;
700 boolean mConsumeSearchKeyUp;
701 boolean mAssistKeyLongPressed;
702 boolean mPendingMetaAction;
703 boolean mPendingCapsLockToggle;
705 int mInitialMetaState;
706 boolean mForceShowSystemBars;
708 // Tracks user-customisable behavior for certain key events
709 private int mLongPressOnHomeBehavior = -1;
710 private int mPressOnMenuBehavior = -1;
711 private int mLongPressOnMenuBehavior = -1;
712 private int mPressOnAssistBehavior = -1;
713 private int mLongPressOnAssistBehavior = -1;
714 private int mPressOnAppSwitchBehavior = -1;
715 private int mLongPressOnAppSwitchBehavior = -1;
717 // support for activating the lock screen while the screen is on
718 boolean mAllowLockscreenWhenOn;
719 int mLockScreenTimeout;
720 boolean mLockScreenTimerActive;
722 // Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.)
723 int mEndcallBehavior;
725 // Behavior of POWER button while in-call and screen on.
726 // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
727 int mIncallPowerBehavior;
731 private int mDisplayRotation;
733 int mLandscapeRotation = 0; // default landscape rotation
734 int mSeascapeRotation = 0; // "other" landscape rotation, 180 degrees from mLandscapeRotation
735 int mPortraitRotation = 0; // default portrait rotation
736 int mUpsideDownRotation = 0; // "other" portrait rotation
738 int mOverscanLeft = 0;
739 int mOverscanTop = 0;
740 int mOverscanRight = 0;
741 int mOverscanBottom = 0;
743 // What we do when the user double-taps on home
744 private int mDoubleTapOnHomeBehavior;
746 // Allowed theater mode wake actions
747 private boolean mAllowTheaterModeWakeFromKey;
748 private boolean mAllowTheaterModeWakeFromPowerKey;
749 private boolean mAllowTheaterModeWakeFromMotion;
750 private boolean mAllowTheaterModeWakeFromMotionWhenNotDreaming;
751 private boolean mAllowTheaterModeWakeFromCameraLens;
752 private boolean mAllowTheaterModeWakeFromLidSwitch;
753 private boolean mAllowTheaterModeWakeFromWakeGesture;
755 // Whether to support long press from power button in non-interactive mode
756 private boolean mSupportLongPressPowerWhenNonInteractive;
758 // Whether to go to sleep entering theater mode from power button
759 private boolean mGoToSleepOnButtonPressTheaterMode;
761 // Screenshot trigger states
762 // Time to volume and power must be pressed within this interval of each other.
763 private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
764 // Increase the chord delay when taking a screenshot from the keyguard
765 private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f;
766 private boolean mScreenshotChordEnabled;
767 private boolean mScreenshotChordVolumeDownKeyTriggered;
768 private long mScreenshotChordVolumeDownKeyTime;
769 private boolean mScreenshotChordVolumeDownKeyConsumed;
770 private boolean mScreenshotChordVolumeUpKeyTriggered;
771 private boolean mScreenshotChordPowerKeyTriggered;
772 private long mScreenshotChordPowerKeyTime;
774 /* The number of steps between min and max brightness */
775 private static final int BRIGHTNESS_STEPS = 10;
777 SettingsObserver mSettingsObserver;
778 ShortcutManager mShortcutManager;
779 PowerManager.WakeLock mBroadcastWakeLock;
780 PowerManager.WakeLock mPowerKeyWakeLock;
781 boolean mHavePendingMediaKeyRepeatWithWakeLock;
783 private int mCurrentUserId;
785 // Maps global key codes to the components that will handle them.
786 private GlobalKeyManager mGlobalKeyManager;
788 // Fallback actions by key code.
789 private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions =
790 new SparseArray<KeyCharacterMap.FallbackAction>();
792 private final LogDecelerateInterpolator mLogDecelerateInterpolator
793 = new LogDecelerateInterpolator(100, 0);
795 private final MutableBoolean mTmpBoolean = new MutableBoolean(false);
797 private static final int MSG_ENABLE_POINTER_LOCATION = 1;
798 private static final int MSG_DISABLE_POINTER_LOCATION = 2;
799 private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
800 private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
801 private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
802 private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6;
803 private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7;
804 private static final int MSG_DISPATCH_SHOW_RECENTS = 9;
805 private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10;
806 private static final int MSG_HIDE_BOOT_MESSAGE = 11;
807 private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12;
808 private static final int MSG_POWER_DELAYED_PRESS = 13;
809 private static final int MSG_POWER_LONG_PRESS = 14;
810 private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 15;
811 private static final int MSG_REQUEST_TRANSIENT_BARS = 16;
812 private static final int MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU = 17;
813 private static final int MSG_BACK_LONG_PRESS = 18;
814 private static final int MSG_DISPOSE_INPUT_CONSUMER = 19;
815 private static final int MSG_DISPATCH_VOLKEY_WITH_WAKE_LOCK = 20;
816 private static final int MSG_CAMERA_LONG_PRESS = 21;
818 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
819 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
820 boolean mWifiDisplayConnected = false;
821 int mWifiDisplayCustomRotation = -1;
823 private CMHardwareManager mCMHardware;
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:
888 case MSG_DISPOSE_INPUT_CONSUMER:
889 disposeInputConsumer((InputConsumer) msg.obj);
891 case MSG_DISPATCH_VOLKEY_WITH_WAKE_LOCK: {
892 KeyEvent event = (KeyEvent) msg.obj;
894 dispatchMediaKeyWithWakeLockToAudioService(event);
895 dispatchMediaKeyWithWakeLockToAudioService(
896 KeyEvent.changeAction(event, KeyEvent.ACTION_UP));
899 case MSG_CAMERA_LONG_PRESS: {
900 KeyEvent event = (KeyEvent) msg.obj;
908 private UEventObserver mHDMIObserver = new UEventObserver() {
910 public void onUEvent(UEventObserver.UEvent event) {
911 setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
915 class SettingsObserver extends ContentObserver {
916 SettingsObserver(Handler handler) {
921 // Observe all users' changes
922 ContentResolver resolver = mContext.getContentResolver();
923 resolver.registerContentObserver(Settings.System.getUriFor(
924 Settings.System.END_BUTTON_BEHAVIOR), false, this,
925 UserHandle.USER_ALL);
926 resolver.registerContentObserver(Settings.Secure.getUriFor(
927 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this,
928 UserHandle.USER_ALL);
929 resolver.registerContentObserver(Settings.Secure.getUriFor(
930 Settings.Secure.WAKE_GESTURE_ENABLED), false, this,
931 UserHandle.USER_ALL);
932 resolver.registerContentObserver(Settings.System.getUriFor(
933 Settings.System.ACCELEROMETER_ROTATION), false, this,
934 UserHandle.USER_ALL);
935 resolver.registerContentObserver(Settings.System.getUriFor(
936 Settings.System.USER_ROTATION), false, this,
937 UserHandle.USER_ALL);
938 resolver.registerContentObserver(Settings.System.getUriFor(
939 Settings.System.SCREEN_OFF_TIMEOUT), false, this,
940 UserHandle.USER_ALL);
941 resolver.registerContentObserver(Settings.System.getUriFor(
942 Settings.System.POINTER_LOCATION), false, this,
943 UserHandle.USER_ALL);
944 resolver.registerContentObserver(CMSettings.System.getUriFor(
945 CMSettings.System.KEY_HOME_LONG_PRESS_ACTION), false, this,
946 UserHandle.USER_ALL);
947 resolver.registerContentObserver(CMSettings.System.getUriFor(
948 CMSettings.System.KEY_HOME_DOUBLE_TAP_ACTION), false, this,
949 UserHandle.USER_ALL);
950 resolver.registerContentObserver(CMSettings.System.getUriFor(
951 CMSettings.System.KEY_MENU_ACTION), false, this,
952 UserHandle.USER_ALL);
953 resolver.registerContentObserver(CMSettings.System.getUriFor(
954 CMSettings.System.KEY_MENU_LONG_PRESS_ACTION), false, this,
955 UserHandle.USER_ALL);
956 resolver.registerContentObserver(CMSettings.System.getUriFor(
957 CMSettings.System.KEY_ASSIST_ACTION), false, this,
958 UserHandle.USER_ALL);
959 resolver.registerContentObserver(CMSettings.System.getUriFor(
960 CMSettings.System.KEY_ASSIST_LONG_PRESS_ACTION), false, this,
961 UserHandle.USER_ALL);
962 resolver.registerContentObserver(CMSettings.System.getUriFor(
963 CMSettings.System.KEY_APP_SWITCH_ACTION), false, this,
964 UserHandle.USER_ALL);
965 resolver.registerContentObserver(CMSettings.System.getUriFor(
966 CMSettings.System.KEY_APP_SWITCH_LONG_PRESS_ACTION), false, this,
967 UserHandle.USER_ALL);
968 resolver.registerContentObserver(Settings.Secure.getUriFor(
969 Settings.Secure.DEFAULT_INPUT_METHOD), false, this,
970 UserHandle.USER_ALL);
971 resolver.registerContentObserver(Settings.Secure.getUriFor(
972 Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this,
973 UserHandle.USER_ALL);
974 resolver.registerContentObserver(Settings.Global.getUriFor(
975 Settings.Global.POLICY_CONTROL), false, this,
976 UserHandle.USER_ALL);
977 resolver.registerContentObserver(Settings.System.getUriFor(
978 Settings.System.ACCELEROMETER_ROTATION_ANGLES), false, this,
979 UserHandle.USER_ALL);
980 resolver.registerContentObserver(CMSettings.Global.getUriFor(
981 CMSettings.Global.DEV_FORCE_SHOW_NAVBAR), false, this,
982 UserHandle.USER_ALL);
983 resolver.registerContentObserver(CMSettings.System.getUriFor(
984 CMSettings.System.VOLBTN_MUSIC_CONTROLS), false, this,
985 UserHandle.USER_ALL);
986 resolver.registerContentObserver(CMSettings.System.getUriFor(
987 CMSettings.System.BACK_WAKE_SCREEN), false, this,
988 UserHandle.USER_ALL);
989 resolver.registerContentObserver(CMSettings.System.getUriFor(
990 CMSettings.System.MENU_WAKE_SCREEN), false, this,
991 UserHandle.USER_ALL);
992 resolver.registerContentObserver(CMSettings.System.getUriFor(
993 CMSettings.System.ASSIST_WAKE_SCREEN), false, this,
994 UserHandle.USER_ALL);
995 resolver.registerContentObserver(CMSettings.System.getUriFor(
996 CMSettings.System.APP_SWITCH_WAKE_SCREEN), false, this,
997 UserHandle.USER_ALL);
998 resolver.registerContentObserver(CMSettings.System.getUriFor(
999 CMSettings.System.CAMERA_WAKE_SCREEN), false, this,
1000 UserHandle.USER_ALL);
1001 resolver.registerContentObserver(CMSettings.System.getUriFor(
1002 CMSettings.System.CAMERA_SLEEP_ON_RELEASE), false, this,
1003 UserHandle.USER_ALL);
1004 resolver.registerContentObserver(CMSettings.System.getUriFor(
1005 CMSettings.System.CAMERA_LAUNCH), false, this,
1006 UserHandle.USER_ALL);
1007 resolver.registerContentObserver(CMSettings.System.getUriFor(
1008 CMSettings.System.VOLUME_WAKE_SCREEN), false, this,
1009 UserHandle.USER_ALL);
1010 resolver.registerContentObserver(CMSettings.System.getUriFor(
1011 CMSettings.System.HOME_WAKE_SCREEN), false, this,
1012 UserHandle.USER_ALL);
1013 resolver.registerContentObserver(CMSettings.System.getUriFor(
1014 CMSettings.System.VOLUME_WAKE_SCREEN), false, this,
1015 UserHandle.USER_ALL);
1016 resolver.registerContentObserver(Settings.System.getUriFor(
1017 Settings.System.ACCELEROMETER_ROTATION_ANGLES), false, this,
1018 UserHandle.USER_ALL);
1019 resolver.registerContentObserver(CMSettings.System.getUriFor(
1020 CMSettings.System.NAVBAR_LEFT_IN_LANDSCAPE), false, this,
1021 UserHandle.USER_ALL);
1025 @Override public void onChange(boolean selfChange) {
1027 updateRotation(false);
1031 class MyWakeGestureListener extends WakeGestureListener {
1032 MyWakeGestureListener(Context context, Handler handler) {
1033 super(context, handler);
1037 public void onWakeUp() {
1038 synchronized (mLock) {
1039 if (shouldEnableWakeGestureLp()) {
1040 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
1041 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture,
1042 "android.policy:GESTURE");
1048 class MyOrientationListener extends WindowOrientationListener {
1049 private final Runnable mUpdateRotationRunnable = new Runnable() {
1052 // send interaction hint to improve redraw performance
1053 mPowerManagerInternal.powerHint(PowerManagerInternal.POWER_HINT_INTERACTION, 0);
1054 updateRotation(false);
1058 MyOrientationListener(Context context, Handler handler) {
1059 super(context, handler);
1063 public void onProposedRotationChanged(int rotation) {
1064 if (localLOGV) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
1065 mHandler.post(mUpdateRotationRunnable);
1068 MyOrientationListener mOrientationListener;
1070 private final StatusBarController mStatusBarController = new StatusBarController();
1072 private final BarController mNavigationBarController = new BarController("NavigationBar",
1073 View.NAVIGATION_BAR_TRANSIENT,
1074 View.NAVIGATION_BAR_UNHIDE,
1075 View.NAVIGATION_BAR_TRANSLUCENT,
1076 StatusBarManager.WINDOW_NAVIGATION_BAR,
1077 WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
1078 View.NAVIGATION_BAR_TRANSPARENT);
1080 private ImmersiveModeConfirmation mImmersiveModeConfirmation;
1082 private SystemGesturesPointerEventListener mSystemGestures;
1084 IStatusBarService getStatusBarService() {
1085 synchronized (mServiceAquireLock) {
1086 if (mStatusBarService == null) {
1087 mStatusBarService = IStatusBarService.Stub.asInterface(
1088 ServiceManager.getService("statusbar"));
1090 return mStatusBarService;
1094 StatusBarManagerInternal getStatusBarManagerInternal() {
1095 synchronized (mServiceAquireLock) {
1096 if (mStatusBarManagerInternal == null) {
1097 mStatusBarManagerInternal =
1098 LocalServices.getService(StatusBarManagerInternal.class);
1100 return mStatusBarManagerInternal;
1105 * We always let the sensor be switched on by default except when
1106 * the user has explicitly disabled sensor based rotation or when the
1107 * screen is switched off.
1109 boolean needSensorRunningLp() {
1110 if (mSupportAutoRotation) {
1111 if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
1112 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
1113 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
1114 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
1115 // If the application has explicitly requested to follow the
1116 // orientation, then we need to turn the sensor on.
1120 if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
1121 (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
1122 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
1123 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
1124 // enable accelerometer if we are docked in a dock that enables accelerometer
1125 // orientation management,
1128 if (mUserRotationMode == USER_ROTATION_LOCKED) {
1129 // If the setting for using the sensor by default is enabled, then
1130 // we will always leave it on. Note that the user could go to
1131 // a window that forces an orientation that does not use the
1132 // sensor and in theory we could turn it off... however, when next
1133 // turning it on we won't have a good value for the current
1134 // orientation for a little bit, which can cause orientation
1135 // changes to lag, so we'd like to keep it always on. (It will
1136 // still be turned off when the screen is off.)
1139 return mSupportAutoRotation;
1143 * Various use cases for invoking this function
1144 * screen turning off, should always disable listeners if already enabled
1145 * screen turned on and current app has sensor based orientation, enable listeners
1146 * if not already enabled
1147 * screen turned on and current app does not have sensor orientation, disable listeners if
1149 * screen turning on and current app has sensor based orientation, enable listeners if needed
1150 * screen turning on and current app has nosensor based orientation, do nothing
1152 void updateOrientationListenerLp() {
1153 if (!mOrientationListener.canDetectOrientation()) {
1154 // If sensor is turned off or nonexistent for some reason
1157 // Could have been invoked due to screen turning on or off or
1158 // change of the currently visible window's orientation.
1159 if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly
1160 + ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation
1161 + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled
1162 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
1163 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
1164 boolean disable = true;
1165 // Note: We postpone the rotating of the screen until the keyguard as well as the
1166 // window manager have reported a draw complete.
1167 if (mScreenOnEarly && mAwake &&
1168 mKeyguardDrawComplete && mWindowManagerDrawComplete) {
1169 if (needSensorRunningLp()) {
1171 //enable listener if not already enabled
1172 if (!mOrientationSensorEnabled) {
1173 mOrientationListener.enable();
1174 if(localLOGV) Slog.v(TAG, "Enabling listeners");
1175 mOrientationSensorEnabled = true;
1179 //check if sensors need to be disabled
1180 if (disable && mOrientationSensorEnabled) {
1181 mOrientationListener.disable();
1182 if(localLOGV) Slog.v(TAG, "Disabling listeners");
1183 mOrientationSensorEnabled = false;
1187 private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
1188 // Hold a wake lock until the power key is released.
1189 if (!mPowerKeyWakeLock.isHeld()) {
1190 mPowerKeyWakeLock.acquire();
1193 // Cancel multi-press detection timeout.
1194 if (mPowerKeyPressCounter != 0) {
1195 mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);
1198 // Detect user pressing the power button in panic when an application has
1199 // taken over the whole screen.
1200 boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
1201 SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags));
1203 mHandler.post(mHiddenNavPanic);
1206 // Latch power key state to detect screenshot chord.
1207 if (interactive && !mScreenshotChordPowerKeyTriggered
1208 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
1209 mScreenshotChordPowerKeyTriggered = true;
1210 mScreenshotChordPowerKeyTime = event.getDownTime();
1211 interceptScreenshotChord();
1214 // Stop ringing or end call if configured to do so when power is pressed.
1215 TelecomManager telecomManager = getTelecommService();
1216 boolean hungUp = false;
1217 if (telecomManager != null) {
1218 if (telecomManager.isRinging()) {
1219 // Pressing Power while there's a ringing incoming
1220 // call should silence the ringer.
1221 telecomManager.silenceRinger();
1222 } else if ((mIncallPowerBehavior
1223 & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
1224 && telecomManager.isInCall() && interactive) {
1225 // Otherwise, if "Power button ends call" is enabled,
1226 // the Power button will hang up any current active call.
1227 hungUp = telecomManager.endCall();
1231 GestureLauncherService gestureService = LocalServices.getService(
1232 GestureLauncherService.class);
1233 boolean gesturedServiceIntercepted = false;
1234 if (gestureService != null) {
1235 gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive,
1237 if (mTmpBoolean.value && mGoingToSleep) {
1238 mCameraGestureTriggeredDuringGoingToSleep = true;
1242 // If the power key has still not yet been handled, then detect short
1243 // press, long press, or multi press and decide what to do.
1244 mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
1245 || mScreenshotChordVolumeUpKeyTriggered || gesturedServiceIntercepted;
1246 if (!mPowerKeyHandled) {
1248 // When interactive, we're already awake.
1249 // Wait for a long press or for the button to be released to decide what to do.
1250 if (hasLongPressOnPowerBehavior()) {
1251 Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
1252 msg.setAsynchronous(true);
1253 mHandler.sendMessageDelayed(msg,
1254 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1257 wakeUpFromPowerKey(event.getDownTime());
1259 if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
1260 Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
1261 msg.setAsynchronous(true);
1262 mHandler.sendMessageDelayed(msg,
1263 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1264 mBeganFromNonInteractive = true;
1266 final int maxCount = getMaxMultiPressPowerCount();
1268 if (maxCount <= 1) {
1269 mPowerKeyHandled = true;
1271 mBeganFromNonInteractive = true;
1278 private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
1279 final boolean handled = canceled || mPowerKeyHandled;
1280 mScreenshotChordPowerKeyTriggered = false;
1281 cancelPendingScreenshotChordAction();
1282 cancelPendingPowerKeyAction();
1285 // Figure out how to handle the key now that it has been released.
1286 mPowerKeyPressCounter += 1;
1288 final int maxCount = getMaxMultiPressPowerCount();
1289 final long eventTime = event.getDownTime();
1290 if (mPowerKeyPressCounter < maxCount) {
1291 // This could be a multi-press. Wait a little bit longer to confirm.
1292 // Continue holding the wake lock.
1293 Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
1294 interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
1295 msg.setAsynchronous(true);
1296 mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
1300 // No other actions. Handle it immediately.
1301 powerPress(eventTime, interactive, mPowerKeyPressCounter);
1304 // Done. Reset our state.
1305 finishPowerKeyPress();
1308 private void finishPowerKeyPress() {
1309 mBeganFromNonInteractive = false;
1310 mPowerKeyPressCounter = 0;
1311 if (mPowerKeyWakeLock.isHeld()) {
1312 mPowerKeyWakeLock.release();
1316 private void cancelPendingPowerKeyAction() {
1317 if (!mPowerKeyHandled) {
1318 mPowerKeyHandled = true;
1319 mHandler.removeMessages(MSG_POWER_LONG_PRESS);
1323 private void cancelPendingBackKeyAction() {
1324 if (!mBackKeyHandled) {
1325 mBackKeyHandled = true;
1326 mHandler.removeMessages(MSG_BACK_LONG_PRESS);
1330 private void powerPress(long eventTime, boolean interactive, int count) {
1331 if (mScreenOnEarly && !mScreenOnFully) {
1332 Slog.i(TAG, "Suppressed redundant power key press while "
1333 + "already in the process of turning the screen on.");
1338 powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
1339 } else if (count == 3) {
1340 powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
1341 } else if (interactive && !mBeganFromNonInteractive) {
1342 switch (mShortPressOnPowerBehavior) {
1343 case SHORT_PRESS_POWER_NOTHING:
1345 case SHORT_PRESS_POWER_GO_TO_SLEEP:
1346 mPowerManager.goToSleep(eventTime,
1347 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
1349 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
1350 mPowerManager.goToSleep(eventTime,
1351 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
1352 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
1354 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
1355 mPowerManager.goToSleep(eventTime,
1356 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
1357 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
1358 launchHomeFromHotKey();
1360 case SHORT_PRESS_POWER_GO_HOME:
1361 launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
1367 private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) {
1369 case MULTI_PRESS_POWER_NOTHING:
1371 case MULTI_PRESS_POWER_THEATER_MODE:
1372 if (!isUserSetupComplete()) {
1373 Slog.i(TAG, "Ignoring toggling theater mode - device not setup.");
1377 if (isTheaterModeEnabled()) {
1378 Slog.i(TAG, "Toggling theater mode off.");
1379 Settings.Global.putInt(mContext.getContentResolver(),
1380 Settings.Global.THEATER_MODE_ON, 0);
1382 wakeUpFromPowerKey(eventTime);
1385 Slog.i(TAG, "Toggling theater mode on.");
1386 Settings.Global.putInt(mContext.getContentResolver(),
1387 Settings.Global.THEATER_MODE_ON, 1);
1389 if (mGoToSleepOnButtonPressTheaterMode && interactive) {
1390 mPowerManager.goToSleep(eventTime,
1391 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
1395 case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
1396 Slog.i(TAG, "Starting brightness boost.");
1398 wakeUpFromPowerKey(eventTime);
1400 mPowerManager.boostScreenBrightness(eventTime);
1405 private int getMaxMultiPressPowerCount() {
1406 if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
1409 if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
1415 private void powerLongPress() {
1416 final int behavior = getResolvedLongPressOnPowerBehavior();
1418 case LONG_PRESS_POWER_NOTHING:
1420 case LONG_PRESS_POWER_GLOBAL_ACTIONS:
1421 mPowerKeyHandled = true;
1422 if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
1423 performAuditoryFeedbackForAccessibilityIfNeed();
1425 showGlobalActionsInternal();
1427 case LONG_PRESS_POWER_SHUT_OFF:
1428 case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
1429 mPowerKeyHandled = true;
1430 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1431 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
1432 mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
1437 private void backLongPress() {
1438 mBackKeyHandled = true;
1440 switch (mLongPressOnBackBehavior) {
1441 case LONG_PRESS_BACK_NOTHING:
1443 case LONG_PRESS_BACK_GO_TO_VOICE_ASSIST:
1444 Intent intent = new Intent(Intent.ACTION_VOICE_ASSIST);
1445 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
1450 private void disposeInputConsumer(InputConsumer inputConsumer) {
1451 if (inputConsumer != null) {
1452 inputConsumer.dismiss();
1456 private void sleepPress(long eventTime) {
1457 if (mShortPressOnSleepBehavior == SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME) {
1458 launchHomeFromHotKey(false /* awakenDreams */, true /*respectKeyguard*/);
1462 private void sleepRelease(long eventTime) {
1463 switch (mShortPressOnSleepBehavior) {
1464 case SHORT_PRESS_SLEEP_GO_TO_SLEEP:
1465 case SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME:
1466 Slog.i(TAG, "sleepRelease() calling goToSleep(GO_TO_SLEEP_REASON_SLEEP_BUTTON)");
1467 mPowerManager.goToSleep(eventTime,
1468 PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON, 0);
1473 private int getResolvedLongPressOnPowerBehavior() {
1474 if (FactoryTest.isLongPressOnPowerOffEnabled()) {
1475 return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
1477 return mLongPressOnPowerBehavior;
1480 private boolean hasLongPressOnPowerBehavior() {
1481 return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;
1484 private boolean hasLongPressOnBackBehavior() {
1485 return mLongPressOnBackBehavior != LONG_PRESS_BACK_NOTHING;
1488 private void interceptScreenshotChord() {
1489 if (mScreenshotChordEnabled
1490 && mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered
1491 && !mScreenshotChordVolumeUpKeyTriggered) {
1492 final long now = SystemClock.uptimeMillis();
1493 if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
1494 && now <= mScreenshotChordPowerKeyTime
1495 + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
1496 mScreenshotChordVolumeDownKeyConsumed = true;
1497 cancelPendingPowerKeyAction();
1498 mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
1499 mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
1504 private long getScreenshotChordLongPressDelay() {
1505 if (mKeyguardDelegate.isShowing()) {
1506 // Double the time it takes to take a screenshot from the keyguard
1507 return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER *
1508 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1510 return ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout();
1513 private void cancelPendingScreenshotChordAction() {
1514 mHandler.removeCallbacks(mScreenshotRunnable);
1517 private final Runnable mEndCallLongPress = new Runnable() {
1520 mEndCallKeyHandled = true;
1521 if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
1522 performAuditoryFeedbackForAccessibilityIfNeed();
1524 showGlobalActionsInternal();
1528 private class ScreenshotRunnable implements Runnable {
1529 private int mScreenshotType = TAKE_SCREENSHOT_FULLSCREEN;
1531 public void setScreenshotType(int screenshotType) {
1532 mScreenshotType = screenshotType;
1537 takeScreenshot(mScreenshotType);
1541 private final ScreenshotRunnable mScreenshotRunnable = new ScreenshotRunnable();
1544 public void showGlobalActions() {
1545 mHandler.removeMessages(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
1546 mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
1549 Runnable mBackLongPress = new Runnable() {
1551 if (unpinActivity(false)) {
1555 final Intent intent = new Intent(Intent.ACTION_MAIN);
1556 String defaultHomePackage = "com.android.launcher";
1557 intent.addCategory(Intent.CATEGORY_HOME);
1558 final ResolveInfo res = mContext.getPackageManager().resolveActivity(intent, 0);
1559 if (res.activityInfo != null && !res.activityInfo.packageName.equals("android")) {
1560 defaultHomePackage = res.activityInfo.packageName;
1562 boolean targetKilled = false;
1563 IActivityManager am = ActivityManagerNative.getDefault();
1564 List<RunningAppProcessInfo> apps = am.getRunningAppProcesses();
1565 for (RunningAppProcessInfo appInfo : apps) {
1566 int uid = appInfo.uid;
1567 // Make sure it's a foreground user application (not system,
1568 // root, phone, etc.)
1569 if (uid >= Process.FIRST_APPLICATION_UID && uid <= Process.LAST_APPLICATION_UID
1570 && appInfo.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
1571 if (appInfo.pkgList != null && (appInfo.pkgList.length > 0)) {
1572 for (String pkg : appInfo.pkgList) {
1573 if (!pkg.equals("com.android.systemui") && !pkg.equals(defaultHomePackage)) {
1574 am.forceStopPackage(pkg, UserHandle.USER_CURRENT);
1575 targetKilled = true;
1580 Process.killProcess(appInfo.pid);
1581 targetKilled = true;
1585 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1586 Toast.makeText(mContext, R.string.app_killed_message, Toast.LENGTH_SHORT).show();
1590 } catch (RemoteException remoteException) {
1591 // Do nothing; just let it go.
1596 void showGlobalActionsInternal() {
1597 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
1598 if (mGlobalActions == null) {
1599 mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
1601 final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();
1602 mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
1603 if (keyguardShowing) {
1604 // since it took two seconds of long press to bring this up,
1605 // poke the wake lock so they have some time to see the dialog.
1606 mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
1610 boolean isDeviceProvisioned() {
1611 return Settings.Global.getInt(
1612 mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
1615 boolean isUserSetupComplete() {
1616 return Settings.Secure.getIntForUser(mContext.getContentResolver(),
1617 Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
1620 private void handleShortPressOnHome() {
1621 // Turn on the connected TV and switch HDMI input if we're a HDMI playback device.
1622 getHdmiControl().turnOnTv();
1624 // If there's a dream running then use home to escape the dream
1625 // but don't actually go home.
1626 if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) {
1627 mDreamManagerInternal.stopDream(false /*immediate*/);
1632 launchHomeFromHotKey();
1636 * Creates an accessor to HDMI control service that performs the operation of
1637 * turning on TV (optional) and switching input to us. If HDMI control service
1638 * is not available or we're not a HDMI playback device, the operation is no-op.
1640 private HdmiControl getHdmiControl() {
1641 if (null == mHdmiControl) {
1642 HdmiControlManager manager = (HdmiControlManager) mContext.getSystemService(
1643 Context.HDMI_CONTROL_SERVICE);
1644 HdmiPlaybackClient client = null;
1645 if (manager != null) {
1646 client = manager.getPlaybackClient();
1648 mHdmiControl = new HdmiControl(client);
1650 return mHdmiControl;
1653 private static class HdmiControl {
1654 private final HdmiPlaybackClient mClient;
1656 private HdmiControl(HdmiPlaybackClient client) {
1660 public void turnOnTv() {
1661 if (mClient == null) {
1664 mClient.oneTouchPlay(new OneTouchPlayCallback() {
1666 public void onComplete(int result) {
1667 if (result != HdmiControlManager.RESULT_SUCCESS) {
1668 Log.w(TAG, "One touch play failed: " + result);
1675 private void triggerVirtualKeypress(final int keyCode) {
1676 InputManager im = InputManager.getInstance();
1677 long now = SystemClock.uptimeMillis();
1678 final KeyEvent downEvent = new KeyEvent(now, now, KeyEvent.ACTION_DOWN,
1679 keyCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
1680 KeyEvent.FLAG_FROM_SYSTEM, InputDevice.SOURCE_KEYBOARD);
1681 final KeyEvent upEvent = KeyEvent.changeAction(downEvent, KeyEvent.ACTION_UP);
1683 im.injectInputEvent(downEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
1684 im.injectInputEvent(upEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
1687 private void launchCameraAction() {
1688 sendCloseSystemWindows();
1689 Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null);
1690 mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT_OR_SELF,
1691 null, null, null, 0, null, null);
1694 private void showTvPictureInPictureMenu(KeyEvent event) {
1695 if (DEBUG_INPUT) Log.d(TAG, "showTvPictureInPictureMenu event=" + event);
1696 mHandler.removeMessages(MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU);
1697 Message msg = mHandler.obtainMessage(MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU);
1698 msg.setAsynchronous(true);
1702 private void showTvPictureInPictureMenuInternal() {
1703 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
1704 if (statusbar != null) {
1705 statusbar.showTvPictureInPictureMenu();
1709 private void performKeyAction(int behavior, KeyEvent event) {
1711 case KEY_ACTION_NOTHING:
1713 case KEY_ACTION_MENU:
1714 triggerVirtualKeypress(KeyEvent.KEYCODE_MENU);
1716 case KEY_ACTION_APP_SWITCH:
1719 case KEY_ACTION_SEARCH:
1720 launchAssistAction(null, event.getDeviceId());
1722 case KEY_ACTION_VOICE_SEARCH:
1723 launchAssistLongPressAction();
1725 case KEY_ACTION_IN_APP_SEARCH:
1726 triggerVirtualKeypress(KeyEvent.KEYCODE_SEARCH);
1728 case KEY_ACTION_LAUNCH_CAMERA:
1729 launchCameraAction();
1731 case KEY_ACTION_SLEEP:
1732 mPowerManager.goToSleep(SystemClock.uptimeMillis());
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);
1768 // Init display burn-in protection
1769 boolean burnInProtectionEnabled = context.getResources().getBoolean(
1770 com.android.internal.R.bool.config_enableBurnInProtection);
1771 // Allow a system property to override this. Used by developer settings.
1772 boolean burnInProtectionDevMode =
1773 SystemProperties.getBoolean("persist.debug.force_burn_in", false);
1774 if (burnInProtectionEnabled || burnInProtectionDevMode) {
1775 final int minHorizontal;
1776 final int maxHorizontal;
1777 final int minVertical;
1778 final int maxVertical;
1779 final int maxRadius;
1780 if (burnInProtectionDevMode) {
1785 maxRadius = (isRoundWindow()) ? 6 : -1;
1787 Resources resources = context.getResources();
1788 minHorizontal = resources.getInteger(
1789 com.android.internal.R.integer.config_burnInProtectionMinHorizontalOffset);
1790 maxHorizontal = resources.getInteger(
1791 com.android.internal.R.integer.config_burnInProtectionMaxHorizontalOffset);
1792 minVertical = resources.getInteger(
1793 com.android.internal.R.integer.config_burnInProtectionMinVerticalOffset);
1794 maxVertical = resources.getInteger(
1795 com.android.internal.R.integer.config_burnInProtectionMaxVerticalOffset);
1796 maxRadius = resources.getInteger(
1797 com.android.internal.R.integer.config_burnInProtectionMaxRadius);
1799 mBurnInProtectionHelper = new BurnInProtectionHelper(
1800 context, minHorizontal, maxHorizontal, minVertical, maxVertical, maxRadius);
1803 mHandler = new PolicyHandler();
1804 mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
1805 mOrientationListener = new MyOrientationListener(mContext, mHandler);
1807 mOrientationListener.setCurrentRotation(windowManager.getRotation());
1808 } catch (RemoteException ex) { }
1809 mSettingsObserver = new SettingsObserver(mHandler);
1810 mShortcutManager = new ShortcutManager(context);
1811 mUiMode = context.getResources().getInteger(
1812 com.android.internal.R.integer.config_defaultUiModeType);
1813 mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
1814 mHomeIntent.addCategory(Intent.CATEGORY_HOME);
1815 mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1816 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1817 mEnableCarDockHomeCapture = context.getResources().getBoolean(
1818 com.android.internal.R.bool.config_enableCarDockHomeLaunch);
1819 mCarDockIntent = new Intent(Intent.ACTION_MAIN, null);
1820 mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
1821 mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1822 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1823 mDeskDockIntent = new Intent(Intent.ACTION_MAIN, null);
1824 mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
1825 mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1826 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1828 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1829 mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1830 "PhoneWindowManager.mBroadcastWakeLock");
1831 mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1832 "PhoneWindowManager.mPowerKeyWakeLock");
1833 mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
1834 mSupportAutoRotation = mContext.getResources().getBoolean(
1835 com.android.internal.R.bool.config_supportAutoRotation);
1836 mLidOpenRotation = readRotation(
1837 com.android.internal.R.integer.config_lidOpenRotation);
1838 mCarDockRotation = readRotation(
1839 com.android.internal.R.integer.config_carDockRotation);
1840 mDeskDockRotation = readRotation(
1841 com.android.internal.R.integer.config_deskDockRotation);
1842 mUndockedHdmiRotation = readRotation(
1843 com.android.internal.R.integer.config_undockedHdmiRotation);
1844 mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
1845 com.android.internal.R.bool.config_carDockEnablesAccelerometer);
1846 mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
1847 com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
1848 mLidKeyboardAccessibility = mContext.getResources().getInteger(
1849 com.android.internal.R.integer.config_lidKeyboardAccessibility);
1850 mLidNavigationAccessibility = mContext.getResources().getInteger(
1851 com.android.internal.R.integer.config_lidNavigationAccessibility);
1852 mLidControlsScreenLock = mContext.getResources().getBoolean(
1853 com.android.internal.R.bool.config_lidControlsScreenLock);
1854 mLidControlsSleep = mContext.getResources().getBoolean(
1855 com.android.internal.R.bool.config_lidControlsSleep);
1856 mTranslucentDecorEnabled = mContext.getResources().getBoolean(
1857 com.android.internal.R.bool.config_enableTranslucentDecor);
1859 mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
1860 com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
1861 mAllowTheaterModeWakeFromPowerKey = mAllowTheaterModeWakeFromKey
1862 || mContext.getResources().getBoolean(
1863 com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey);
1864 mAllowTheaterModeWakeFromMotion = mContext.getResources().getBoolean(
1865 com.android.internal.R.bool.config_allowTheaterModeWakeFromMotion);
1866 mAllowTheaterModeWakeFromMotionWhenNotDreaming = mContext.getResources().getBoolean(
1867 com.android.internal.R.bool.config_allowTheaterModeWakeFromMotionWhenNotDreaming);
1868 mAllowTheaterModeWakeFromCameraLens = mContext.getResources().getBoolean(
1869 com.android.internal.R.bool.config_allowTheaterModeWakeFromCameraLens);
1870 mAllowTheaterModeWakeFromLidSwitch = mContext.getResources().getBoolean(
1871 com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch);
1872 mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean(
1873 com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture);
1875 mGoToSleepOnButtonPressTheaterMode = mContext.getResources().getBoolean(
1876 com.android.internal.R.bool.config_goToSleepOnButtonPressTheaterMode);
1878 mSupportLongPressPowerWhenNonInteractive = mContext.getResources().getBoolean(
1879 com.android.internal.R.bool.config_supportLongPressPowerWhenNonInteractive);
1881 mLongPressOnBackBehavior = mContext.getResources().getInteger(
1882 com.android.internal.R.integer.config_longPressOnBackBehavior);
1884 mShortPressOnPowerBehavior = mContext.getResources().getInteger(
1885 com.android.internal.R.integer.config_shortPressOnPowerBehavior);
1886 mLongPressOnPowerBehavior = mContext.getResources().getInteger(
1887 com.android.internal.R.integer.config_longPressOnPowerBehavior);
1888 mDoublePressOnPowerBehavior = mContext.getResources().getInteger(
1889 com.android.internal.R.integer.config_doublePressOnPowerBehavior);
1890 mTriplePressOnPowerBehavior = mContext.getResources().getInteger(
1891 com.android.internal.R.integer.config_triplePressOnPowerBehavior);
1892 mShortPressOnSleepBehavior = mContext.getResources().getInteger(
1893 com.android.internal.R.integer.config_shortPressOnSleepBehavior);
1895 mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION;
1897 mDeviceHardwareKeys = mContext.getResources().getInteger(
1898 com.android.internal.R.integer.config_deviceHardwareKeys);
1899 mBackKillTimeout = mContext.getResources().getInteger(
1900 com.android.internal.R.integer.config_backKillTimeout);
1902 updateKeyAssignments();
1904 mAccessibilityManager = (AccessibilityManager) context.getSystemService(
1905 Context.ACCESSIBILITY_SERVICE);
1907 // register for dock events
1908 IntentFilter filter = new IntentFilter();
1909 filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
1910 filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
1911 filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
1912 filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
1913 filter.addAction(Intent.ACTION_DOCK_EVENT);
1914 Intent intent = context.registerReceiver(mDockReceiver, filter);
1915 if (intent != null) {
1916 // Retrieve current sticky dock event broadcast.
1917 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
1918 Intent.EXTRA_DOCK_STATE_UNDOCKED);
1921 // register for dream-related broadcasts
1922 filter = new IntentFilter();
1923 filter.addAction(Intent.ACTION_DREAMING_STARTED);
1924 filter.addAction(Intent.ACTION_DREAMING_STOPPED);
1925 context.registerReceiver(mDreamReceiver, filter);
1927 // register for multiuser-relevant broadcasts
1928 filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
1929 context.registerReceiver(mMultiuserReceiver, filter);
1931 // monitor for system gestures
1932 mSystemGestures = new SystemGesturesPointerEventListener(context,
1933 new SystemGesturesPointerEventListener.Callbacks() {
1935 public void onSwipeFromTop() {
1936 if (mStatusBar != null) {
1937 requestTransientBars(mStatusBar);
1941 public void onSwipeFromBottom() {
1942 if (mNavigationBar != null && mNavigationBarOnBottom) {
1943 requestTransientBars(mNavigationBar);
1947 public void onSwipeFromRight() {
1948 if (mNavigationBar != null && !mNavigationBarOnBottom &&
1949 !mNavigationBarLeftInLandscape) {
1950 requestTransientBars(mNavigationBar);
1954 public void onSwipeFromLeft() {
1955 if (mNavigationBar != null && !mNavigationBarOnBottom &&
1956 mNavigationBarLeftInLandscape) {
1957 requestTransientBars(mNavigationBar);
1961 public void onFling(int duration) {
1962 if (mPowerManagerInternal != null) {
1963 mPowerManagerInternal.powerHint(
1964 PowerManagerInternal.POWER_HINT_INTERACTION, duration);
1968 public void onDebug() {
1972 public void onDown() {
1973 mOrientationListener.onTouchStart();
1976 public void onUpOrCancel() {
1977 mOrientationListener.onTouchEnd();
1980 public void onMouseHoverAtTop() {
1981 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
1982 Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
1983 msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
1984 mHandler.sendMessageDelayed(msg, 500);
1987 public void onMouseHoverAtBottom() {
1988 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
1989 Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
1990 msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
1991 mHandler.sendMessageDelayed(msg, 500);
1994 public void onMouseLeaveFromEdge() {
1995 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
1998 mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext);
1999 mWindowManagerFuncs.registerPointerEventListener(mSystemGestures);
2001 mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
2003 /* Register for WIFI Display Intents */
2004 IntentFilter wifiDisplayFilter = new IntentFilter(ACTION_WIFI_DISPLAY_VIDEO);
2005 Intent wifidisplayIntent = context.registerReceiver(
2006 mWifiDisplayReceiver, wifiDisplayFilter);
2007 mLongPressVibePattern = getLongIntArray(mContext.getResources(),
2008 com.android.internal.R.array.config_longPressVibePattern);
2009 mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(),
2010 com.android.internal.R.array.config_virtualKeyVibePattern);
2011 mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(),
2012 com.android.internal.R.array.config_keyboardTapVibePattern);
2013 mClockTickVibePattern = getLongIntArray(mContext.getResources(),
2014 com.android.internal.R.array.config_clockTickVibePattern);
2015 mCalendarDateVibePattern = getLongIntArray(mContext.getResources(),
2016 com.android.internal.R.array.config_calendarDateVibePattern);
2017 mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
2018 com.android.internal.R.array.config_safeModeDisabledVibePattern);
2019 mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
2020 com.android.internal.R.array.config_safeModeEnabledVibePattern);
2021 mContextClickVibePattern = getLongIntArray(mContext.getResources(),
2022 com.android.internal.R.array.config_contextClickVibePattern);
2024 mScreenshotChordEnabled = mContext.getResources().getBoolean(
2025 com.android.internal.R.bool.config_enableScreenshotChord);
2027 mGlobalKeyManager = new GlobalKeyManager(mContext);
2029 // Controls rotation and the like.
2030 initializeHdmiState();
2032 // Match current screen state.
2033 if (!mPowerManager.isInteractive()) {
2034 startedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
2035 finishedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
2038 mWindowManagerInternal.registerAppTransitionListener(
2039 mStatusBarController.getAppTransitionListener());
2041 String deviceKeyHandlerLib = mContext.getResources().getString(
2042 com.android.internal.R.string.config_deviceKeyHandlerLib);
2044 String deviceKeyHandlerClass = mContext.getResources().getString(
2045 com.android.internal.R.string.config_deviceKeyHandlerClass);
2047 if (!deviceKeyHandlerLib.isEmpty() && !deviceKeyHandlerClass.isEmpty()) {
2048 PathClassLoader loader = new PathClassLoader(deviceKeyHandlerLib,
2049 getClass().getClassLoader());
2051 Class<?> klass = loader.loadClass(deviceKeyHandlerClass);
2052 Constructor<?> constructor = klass.getConstructor(Context.class);
2053 mDeviceKeyHandler = (DeviceKeyHandler) constructor.newInstance(
2055 if(DEBUG) Slog.d(TAG, "Device key handler loaded");
2056 } catch (Exception e) {
2057 Slog.w(TAG, "Could not instantiate device key handler "
2058 + deviceKeyHandlerClass + " from class "
2059 + deviceKeyHandlerLib, e);
2064 private void updateKeyAssignments() {
2065 int activeHardwareKeys = mDeviceHardwareKeys;
2067 if (mDevForceNavbar) {
2068 activeHardwareKeys = 0;
2070 final boolean hasMenu = (activeHardwareKeys & KEY_MASK_MENU) != 0;
2071 final boolean hasHome = (activeHardwareKeys & KEY_MASK_HOME) != 0;
2072 final boolean hasAssist = (activeHardwareKeys & KEY_MASK_ASSIST) != 0;
2073 final boolean hasAppSwitch = (activeHardwareKeys & KEY_MASK_APP_SWITCH) != 0;
2075 final ContentResolver resolver = mContext.getContentResolver();
2076 final Resources res = mContext.getResources();
2078 // Initialize all assignments to sane defaults.
2079 mPressOnMenuBehavior = KEY_ACTION_MENU;
2081 mLongPressOnMenuBehavior = mContext.getResources().getInteger(
2082 com.android.internal.R.integer.config_longPressOnMenuBehavior);
2084 if (mLongPressOnMenuBehavior == KEY_ACTION_NOTHING &&
2085 (hasMenu && !hasAssist)) {
2086 mLongPressOnMenuBehavior = KEY_ACTION_SEARCH;
2088 mPressOnAssistBehavior = KEY_ACTION_SEARCH;
2089 mLongPressOnAssistBehavior = KEY_ACTION_VOICE_SEARCH;
2090 mPressOnAppSwitchBehavior = KEY_ACTION_APP_SWITCH;
2091 mLongPressOnAppSwitchBehavior = res.getInteger(
2092 com.android.internal.R.integer.config_longPressOnAppSwitchBehavior);
2094 mLongPressOnHomeBehavior = res.getInteger(
2095 com.android.internal.R.integer.config_longPressOnHomeBehavior);
2096 if (mLongPressOnHomeBehavior < KEY_ACTION_NOTHING ||
2097 mLongPressOnHomeBehavior > KEY_ACTION_SLEEP) {
2098 mLongPressOnHomeBehavior = KEY_ACTION_NOTHING;
2101 mDoubleTapOnHomeBehavior = res.getInteger(
2102 com.android.internal.R.integer.config_doubleTapOnHomeBehavior);
2103 if (mDoubleTapOnHomeBehavior < KEY_ACTION_NOTHING ||
2104 mDoubleTapOnHomeBehavior > KEY_ACTION_SLEEP) {
2105 mDoubleTapOnHomeBehavior = KEY_ACTION_NOTHING;
2108 // Check for custom assignments and whether KEY_ACTION_MENU is assigned.
2110 mLongPressOnHomeBehavior = CMSettings.System.getIntForUser(resolver,
2111 CMSettings.System.KEY_HOME_LONG_PRESS_ACTION,
2112 mLongPressOnHomeBehavior, UserHandle.USER_CURRENT);
2113 mDoubleTapOnHomeBehavior = CMSettings.System.getIntForUser(resolver,
2114 CMSettings.System.KEY_HOME_DOUBLE_TAP_ACTION,
2115 mDoubleTapOnHomeBehavior, UserHandle.USER_CURRENT);
2118 mPressOnMenuBehavior = CMSettings.System.getIntForUser(resolver,
2119 CMSettings.System.KEY_MENU_ACTION,
2120 mPressOnMenuBehavior, UserHandle.USER_CURRENT);
2121 mLongPressOnMenuBehavior = CMSettings.System.getIntForUser(resolver,
2122 CMSettings.System.KEY_MENU_LONG_PRESS_ACTION,
2123 mLongPressOnMenuBehavior, UserHandle.USER_CURRENT);
2126 mPressOnAssistBehavior = CMSettings.System.getIntForUser(resolver,
2127 CMSettings.System.KEY_ASSIST_ACTION,
2128 mPressOnAssistBehavior, UserHandle.USER_CURRENT);
2129 mLongPressOnAssistBehavior = CMSettings.System.getIntForUser(resolver,
2130 CMSettings.System.KEY_ASSIST_LONG_PRESS_ACTION,
2131 mLongPressOnAssistBehavior, UserHandle.USER_CURRENT);
2134 mPressOnAppSwitchBehavior = CMSettings.System.getIntForUser(resolver,
2135 CMSettings.System.KEY_APP_SWITCH_ACTION,
2136 mPressOnAppSwitchBehavior, UserHandle.USER_CURRENT);
2137 mLongPressOnAppSwitchBehavior = CMSettings.System.getIntForUser(resolver,
2138 CMSettings.System.KEY_APP_SWITCH_LONG_PRESS_ACTION,
2139 mLongPressOnAppSwitchBehavior, UserHandle.USER_CURRENT);
2142 mShortPressWindowBehavior = SHORT_PRESS_WINDOW_NOTHING;
2143 if (mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
2144 mShortPressWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE;
2147 mNavBarOpacityMode = res.getInteger(
2148 com.android.internal.R.integer.config_navBarOpacityMode);
2152 public void setInitialDisplaySize(Display display, int width, int height, int density) {
2153 // This method might be called before the policy has been fully initialized
2154 // or for other displays we don't care about.
2155 if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) {
2160 final Resources res = mContext.getResources();
2161 int shortSize, longSize;
2162 if (width > height) {
2165 mLandscapeRotation = Surface.ROTATION_0;
2166 mSeascapeRotation = Surface.ROTATION_180;
2167 if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
2168 mPortraitRotation = Surface.ROTATION_90;
2169 mUpsideDownRotation = Surface.ROTATION_270;
2171 mPortraitRotation = Surface.ROTATION_270;
2172 mUpsideDownRotation = Surface.ROTATION_90;
2177 mPortraitRotation = Surface.ROTATION_0;
2178 mUpsideDownRotation = Surface.ROTATION_180;
2179 if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
2180 mLandscapeRotation = Surface.ROTATION_270;
2181 mSeascapeRotation = Surface.ROTATION_90;
2183 mLandscapeRotation = Surface.ROTATION_90;
2184 mSeascapeRotation = Surface.ROTATION_270;
2188 // SystemUI (status bar) layout policy
2189 int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
2190 int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
2192 // Allow the navigation bar to move on non-square small devices (phones).
2193 mNavigationBarCanMove = width != height && shortSizeDp < 600;
2195 mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
2197 // Allow a system property to override this. Used by the emulator.
2198 // See also hasNavigationBar().
2199 String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
2200 if ("1".equals(navBarOverride)) {
2201 mHasNavigationBar = false;
2202 } else if ("0".equals(navBarOverride)) {
2203 mHasNavigationBar = true;
2206 // For demo purposes, allow the rotation of the HDMI display to be controlled.
2207 // By default, HDMI locks rotation to landscape.
2208 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
2209 mDemoHdmiRotation = mPortraitRotation;
2211 mDemoHdmiRotation = mLandscapeRotation;
2213 mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
2215 // For demo purposes, allow the rotation of the remote display to be controlled.
2216 // By default, remote display locks rotation to landscape.
2217 if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
2218 mDemoRotation = mPortraitRotation;
2220 mDemoRotation = mLandscapeRotation;
2222 mDemoRotationLock = SystemProperties.getBoolean(
2223 "persist.demo.rotationlock", false);
2225 // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
2226 // http://developer.android.com/guide/practices/screens_support.html#range
2227 mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 &&
2228 res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
2229 // For debug purposes the next line turns this feature off with:
2230 // $ adb shell setprop config.override_forced_orient true
2231 // $ adb shell wm size reset
2232 !"true".equals(SystemProperties.get("config.override_forced_orient"));
2236 * @return whether the navigation bar can be hidden, e.g. the device has a
2237 * navigation bar and touch exploration is not enabled
2239 private boolean canHideNavigationBar() {
2240 return hasNavigationBar();
2244 public boolean isDefaultOrientationForced() {
2245 return mForceDefaultOrientation;
2249 public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) {
2250 if (display.getDisplayId() == Display.DEFAULT_DISPLAY) {
2251 mOverscanLeft = left;
2253 mOverscanRight = right;
2254 mOverscanBottom = bottom;
2258 public void updateSettings() {
2259 ContentResolver resolver = mContext.getContentResolver();
2260 boolean updateRotation = false;
2261 int mDeviceHardwareWakeKeys = mContext.getResources().getInteger(
2262 com.android.internal.R.integer.config_deviceHardwareWakeKeys);
2263 synchronized (mLock) {
2264 mEndcallBehavior = Settings.System.getIntForUser(resolver,
2265 Settings.System.END_BUTTON_BEHAVIOR,
2266 Settings.System.END_BUTTON_BEHAVIOR_DEFAULT,
2267 UserHandle.USER_CURRENT);
2268 mHomeWakeScreen = (CMSettings.System.getIntForUser(resolver,
2269 CMSettings.System.HOME_WAKE_SCREEN, 1, UserHandle.USER_CURRENT) == 1) &&
2270 ((mDeviceHardwareWakeKeys & KEY_MASK_HOME) != 0);
2271 mBackWakeScreen = (CMSettings.System.getIntForUser(resolver,
2272 CMSettings.System.BACK_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1) &&
2273 ((mDeviceHardwareWakeKeys & KEY_MASK_BACK) != 0);
2274 mMenuWakeScreen = (CMSettings.System.getIntForUser(resolver,
2275 CMSettings.System.MENU_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1) &&
2276 ((mDeviceHardwareWakeKeys & KEY_MASK_MENU) != 0);
2277 mAssistWakeScreen = (CMSettings.System.getIntForUser(resolver,
2278 CMSettings.System.ASSIST_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1) &&
2279 ((mDeviceHardwareWakeKeys & KEY_MASK_ASSIST) != 0);
2280 mAppSwitchWakeScreen = (CMSettings.System.getIntForUser(resolver,
2281 CMSettings.System.APP_SWITCH_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1) &&
2282 ((mDeviceHardwareWakeKeys & KEY_MASK_APP_SWITCH) != 0);
2283 mCameraWakeScreen = (CMSettings.System.getIntForUser(resolver,
2284 CMSettings.System.CAMERA_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1) &&
2285 ((mDeviceHardwareWakeKeys & KEY_MASK_CAMERA) != 0);
2286 mCameraSleepOnRelease = (CMSettings.System.getIntForUser(resolver,
2287 CMSettings.System.CAMERA_SLEEP_ON_RELEASE, 0, UserHandle.USER_CURRENT) == 1);
2288 mCameraLaunch = (CMSettings.System.getIntForUser(resolver,
2289 CMSettings.System.CAMERA_LAUNCH, 0, UserHandle.USER_CURRENT) == 1);
2290 mVolumeWakeScreen = (CMSettings.System.getIntForUser(resolver,
2291 CMSettings.System.VOLUME_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1) &&
2292 ((mDeviceHardwareWakeKeys & KEY_MASK_VOLUME) != 0);
2293 mVolBtnMusicControls = (CMSettings.System.getIntForUser(resolver,
2294 CMSettings.System.VOLBTN_MUSIC_CONTROLS, 1, UserHandle.USER_CURRENT) == 1);
2296 // Configure wake gesture.
2297 boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver,
2298 Settings.Secure.WAKE_GESTURE_ENABLED, 0,
2299 UserHandle.USER_CURRENT) != 0;
2300 if (mWakeGestureEnabledSetting != wakeGestureEnabledSetting) {
2301 mWakeGestureEnabledSetting = wakeGestureEnabledSetting;
2302 updateWakeGestureListenerLp();
2305 boolean devForceNavbar = CMSettings.Global.getIntForUser(resolver,
2306 CMSettings.Global.DEV_FORCE_SHOW_NAVBAR, 0, UserHandle.USER_CURRENT) == 1;
2307 if (devForceNavbar != mDevForceNavbar) {
2308 mDevForceNavbar = devForceNavbar;
2309 if (mCMHardware.isSupported(CMHardwareManager.FEATURE_KEY_DISABLE)) {
2310 mCMHardware.set(CMHardwareManager.FEATURE_KEY_DISABLE, mDevForceNavbar);
2314 mNavigationBarLeftInLandscape = CMSettings.System.getIntForUser(resolver,
2315 CMSettings.System.NAVBAR_LEFT_IN_LANDSCAPE, 0, UserHandle.USER_CURRENT) == 1;
2317 updateKeyAssignments();
2319 // Configure rotation lock.
2320 int userRotation = Settings.System.getIntForUser(resolver,
2321 Settings.System.USER_ROTATION, Surface.ROTATION_0,
2322 UserHandle.USER_CURRENT);
2323 if (mUserRotation != userRotation) {
2324 mUserRotation = userRotation;
2325 updateRotation = true;
2327 int userRotationMode = Settings.System.getIntForUser(resolver,
2328 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
2329 WindowManagerPolicy.USER_ROTATION_FREE :
2330 WindowManagerPolicy.USER_ROTATION_LOCKED;
2331 if (mUserRotationMode != userRotationMode) {
2332 mUserRotationMode = userRotationMode;
2333 updateRotation = true;
2334 updateOrientationListenerLp();
2337 mUserRotationAngles = Settings.System.getInt(resolver,
2338 Settings.System.ACCELEROMETER_ROTATION_ANGLES, -1);
2341 int pointerLocation = Settings.System.getIntForUser(resolver,
2342 Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT);
2343 if (mPointerLocationMode != pointerLocation) {
2344 mPointerLocationMode = pointerLocation;
2345 mHandler.sendEmptyMessage(pointerLocation != 0 ?
2346 MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
2349 // use screen off timeout setting as the timeout for the lockscreen
2350 mLockScreenTimeout = Settings.System.getIntForUser(resolver,
2351 Settings.System.SCREEN_OFF_TIMEOUT, 0, UserHandle.USER_CURRENT);
2352 String imId = Settings.Secure.getStringForUser(resolver,
2353 Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.USER_CURRENT);
2354 boolean hasSoftInput = imId != null && imId.length() > 0;
2355 if (mHasSoftInput != hasSoftInput) {
2356 mHasSoftInput = hasSoftInput;
2357 updateRotation = true;
2359 if (mImmersiveModeConfirmation != null) {
2360 mImmersiveModeConfirmation.loadSetting(mCurrentUserId);
2363 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
2364 PolicyControl.reloadFromSetting(mContext);
2366 if (updateRotation) {
2367 updateRotation(true);
2371 private void updateWakeGestureListenerLp() {
2372 if (shouldEnableWakeGestureLp()) {
2373 mWakeGestureListener.requestWakeUpTrigger();
2375 mWakeGestureListener.cancelWakeUpTrigger();
2379 private boolean shouldEnableWakeGestureLp() {
2380 return mWakeGestureEnabledSetting && !mAwake
2381 && (!mLidControlsSleep || mLidState != LID_CLOSED)
2382 && mWakeGestureListener.isSupported();
2385 private void enablePointerLocation() {
2386 if (mPointerLocationView == null) {
2387 mPointerLocationView = new PointerLocationView(mContext);
2388 mPointerLocationView.setPrintCoords(false);
2389 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
2390 WindowManager.LayoutParams.MATCH_PARENT,
2391 WindowManager.LayoutParams.MATCH_PARENT);
2392 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
2393 lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
2394 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
2395 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2396 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
2397 if (ActivityManager.isHighEndGfx()) {
2398 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
2400 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
2402 lp.format = PixelFormat.TRANSLUCENT;
2403 lp.setTitle("PointerLocation");
2404 WindowManager wm = (WindowManager)
2405 mContext.getSystemService(Context.WINDOW_SERVICE);
2406 lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
2407 wm.addView(mPointerLocationView, lp);
2408 mWindowManagerFuncs.registerPointerEventListener(mPointerLocationView);
2412 private void disablePointerLocation() {
2413 if (mPointerLocationView != null) {
2414 mWindowManagerFuncs.unregisterPointerEventListener(mPointerLocationView);
2415 WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
2416 wm.removeView(mPointerLocationView);
2417 mPointerLocationView = null;
2421 private int readRotation(int resID) {
2423 int rotation = mContext.getResources().getInteger(resID);
2426 return Surface.ROTATION_0;
2428 return Surface.ROTATION_90;
2430 return Surface.ROTATION_180;
2432 return Surface.ROTATION_270;
2434 } catch (Resources.NotFoundException e) {
2440 /** {@inheritDoc} */
2442 public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) {
2443 int type = attrs.type;
2445 outAppOp[0] = AppOpsManager.OP_NONE;
2447 if (!((type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW)
2448 || (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW)
2449 || (type >= FIRST_SYSTEM_WINDOW && type <= LAST_SYSTEM_WINDOW))) {
2450 return WindowManagerGlobal.ADD_INVALID_TYPE;
2453 if (type < FIRST_SYSTEM_WINDOW || type > LAST_SYSTEM_WINDOW) {
2454 // Window manager will make sure these are okay.
2455 return WindowManagerGlobal.ADD_OKAY;
2457 String permission = null;
2460 // XXX right now the app process has complete control over
2461 // this... should introduce a token to let the system
2462 // monitor/control what they are doing.
2463 outAppOp[0] = AppOpsManager.OP_TOAST_WINDOW;
2466 case TYPE_INPUT_METHOD:
2467 case TYPE_WALLPAPER:
2468 case TYPE_PRIVATE_PRESENTATION:
2469 case TYPE_VOICE_INTERACTION:
2470 case TYPE_ACCESSIBILITY_OVERLAY:
2471 case TYPE_QS_DIALOG:
2472 // The window manager will check these.
2475 case TYPE_PRIORITY_PHONE:
2476 case TYPE_SYSTEM_ALERT:
2477 case TYPE_SYSTEM_ERROR:
2478 case TYPE_SYSTEM_OVERLAY:
2479 permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
2480 outAppOp[0] = AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
2483 permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
2485 if (permission != null) {
2486 if (android.Manifest.permission.SYSTEM_ALERT_WINDOW.equals(permission)) {
2487 final int callingUid = Binder.getCallingUid();
2488 // system processes will be automatically allowed privilege to draw
2489 if (callingUid == Process.SYSTEM_UID) {
2490 return WindowManagerGlobal.ADD_OKAY;
2493 // check if user has enabled this operation. SecurityException will be thrown if
2494 // this app has not been allowed by the user
2495 final int mode = mAppOpsManager.checkOpNoThrow(outAppOp[0], callingUid,
2498 case AppOpsManager.MODE_ALLOWED:
2499 case AppOpsManager.MODE_IGNORED:
2500 // although we return ADD_OKAY for MODE_IGNORED, the added window will
2501 // actually be hidden in WindowManagerService
2502 return WindowManagerGlobal.ADD_OKAY;
2503 case AppOpsManager.MODE_ERRORED:
2505 ApplicationInfo appInfo = mContext.getPackageManager()
2506 .getApplicationInfo(attrs.packageName,
2507 UserHandle.getUserId(callingUid));
2508 // Don't crash legacy apps
2509 if (appInfo.targetSdkVersion < Build.VERSION_CODES.M) {
2510 return WindowManagerGlobal.ADD_OKAY;
2512 } catch (PackageManager.NameNotFoundException e) {
2515 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
2517 // in the default mode, we will make a decision here based on
2518 // checkCallingPermission()
2519 if (mContext.checkCallingPermission(permission) !=
2520 PackageManager.PERMISSION_GRANTED) {
2521 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
2523 return WindowManagerGlobal.ADD_OKAY;
2528 if (mContext.checkCallingOrSelfPermission(permission)
2529 != PackageManager.PERMISSION_GRANTED) {
2530 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
2533 return WindowManagerGlobal.ADD_OKAY;
2537 public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) {
2539 // If this switch statement is modified, modify the comment in the declarations of
2540 // the type in {@link WindowManager.LayoutParams} as well.
2541 switch (attrs.type) {
2543 // These are the windows that by default are shown only to the user that created
2544 // them. If this needs to be overridden, set
2545 // {@link WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS} in
2546 // {@link WindowManager.LayoutParams}. Note that permission
2547 // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well.
2548 if ((attrs.privateFlags & PRIVATE_FLAG_SHOW_FOR_ALL_USERS) == 0) {
2553 // These are the windows that by default are shown to all users. However, to
2554 // protect against spoofing, check permissions below.
2555 case TYPE_APPLICATION_STARTING:
2556 case TYPE_BOOT_PROGRESS:
2557 case TYPE_DISPLAY_OVERLAY:
2558 case TYPE_INPUT_CONSUMER:
2559 case TYPE_KEYGUARD_SCRIM:
2560 case TYPE_KEYGUARD_DIALOG:
2561 case TYPE_MAGNIFICATION_OVERLAY:
2562 case TYPE_NAVIGATION_BAR:
2563 case TYPE_NAVIGATION_BAR_PANEL:
2566 case TYPE_PRIORITY_PHONE:
2567 case TYPE_SEARCH_BAR:
2568 case TYPE_STATUS_BAR:
2569 case TYPE_STATUS_BAR_PANEL:
2570 case TYPE_STATUS_BAR_SUB_PANEL:
2571 case TYPE_SYSTEM_DIALOG:
2572 case TYPE_VOLUME_OVERLAY:
2573 case TYPE_PRIVATE_PRESENTATION:
2574 case TYPE_DOCK_DIVIDER:
2578 // Check if third party app has set window to system window type.
2579 return mContext.checkCallingOrSelfPermission(
2580 android.Manifest.permission.INTERNAL_SYSTEM_WINDOW)
2581 != PackageManager.PERMISSION_GRANTED;
2585 public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
2586 switch (attrs.type) {
2587 case TYPE_SYSTEM_OVERLAY:
2588 case TYPE_SECURE_SYSTEM_OVERLAY:
2589 // These types of windows can't receive input events.
2590 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2591 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
2592 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
2594 case TYPE_STATUS_BAR:
2596 // If the Keyguard is in a hidden state (occluded by another window), we force to
2597 // remove the wallpaper and keyguard flag so that any change in-flight after setting
2598 // the keyguard as occluded wouldn't set these flags again.
2599 // See {@link #processKeyguardSetHiddenResultLw}.
2600 if (mKeyguardHidden) {
2601 attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
2602 attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2607 if (attrs.type != TYPE_STATUS_BAR) {
2608 // The status bar is the only window allowed to exhibit keyguard behavior.
2609 attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2612 if (ActivityManager.isHighEndGfx()) {
2613 if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
2614 attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
2616 final boolean forceWindowDrawsStatusBarBackground =
2617 (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND)
2619 if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
2620 || forceWindowDrawsStatusBarBackground
2621 && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) {
2622 attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2627 void readLidState() {
2628 mLidState = mWindowManagerFuncs.getLidState();
2631 private void readCameraLensCoverState() {
2632 mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState();
2635 private boolean isHidden(int accessibilityMode) {
2636 switch (accessibilityMode) {
2638 return mLidState == LID_CLOSED;
2640 return mLidState == LID_OPEN;
2646 private boolean isBuiltInKeyboardVisible() {
2647 return mHaveBuiltInKeyboard && !isHidden(mLidKeyboardAccessibility);
2650 /** {@inheritDoc} */
2652 public void adjustConfigurationLw(Configuration config, int keyboardPresence,
2653 int navigationPresence) {
2654 mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0;
2658 if (config.keyboard == Configuration.KEYBOARD_NOKEYS
2659 || (keyboardPresence == PRESENCE_INTERNAL
2660 && isHidden(mLidKeyboardAccessibility))) {
2661 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
2662 if (!mHasSoftInput) {
2663 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
2667 if (config.navigation == Configuration.NAVIGATION_NONAV
2668 || (navigationPresence == PRESENCE_INTERNAL
2669 && isHidden(mLidNavigationAccessibility))) {
2670 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
2675 public void onConfigurationChanged() {
2676 final Resources res = mContext.getResources();
2679 res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
2681 // Height of the navigation bar when presented horizontally at bottom
2682 mNavigationBarHeightForRotationDefault[mPortraitRotation] =
2683 mNavigationBarHeightForRotationDefault[mUpsideDownRotation] =
2684 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
2685 mNavigationBarHeightForRotationDefault[mLandscapeRotation] =
2686 mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize(
2687 com.android.internal.R.dimen.navigation_bar_height_landscape);
2689 // Width of the navigation bar when presented vertically along one side
2690 mNavigationBarWidthForRotationDefault[mPortraitRotation] =
2691 mNavigationBarWidthForRotationDefault[mUpsideDownRotation] =
2692 mNavigationBarWidthForRotationDefault[mLandscapeRotation] =
2693 mNavigationBarWidthForRotationDefault[mSeascapeRotation] =
2694 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
2696 // Height of the navigation bar when presented horizontally at bottom
2697 mNavigationBarHeightForRotationInCarMode[mPortraitRotation] =
2698 mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] =
2699 res.getDimensionPixelSize(
2700 com.android.internal.R.dimen.navigation_bar_height_car_mode);
2701 mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] =
2702 mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize(
2703 com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode);
2705 // Width of the navigation bar when presented vertically along one side
2706 mNavigationBarWidthForRotationInCarMode[mPortraitRotation] =
2707 mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] =
2708 mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] =
2709 mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] =
2710 res.getDimensionPixelSize(
2711 com.android.internal.R.dimen.navigation_bar_width_car_mode);
2714 /** {@inheritDoc} */
2716 public int windowTypeToLayerLw(int type) {
2717 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
2721 case TYPE_PRIVATE_PRESENTATION:
2723 case TYPE_WALLPAPER:
2724 // wallpaper is at the bottom, though the window manager may move it.
2726 case TYPE_DOCK_DIVIDER:
2728 case TYPE_QS_DIALOG:
2732 case TYPE_SEARCH_BAR:
2733 case TYPE_VOICE_INTERACTION_STARTING:
2735 case TYPE_VOICE_INTERACTION:
2736 // voice interaction layer is almost immediately above apps.
2738 case TYPE_INPUT_CONSUMER:
2740 case TYPE_SYSTEM_DIALOG:
2743 // toasts and the plugged-in battery thing
2745 case TYPE_PRIORITY_PHONE:
2746 // SIM errors and unlock. Not sure if this really should be in a high layer.
2749 // used for Dreams (screensavers with TYPE_DREAM windows)
2751 case TYPE_SYSTEM_ALERT:
2752 // like the ANR / app crashed dialogs
2754 case TYPE_INPUT_METHOD:
2755 // on-screen keyboards and other such input method user interfaces go here.
2757 case TYPE_INPUT_METHOD_DIALOG:
2758 // on-screen keyboards and other such input method user interfaces go here.
2760 case TYPE_KEYGUARD_SCRIM:
2761 // the safety window that shows behind keyguard while keyguard is starting
2763 case TYPE_STATUS_BAR_SUB_PANEL:
2765 case TYPE_STATUS_BAR:
2767 case TYPE_STATUS_BAR_PANEL:
2769 case TYPE_KEYGUARD_DIALOG:
2771 case TYPE_VOLUME_OVERLAY:
2772 // the on-screen volume indicator and controller shown when the user
2773 // changes the device volume
2775 case TYPE_SYSTEM_OVERLAY:
2776 // the on-screen volume indicator and controller shown when the user
2777 // changes the device volume
2779 case TYPE_NAVIGATION_BAR:
2780 // the navigation bar, if available, shows atop most things
2782 case TYPE_NAVIGATION_BAR_PANEL:
2783 // some panels (e.g. search) need to show on top of the navigation bar
2785 case TYPE_SCREENSHOT:
2786 // screenshot selection layer shouldn't go above system error, but it should cover
2787 // navigation bars at the very least.
2789 case TYPE_SYSTEM_ERROR:
2790 // system-level error dialogs
2792 case TYPE_MAGNIFICATION_OVERLAY:
2793 // used to highlight the magnified portion of a display
2795 case TYPE_DISPLAY_OVERLAY:
2796 // used to simulate secondary display devices
2799 // the drag layer: input for drag-and-drop is associated with this window,
2800 // which sits above all other focusable windows
2802 case TYPE_ACCESSIBILITY_OVERLAY:
2803 // overlay put by accessibility services to intercept user interaction
2805 case TYPE_SECURE_SYSTEM_OVERLAY:
2807 case TYPE_BOOT_PROGRESS:
2810 // the (mouse) pointer layer
2813 Log.e(TAG, "Unknown window type: " + type);
2817 /** {@inheritDoc} */
2819 public int subWindowTypeToLayerLw(int type) {
2821 case TYPE_APPLICATION_PANEL:
2822 case TYPE_APPLICATION_ATTACHED_DIALOG:
2823 return APPLICATION_PANEL_SUBLAYER;
2824 case TYPE_APPLICATION_MEDIA:
2825 return APPLICATION_MEDIA_SUBLAYER;
2826 case TYPE_APPLICATION_MEDIA_OVERLAY:
2827 return APPLICATION_MEDIA_OVERLAY_SUBLAYER;
2828 case TYPE_APPLICATION_SUB_PANEL:
2829 return APPLICATION_SUB_PANEL_SUBLAYER;
2830 case TYPE_APPLICATION_ABOVE_SUB_PANEL:
2831 return APPLICATION_ABOVE_SUB_PANEL_SUBLAYER;
2833 Log.e(TAG, "Unknown sub-window type: " + type);
2838 public int getMaxWallpaperLayer() {
2839 return windowTypeToLayerLw(TYPE_STATUS_BAR);
2842 private int getNavigationBarWidth(int rotation, int uiMode) {
2843 if ((uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2844 return mNavigationBarWidthForRotationInCarMode[rotation];
2846 return mNavigationBarWidthForRotationDefault[rotation];
2851 public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation,
2853 if (hasNavigationBar()) {
2854 // For a basic navigation bar, when we are in landscape mode we place
2855 // the navigation bar to the side.
2856 if (mNavigationBarCanMove && fullWidth > fullHeight) {
2857 return fullWidth - getNavigationBarWidth(rotation, uiMode);
2863 private int getNavigationBarHeight(int rotation, int uiMode) {
2864 if ((uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2865 return mNavigationBarHeightForRotationInCarMode[rotation];
2867 return mNavigationBarHeightForRotationDefault[rotation];
2872 public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation,
2874 if (hasNavigationBar()) {
2875 // For a basic navigation bar, when we are in portrait mode we place
2876 // the navigation bar to the bottom.
2877 if (!mNavigationBarCanMove || fullWidth < fullHeight) {
2878 return fullHeight - getNavigationBarHeight(rotation, uiMode);
2885 public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode) {
2886 return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode);
2890 public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode) {
2891 // There is a separate status bar at the top of the display. We don't count that as part
2892 // of the fixed decor, since it can hide; however, for purposes of configurations,
2893 // we do want to exclude it since applications can't generally use that part
2895 return getNonDecorDisplayHeight(
2896 fullWidth, fullHeight, rotation, uiMode) - mStatusBarHeight;
2900 public boolean isForceHiding(WindowManager.LayoutParams attrs) {
2901 return (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
2902 (isKeyguardHostWindow(attrs) &&
2903 (mKeyguardDelegate != null && mKeyguardDelegate.isShowing())) ||
2904 (attrs.type == TYPE_KEYGUARD_SCRIM);
2908 public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) {
2909 return attrs.type == TYPE_STATUS_BAR;
2913 public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
2914 switch (attrs.type) {
2915 case TYPE_STATUS_BAR:
2916 case TYPE_NAVIGATION_BAR:
2917 case TYPE_WALLPAPER:
2919 case TYPE_KEYGUARD_SCRIM:
2922 // Hide only windows below the keyguard host window.
2923 return windowTypeToLayerLw(win.getBaseType())
2924 < windowTypeToLayerLw(TYPE_STATUS_BAR);
2929 public WindowState getWinShowWhenLockedLw() {
2930 return mWinShowWhenLocked;
2933 /** {@inheritDoc} */
2935 public View addStartingWindow(IBinder appToken, String packageName, int theme,
2936 CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
2937 int icon, int logo, int windowFlags, Configuration overrideConfig) {
2938 if (!SHOW_STARTING_ANIMATIONS) {
2941 if (packageName == null) {
2945 WindowManager wm = null;
2949 Context context = mContext;
2950 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow " + packageName
2951 + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
2952 + Integer.toHexString(theme));
2953 if (theme != context.getThemeResId() || labelRes != 0) {
2955 context = context.createPackageContext(packageName, 0);
2956 context.setTheme(theme);
2957 } catch (PackageManager.NameNotFoundException e) {
2962 if (overrideConfig != null && overrideConfig != EMPTY) {
2963 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: creating context based"
2964 + " on overrideConfig" + overrideConfig + " for starting window");
2965 final Context overrideContext = context.createConfigurationContext(overrideConfig);
2966 overrideContext.setTheme(theme);
2967 final TypedArray typedArray = overrideContext.obtainStyledAttributes(
2968 com.android.internal.R.styleable.Window);
2969 final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
2970 if (resId != 0 && overrideContext.getDrawable(resId) != null) {
2971 // We want to use the windowBackground for the override context if it is
2972 // available, otherwise we use the default one to make sure a themed starting
2973 // window is displayed for the app.
2974 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: apply overrideConfig"
2975 + overrideConfig + " to starting window resId=" + resId);
2976 context = overrideContext;
2980 final PhoneWindow win = new PhoneWindow(context);
2981 win.setIsStartingWindow(true);
2983 CharSequence label = context.getResources().getText(labelRes, null);
2984 // Only change the accessibility title if the label is localized
2985 if (label != null) {
2986 win.setTitle(label, true);
2988 win.setTitle(nonLocalizedLabel, false);
2992 WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
2994 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
2995 // Assumes it's safe to show starting windows of launched apps while
2996 // the keyguard is being hidden. This is okay because starting windows never show
2997 // secret information.
2998 if (mKeyguardHidden) {
2999 windowFlags |= FLAG_SHOW_WHEN_LOCKED;
3003 // Force the window flags: this is a fake window, so it is not really
3004 // touchable or focusable by the user. We also add in the ALT_FOCUSABLE_IM
3005 // flag because we do know that the next window will take input
3006 // focus, so we want to get the IME window up on top of us right away.
3009 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
3010 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
3011 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
3013 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
3014 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
3015 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
3017 win.setDefaultIcon(icon);
3018 win.setDefaultLogo(logo);
3020 win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
3021 WindowManager.LayoutParams.MATCH_PARENT);
3023 final WindowManager.LayoutParams params = win.getAttributes();
3024 params.token = appToken;
3025 params.packageName = packageName;
3026 params.windowAnimations = win.getWindowStyle().getResourceId(
3027 com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
3028 params.privateFlags |=
3029 WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
3030 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
3032 if (!compatInfo.supportsScreen()) {
3033 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
3036 params.setTitle("Starting " + packageName);
3038 wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
3039 view = win.getDecorView();
3041 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Adding starting window for "
3042 + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null));
3044 wm.addView(view, params);
3046 // Only return the view if it was successfully added to the
3047 // window manager... which we can tell by it having a parent.
3048 return view.getParent() != null ? view : null;
3049 } catch (WindowManager.BadTokenException e) {
3051 Log.w(TAG, appToken + " already running, starting window not displayed. " +
3053 } catch (RuntimeException e) {
3054 // don't crash if something else bad happens, for example a
3055 // failure loading resources because we are loading from an app
3056 // on external storage that has been unmounted.
3057 Log.w(TAG, appToken + " failed creating starting window", e);
3059 if (view != null && view.getParent() == null) {
3060 Log.w(TAG, "view not successfully added to wm, removing view");
3061 wm.removeViewImmediate(view);
3068 /** {@inheritDoc} */
3070 public void removeStartingWindow(IBinder appToken, View window) {
3071 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Removing starting window for " + appToken + ": "
3072 + window + " Callers=" + Debug.getCallers(4));
3074 if (window != null) {
3075 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
3076 wm.removeView(window);
3081 * Preflight adding a window to the system.
3083 * Currently enforces that three window types are singletons:
3085 * <li>STATUS_BAR_TYPE</li>
3086 * <li>KEYGUARD_TYPE</li>
3089 * @param win The window to be added
3090 * @param attrs Information about the window to be added
3092 * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons,
3093 * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
3096 public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
3097 switch (attrs.type) {
3098 case TYPE_STATUS_BAR:
3099 mContext.enforceCallingOrSelfPermission(
3100 android.Manifest.permission.STATUS_BAR_SERVICE,
3101 "PhoneWindowManager");
3102 if (mStatusBar != null) {
3103 if (mStatusBar.isAlive()) {
3104 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
3108 mStatusBarController.setWindow(win);
3110 case TYPE_NAVIGATION_BAR:
3111 mContext.enforceCallingOrSelfPermission(
3112 android.Manifest.permission.STATUS_BAR_SERVICE,
3113 "PhoneWindowManager");
3114 if (mNavigationBar != null) {
3115 if (mNavigationBar.isAlive()) {
3116 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
3119 mNavigationBar = win;
3120 mNavigationBarController.setWindow(win);
3121 if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
3123 case TYPE_NAVIGATION_BAR_PANEL:
3124 case TYPE_STATUS_BAR_PANEL:
3125 case TYPE_STATUS_BAR_SUB_PANEL:
3126 case TYPE_VOICE_INTERACTION_STARTING:
3127 mContext.enforceCallingOrSelfPermission(
3128 android.Manifest.permission.STATUS_BAR_SERVICE,
3129 "PhoneWindowManager");
3131 case TYPE_KEYGUARD_SCRIM:
3132 if (mKeyguardScrim != null) {
3133 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
3135 mKeyguardScrim = win;
3138 return WindowManagerGlobal.ADD_OKAY;
3141 /** {@inheritDoc} */
3143 public void removeWindowLw(WindowState win) {
3144 if (mStatusBar == win) {
3146 mStatusBarController.setWindow(null);
3147 mKeyguardDelegate.showScrim();
3148 } else if (mKeyguardScrim == win) {
3149 Log.v(TAG, "Removing keyguard scrim");
3150 mKeyguardScrim = null;
3151 } if (mNavigationBar == win) {
3152 mNavigationBar = null;
3153 mNavigationBarController.setWindow(null);
3157 static final boolean PRINT_ANIM = false;
3159 /** {@inheritDoc} */
3161 public int selectAnimationLw(WindowState win, int transit) {
3162 if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
3163 + ": transit=" + transit);
3164 if (win == mStatusBar) {
3165 boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
3166 if (transit == TRANSIT_EXIT
3167 || transit == TRANSIT_HIDE) {
3168 return isKeyguard ? -1 : R.anim.dock_top_exit;
3169 } else if (transit == TRANSIT_ENTER
3170 || transit == TRANSIT_SHOW) {
3171 return isKeyguard ? -1 : R.anim.dock_top_enter;
3173 } else if (win == mNavigationBar) {
3174 if (win.getAttrs().windowAnimations != 0) {
3177 // This can be on either the bottom, left, or the right.
3178 if (mNavigationBarOnBottom) {
3179 if (transit == TRANSIT_EXIT
3180 || transit == TRANSIT_HIDE) {
3181 return R.anim.dock_bottom_exit;
3182 } else if (transit == TRANSIT_ENTER
3183 || transit == TRANSIT_SHOW) {
3184 return R.anim.dock_bottom_enter;
3187 if (transit == TRANSIT_EXIT
3188 || transit == TRANSIT_HIDE) {
3189 return mNavigationBarLeftInLandscape
3190 ? R.anim.dock_left_exit : R.anim.dock_right_exit;
3191 } else if (transit == TRANSIT_ENTER
3192 || transit == TRANSIT_SHOW) {
3193 return mNavigationBarLeftInLandscape
3194 ? R.anim.dock_left_enter : R.anim.dock_right_enter;
3197 } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) {
3198 return selectDockedDividerAnimationLw(win, transit);
3201 if (transit == TRANSIT_PREVIEW_DONE) {
3202 if (win.hasAppShownWindows()) {
3203 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
3204 return com.android.internal.R.anim.app_starting_exit;
3206 } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
3207 && transit == TRANSIT_ENTER) {
3208 // Special case: we are animating in a dream, while the keyguard
3209 // is shown. We don't want an animation on the dream, because
3210 // we need it shown immediately with the keyguard animating away
3218 private int selectDockedDividerAnimationLw(WindowState win, int transit) {
3219 int insets = mWindowManagerFuncs.getDockedDividerInsetsLw();
3221 // If the divider is behind the navigation bar, don't animate.
3222 final Rect frame = win.getFrameLw();
3223 final boolean behindNavBar = mNavigationBar != null
3224 && ((mNavigationBarOnBottom
3225 && frame.top + insets >= mNavigationBar.getFrameLw().top)
3226 || (!mNavigationBarOnBottom
3227 && frame.left + insets >= mNavigationBar.getFrameLw().left));
3228 final boolean landscape = frame.height() > frame.width();
3229 final boolean offscreenLandscape = landscape && (frame.right - insets <= 0
3230 || frame.left + insets >= win.getDisplayFrameLw().right);
3231 final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0
3232 || frame.bottom + insets >= win.getDisplayFrameLw().bottom);
3233 final boolean offscreen = offscreenLandscape || offscreenPortrait;
3234 if (behindNavBar || offscreen) {
3237 if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
3238 return R.anim.fade_in;
3239 } else if (transit == TRANSIT_EXIT) {
3240 return R.anim.fade_out;
3247 public void selectRotationAnimationLw(int anim[]) {
3248 if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
3249 + mTopFullscreenOpaqueWindowState + " rotationAnimation="
3250 + (mTopFullscreenOpaqueWindowState == null ?
3251 "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation));
3252 if (mTopFullscreenOpaqueWindowState != null && mTopIsFullscreen) {
3253 switch (mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation) {
3254 case ROTATION_ANIMATION_CROSSFADE:
3255 anim[0] = R.anim.rotation_animation_xfade_exit;
3256 anim[1] = R.anim.rotation_animation_enter;
3258 case ROTATION_ANIMATION_JUMPCUT:
3259 anim[0] = R.anim.rotation_animation_jump_exit;
3260 anim[1] = R.anim.rotation_animation_enter;
3262 case ROTATION_ANIMATION_ROTATE:
3264 anim[0] = anim[1] = 0;
3268 anim[0] = anim[1] = 0;
3273 public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId,
3274 boolean forceDefault) {
3275 switch (exitAnimId) {
3276 case R.anim.rotation_animation_xfade_exit:
3277 case R.anim.rotation_animation_jump_exit:
3278 // These are the only cases that matter.
3282 int anim[] = new int[2];
3283 selectRotationAnimationLw(anim);
3284 return (exitAnimId == anim[0] && enterAnimId == anim[1]);
3291 public Animation createForceHideEnterAnimation(boolean onWallpaper,
3292 boolean goingToNotificationShade) {
3293 if (goingToNotificationShade) {
3294 return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
3297 AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ?
3298 R.anim.lock_screen_behind_enter_wallpaper :
3299 R.anim.lock_screen_behind_enter);
3301 // TODO: Use XML interpolators when we have log interpolators available in XML.
3302 final List<Animation> animations = set.getAnimations();
3303 for (int i = animations.size() - 1; i >= 0; --i) {
3304 animations.get(i).setInterpolator(mLogDecelerateInterpolator);
3312 public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade) {
3313 if (goingToNotificationShade) {
3316 return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
3320 private static void awakenDreams() {
3321 IDreamManager dreamManager = getDreamManager();
3322 if (dreamManager != null) {
3324 dreamManager.awaken();
3325 } catch (RemoteException e) {
3326 // fine, stay asleep then
3331 static IDreamManager getDreamManager() {
3332 return IDreamManager.Stub.asInterface(
3333 ServiceManager.checkService(DreamService.DREAM_SERVICE));
3336 TelecomManager getTelecommService() {
3337 return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
3340 static IAudioService getAudioService() {
3341 IAudioService audioService = IAudioService.Stub.asInterface(
3342 ServiceManager.checkService(Context.AUDIO_SERVICE));
3343 if (audioService == null) {
3344 Log.w(TAG, "Unable to find IAudioService interface.");
3346 return audioService;
3349 boolean keyguardOn() {
3350 return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode();
3353 private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
3354 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
3355 WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
3358 /** {@inheritDoc} */
3360 public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
3361 final boolean keyguardOn = keyguardOn();
3362 final int repeatCount = event.getRepeatCount();
3363 final int metaState = event.getMetaState();
3364 final int flags = event.getFlags();
3365 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
3366 final boolean canceled = event.isCanceled();
3367 final boolean longPress = (flags & KeyEvent.FLAG_LONG_PRESS) != 0;
3368 final boolean virtualKey = event.getDeviceId() == KeyCharacterMap.VIRTUAL_KEYBOARD;
3369 final int keyCode = event.getKeyCode();
3372 Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
3373 + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
3374 + " canceled=" + canceled);
3377 // If the boot mode is power off alarm, we should not dispatch the several physical keys
3378 // in power off alarm UI to avoid pausing power off alarm UI.
3379 boolean isAlarmBoot = SystemProperties.getBoolean("ro.alarm_boot", false);
3380 if (isAlarmBoot && (keyCode == KeyEvent.KEYCODE_HOME
3381 || keyCode == KeyEvent.KEYCODE_SEARCH
3382 || keyCode == KeyEvent.KEYCODE_MENU
3383 || keyCode == KeyEvent.KEYCODE_APP_SWITCH
3384 || keyCode == KeyEvent.KEYCODE_BACK)) {
3388 // If we think we might have a volume down & power key chord on the way
3389 // but we're not sure, then tell the dispatcher to wait a little while and
3390 // try again later before dispatching.
3391 if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
3392 if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
3393 final long now = SystemClock.uptimeMillis();
3394 final long timeoutTime = mScreenshotChordVolumeDownKeyTime
3395 + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
3396 if (now < timeoutTime) {
3397 return timeoutTime - now;
3400 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3401 && mScreenshotChordVolumeDownKeyConsumed) {
3403 mScreenshotChordVolumeDownKeyConsumed = false;
3409 // Cancel any pending meta actions if we see any other keys being pressed between the down
3410 // of the meta key and its corresponding up.
3411 if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
3412 mPendingMetaAction = false;
3414 // Any key that is not Alt or Meta cancels Caps Lock combo tracking.
3415 if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) {
3416 mPendingCapsLockToggle = false;
3419 if (keyCode == KeyEvent.KEYCODE_BACK && !down) {
3420 mHandler.removeCallbacks(mBackLongPress);
3423 // First we always handle the home key here, so applications
3424 // can never break it, although if keyguard is on, we do let
3425 // it handle it, because that gives us the correct 5 second
3427 if (keyCode == KeyEvent.KEYCODE_HOME) {
3429 // If we have released the home key, and didn't do anything else
3430 // while it was pressed, then it is time to go home!
3432 if (mDoubleTapOnHomeBehavior != KEY_ACTION_APP_SWITCH) {
3433 cancelPreloadRecentApps();
3436 mHomePressed = false;
3437 if (mHomeConsumed) {
3438 mHomeConsumed = false;
3443 Log.i(TAG, "Ignoring HOME; event canceled.");
3447 // If an incoming call is ringing, HOME is totally disabled.
3448 // (The user is already on the InCallUI at this point,
3449 // and his ONLY options are to answer or reject the call.)
3450 TelecomManager telecomManager = getTelecommService();
3451 if (telecomManager != null && telecomManager.isRinging()) {
3452 Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
3456 // Delay handling home if a double-tap is possible.
3457 if (mDoubleTapOnHomeBehavior != KEY_ACTION_NOTHING) {
3458 mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
3459 mHomeDoubleTapPending = true;
3460 mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
3461 ViewConfiguration.getDoubleTapTimeout());
3465 handleShortPressOnHome();
3469 // If a system window has focus, then it doesn't make sense
3470 // right now to interact with applications.
3471 WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
3472 if (attrs != null) {
3473 final int type = attrs.type;
3474 if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM
3475 || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
3476 || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
3477 // the "app" is keyguard, so give it the key
3480 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
3481 for (int i=0; i<typeCount; i++) {
3482 if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
3483 // don't do anything, but also don't pass it to the app
3489 // Remember that home is pressed and handle special actions.
3490 if (repeatCount == 0) {
3491 mHomePressed = true;
3492 if (mHomeDoubleTapPending) {
3493 mHomeDoubleTapPending = false;
3494 mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
3495 performKeyAction(mDoubleTapOnHomeBehavior, event);
3496 mHomeConsumed = true;
3497 } else if (mLongPressOnHomeBehavior == KEY_ACTION_APP_SWITCH
3498 || mDoubleTapOnHomeBehavior == KEY_ACTION_APP_SWITCH) {
3499 preloadRecentApps();
3501 } else if (longPress) {
3502 if (!keyguardOn && !mHomeConsumed &&
3503 mLongPressOnHomeBehavior != KEY_ACTION_NOTHING) {
3504 if (mLongPressOnHomeBehavior != KEY_ACTION_APP_SWITCH) {
3505 cancelPreloadRecentApps();
3507 mHomePressed = true;
3508 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
3509 performKeyAction(mLongPressOnHomeBehavior, event);
3510 mHomeConsumed = true;
3514 } else if (keyCode == KeyEvent.KEYCODE_MENU) {
3515 // Hijack modified menu keys for debugging features
3516 final int chordBug = KeyEvent.META_SHIFT_ON;
3517 if (virtualKey || keyguardOn) {
3518 // Let the app handle the key
3523 if (mPressOnMenuBehavior == KEY_ACTION_APP_SWITCH
3524 || mLongPressOnMenuBehavior == KEY_ACTION_APP_SWITCH) {
3525 preloadRecentApps();
3527 if (repeatCount == 0) {
3528 mMenuPressed = true;
3529 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
3530 Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
3531 mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
3532 null, null, null, 0, null, null);
3534 } else if (SHOW_PROCESSES_ON_ALT_MENU &&
3535 (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
3536 Intent service = new Intent();
3537 service.setClassName(mContext, "com.android.server.LoadAverageService");
3538 ContentResolver res = mContext.getContentResolver();
3539 boolean shown = Settings.Global.getInt(
3540 res, Settings.Global.SHOW_PROCESSES, 0) != 0;
3542 mContext.startService(service);
3544 mContext.stopService(service);
3546 Settings.Global.putInt(
3547 res, Settings.Global.SHOW_PROCESSES, shown ? 0 : 1);
3550 } else if (longPress) {
3551 if (!keyguardOn && mLongPressOnMenuBehavior != KEY_ACTION_NOTHING) {
3552 if (mLongPressOnMenuBehavior != KEY_ACTION_APP_SWITCH) {
3553 cancelPreloadRecentApps();
3555 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
3556 performKeyAction(mLongPressOnMenuBehavior, event);
3557 mMenuPressed = false;
3562 if (!down && mMenuPressed) {
3563 if (mPressOnMenuBehavior != KEY_ACTION_APP_SWITCH) {
3564 cancelPreloadRecentApps();
3566 mMenuPressed = false;
3568 performKeyAction(mPressOnMenuBehavior, event);
3572 } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
3574 if (repeatCount == 0) {
3575 mSearchKeyShortcutPending = true;
3576 mConsumeSearchKeyUp = false;
3579 mSearchKeyShortcutPending = false;
3580 if (mConsumeSearchKeyUp) {
3581 mConsumeSearchKeyUp = false;
3586 } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
3588 if (mPressOnAppSwitchBehavior == KEY_ACTION_APP_SWITCH
3589 || mLongPressOnAppSwitchBehavior == KEY_ACTION_APP_SWITCH) {
3590 preloadRecentApps();
3592 if (repeatCount == 0) {
3593 mAppSwitchLongPressed = false;
3594 } else if (longPress) {
3595 if (!keyguardOn && mLongPressOnAppSwitchBehavior != KEY_ACTION_NOTHING) {
3596 if (mLongPressOnAppSwitchBehavior != KEY_ACTION_APP_SWITCH) {
3597 cancelPreloadRecentApps();
3599 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
3600 performKeyAction(mLongPressOnAppSwitchBehavior, event);
3601 mAppSwitchLongPressed = true;
3605 if (mAppSwitchLongPressed) {
3606 mAppSwitchLongPressed = false;
3608 if (mPressOnAppSwitchBehavior != KEY_ACTION_APP_SWITCH) {
3609 cancelPreloadRecentApps();
3612 performKeyAction(mPressOnAppSwitchBehavior, event);
3617 } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) {
3619 IStatusBarService service = getStatusBarService();
3620 if (service != null) {
3622 service.expandNotificationsPanel();
3623 } catch (RemoteException e) {
3628 } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed()
3629 && event.isCtrlPressed()) {
3630 if (down && repeatCount == 0) {
3631 int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION
3632 : TAKE_SCREENSHOT_FULLSCREEN;
3633 mScreenshotRunnable.setScreenshotType(type);
3634 mHandler.post(mScreenshotRunnable);
3637 } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
3638 if (down && repeatCount == 0 && !isKeyguardLocked()) {
3639 toggleKeyboardShortcutsMenu(event.getDeviceId());
3641 } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
3643 if (mPressOnAssistBehavior == KEY_ACTION_APP_SWITCH
3644 || mLongPressOnAssistBehavior == KEY_ACTION_APP_SWITCH) {
3645 preloadRecentApps();
3647 if (repeatCount == 0) {
3648 mAssistKeyLongPressed = false;
3649 } else if (longPress) {
3650 if (!keyguardOn && mLongPressOnAssistBehavior != KEY_ACTION_NOTHING) {
3651 if (mLongPressOnAssistBehavior != KEY_ACTION_APP_SWITCH) {
3652 cancelPreloadRecentApps();
3654 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
3655 performKeyAction(mLongPressOnAssistBehavior, event);
3656 mAssistKeyLongPressed = true;
3660 if (mAssistKeyLongPressed) {
3661 mAssistKeyLongPressed = false;
3663 if (mPressOnAssistBehavior != KEY_ACTION_APP_SWITCH) {
3664 cancelPreloadRecentApps();
3667 performKeyAction(mPressOnAssistBehavior, event);
3672 } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
3676 voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
3678 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
3679 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
3682 dic.exitIdle("voice-search");
3683 } catch (RemoteException e) {
3686 voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
3687 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
3689 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
3691 } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
3692 if (down && repeatCount == 0) {
3693 mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
3694 mHandler.post(mScreenshotRunnable);
3697 } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP
3698 || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) {
3700 int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
3702 // Disable autobrightness if it's on
3703 int auto = Settings.System.getIntForUser(
3704 mContext.getContentResolver(),
3705 Settings.System.SCREEN_BRIGHTNESS_MODE,
3706 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3707 UserHandle.USER_CURRENT_OR_SELF);
3709 Settings.System.putIntForUser(mContext.getContentResolver(),
3710 Settings.System.SCREEN_BRIGHTNESS_MODE,
3711 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3712 UserHandle.USER_CURRENT_OR_SELF);
3715 int min = mPowerManager.getMinimumScreenBrightnessSetting();
3716 int max = mPowerManager.getMaximumScreenBrightnessSetting();
3717 int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction;
3718 int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
3719 Settings.System.SCREEN_BRIGHTNESS,
3720 mPowerManager.getDefaultScreenBrightnessSetting(),
3721 UserHandle.USER_CURRENT_OR_SELF);
3723 // Make sure we don't go beyond the limits.
3724 brightness = Math.min(max, brightness);
3725 brightness = Math.max(min, brightness);
3727 Settings.System.putIntForUser(mContext.getContentResolver(),
3728 Settings.System.SCREEN_BRIGHTNESS, brightness,
3729 UserHandle.USER_CURRENT_OR_SELF);
3730 startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
3731 UserHandle.CURRENT_OR_SELF);
3734 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
3735 || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3736 || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
3737 if (mUseTvRouting) {
3738 // On TVs volume keys never go to the foreground app.
3739 dispatchDirectAudioEvent(event);
3744 // Toggle Caps Lock on META-ALT.
3745 boolean actionTriggered = false;
3746 if (KeyEvent.isModifierKey(keyCode)) {
3747 if (!mPendingCapsLockToggle) {
3748 // Start tracking meta state for combo.
3749 mInitialMetaState = mMetaState;
3750 mPendingCapsLockToggle = true;
3751 } else if (event.getAction() == KeyEvent.ACTION_UP) {
3752 int altOnMask = mMetaState & KeyEvent.META_ALT_MASK;
3753 int metaOnMask = mMetaState & KeyEvent.META_META_MASK;
3755 // Check for Caps Lock toggle
3756 if ((metaOnMask != 0) && (altOnMask != 0)) {
3757 // Check if nothing else is pressed
3758 if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) {
3759 // Handle Caps Lock Toggle
3760 mInputManagerInternal.toggleCapsLock(event.getDeviceId());
3761 actionTriggered = true;
3765 // Always stop tracking when key goes up.
3766 mPendingCapsLockToggle = false;
3769 // Store current meta state to be able to evaluate it later.
3770 mMetaState = metaState;
3772 if (actionTriggered) {
3776 if (KeyEvent.isMetaKey(keyCode)) {
3778 mPendingMetaAction = true;
3779 } else if (mPendingMetaAction) {
3780 launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId());
3783 } else if (keyCode == KeyEvent.KEYCODE_BACK) {
3784 if (unpinActivity(true) || CMSettings.Secure.getInt(mContext.getContentResolver(),
3785 CMSettings.Secure.KILL_APP_LONGPRESS_BACK, 0) == 1) {
3786 if (down && repeatCount == 0) {
3787 mHandler.postDelayed(mBackLongPress, mBackKillTimeout);
3792 // Shortcuts are invoked through Search+key, so intercept those here
3793 // Any printing key that is chorded with Search should be consumed
3794 // even if no shortcut was invoked. This prevents text from being
3795 // inadvertently inserted when using a keyboard that has built-in macro
3796 // shortcut keys (that emit Search+x) and some of them are not registered.
3797 if (mSearchKeyShortcutPending) {
3798 final KeyCharacterMap kcm = event.getKeyCharacterMap();
3799 if (kcm.isPrintingKey(keyCode)) {
3800 mConsumeSearchKeyUp = true;
3801 mSearchKeyShortcutPending = false;
3802 if (down && repeatCount == 0 && !keyguardOn) {
3803 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
3804 if (shortcutIntent != null) {
3805 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3807 startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3808 dismissKeyboardShortcutsMenu();
3809 } catch (ActivityNotFoundException ex) {
3810 Slog.w(TAG, "Dropping shortcut key combination because "
3811 + "the activity to which it is registered was not found: "
3812 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);
3815 Slog.i(TAG, "Dropping unregistered shortcut key combination: "
3816 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));
3823 // Invoke shortcuts using Meta.
3824 if (down && repeatCount == 0 && !keyguardOn
3825 && (metaState & KeyEvent.META_META_ON) != 0) {
3826 final KeyCharacterMap kcm = event.getKeyCharacterMap();
3827 if (kcm.isPrintingKey(keyCode)) {
3828 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
3829 metaState & ~(KeyEvent.META_META_ON
3830 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
3831 if (shortcutIntent != null) {
3832 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3834 startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3835 dismissKeyboardShortcutsMenu();
3836 } catch (ActivityNotFoundException ex) {
3837 Slog.w(TAG, "Dropping shortcut key combination because "
3838 + "the activity to which it is registered was not found: "
3839 + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
3846 // Handle application launch keys.
3847 if (down && repeatCount == 0 && !keyguardOn) {
3848 String category = sApplicationLaunchKeyCategories.get(keyCode);
3849 if (category != null) {
3850 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
3851 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3853 startActivityAsUser(intent, UserHandle.CURRENT);
3854 dismissKeyboardShortcutsMenu();
3855 } catch (ActivityNotFoundException ex) {
3856 Slog.w(TAG, "Dropping application launch key because "
3857 + "the activity to which it is registered was not found: "
3858 + "keyCode=" + keyCode + ", category=" + category, ex);
3864 // Display task switcher for ALT-TAB.
3865 if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
3866 if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
3867 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
3868 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
3869 mRecentAppsHeldModifiers = shiftlessModifiers;
3870 showRecentApps(true, false);
3874 } else if (!down && mRecentAppsHeldModifiers != 0
3875 && (metaState & mRecentAppsHeldModifiers) == 0) {
3876 mRecentAppsHeldModifiers = 0;
3877 hideRecentApps(true, false);
3880 // Handle input method switching.
3881 if (down && repeatCount == 0
3882 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3883 || (keyCode == KeyEvent.KEYCODE_SPACE
3884 && (metaState & KeyEvent.META_META_MASK) != 0))) {
3885 final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0;
3886 mWindowManagerFuncs.switchInputMethod(forwardDirection);
3889 if (mLanguageSwitchKeyPressed && !down
3890 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3891 || keyCode == KeyEvent.KEYCODE_SPACE)) {
3892 mLanguageSwitchKeyPressed = false;
3896 if (isValidGlobalKey(keyCode)
3897 && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
3901 // Specific device key handling
3902 if (mDeviceKeyHandler != null) {
3904 // The device only should consume known keys.
3905 if (mDeviceKeyHandler.handleKeyEvent(event)) {
3908 } catch (Exception e) {
3909 Slog.w(TAG, "Could not dispatch event to device key handler", e);
3914 long shortcutCode = keyCode;
3915 if (event.isCtrlPressed()) {
3916 shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
3919 if (event.isAltPressed()) {
3920 shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
3923 if (event.isShiftPressed()) {
3924 shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
3927 if (event.isMetaPressed()) {
3928 shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE;
3931 IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode);
3932 if (shortcutService != null) {
3934 if (isUserSetupComplete()) {
3935 shortcutService.notifyShortcutKeyPressed(shortcutCode);
3937 } catch (RemoteException e) {
3938 mShortcutKeyServices.delete(shortcutCode);
3944 // Reserve all the META modifier combos for system behavior
3945 if ((metaState & KeyEvent.META_META_ON) != 0) {
3949 // Let the application handle the key.
3953 private boolean unpinActivity(boolean checkOnly) {
3954 if (!hasNavigationBar()) {
3956 if (ActivityManagerNative.getDefault().isInLockTaskMode()) {
3958 ActivityManagerNative.getDefault().stopSystemLockTaskMode();
3962 } catch (RemoteException e) {
3969 /** {@inheritDoc} */
3971 public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
3972 // Note: This method is only called if the initial down was unhandled.
3974 Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
3975 + ", flags=" + event.getFlags()
3976 + ", keyCode=" + event.getKeyCode()
3977 + ", scanCode=" + event.getScanCode()
3978 + ", metaState=" + event.getMetaState()
3979 + ", repeatCount=" + event.getRepeatCount()
3980 + ", policyFlags=" + policyFlags);
3983 KeyEvent fallbackEvent = null;
3984 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3985 final KeyCharacterMap kcm = event.getKeyCharacterMap();
3986 final int keyCode = event.getKeyCode();
3987 final int metaState = event.getMetaState();
3988 final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
3989 && event.getRepeatCount() == 0;
3991 // Check for fallback actions specified by the key character map.
3992 final FallbackAction fallbackAction;
3994 fallbackAction = kcm.getFallbackAction(keyCode, metaState);
3996 fallbackAction = mFallbackActions.get(keyCode);
3999 if (fallbackAction != null) {
4001 Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode
4002 + " metaState=" + Integer.toHexString(fallbackAction.metaState));
4005 final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
4006 fallbackEvent = KeyEvent.obtain(
4007 event.getDownTime(), event.getEventTime(),
4008 event.getAction(), fallbackAction.keyCode,
4009 event.getRepeatCount(), fallbackAction.metaState,
4010 event.getDeviceId(), event.getScanCode(),
4011 flags, event.getSource(), null);
4013 if (!interceptFallback(win, fallbackEvent, policyFlags)) {
4014 fallbackEvent.recycle();
4015 fallbackEvent = null;
4019 mFallbackActions.put(keyCode, fallbackAction);
4020 } else if (event.getAction() == KeyEvent.ACTION_UP) {
4021 mFallbackActions.remove(keyCode);
4022 fallbackAction.recycle();
4028 if (fallbackEvent == null) {
4029 Slog.d(TAG, "No fallback.");
4031 Slog.d(TAG, "Performing fallback: " + fallbackEvent);
4034 return fallbackEvent;
4037 private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
4038 int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
4039 if ((actions & ACTION_PASS_TO_USER) != 0) {
4040 long delayMillis = interceptKeyBeforeDispatching(
4041 win, fallbackEvent, policyFlags);
4042 if (delayMillis == 0) {
4050 public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
4051 throws RemoteException {
4052 synchronized (mLock) {
4053 IShortcutService service = mShortcutKeyServices.get(shortcutCode);
4054 if (service != null && service.asBinder().pingBinder()) {
4055 throw new RemoteException("Key already exists.");
4058 mShortcutKeyServices.put(shortcutCode, shortcutService);
4062 private void launchAssistLongPressAction() {
4063 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
4064 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
4066 // launch the search activity
4067 Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
4068 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
4070 // TODO: This only stops the factory-installed search manager.
4071 // Need to formalize an API to handle others
4072 SearchManager searchManager = getSearchManager();
4073 if (searchManager != null) {
4074 searchManager.stopSearch();
4076 startActivityAsUser(intent, UserHandle.CURRENT);
4077 } catch (ActivityNotFoundException e) {
4078 Slog.w(TAG, "No activity to handle assist long press action.", e);
4082 private void launchAssistAction(String hint, int deviceId) {
4083 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
4084 if (!isUserSetupComplete()) {
4085 // Disable opening assist window during setup
4089 if (deviceId > Integer.MIN_VALUE) {
4090 args = new Bundle();
4091 args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
4093 if ((mContext.getResources().getConfiguration().uiMode
4094 & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
4095 // On TV, use legacy handling until assistants are implemented in the proper way.
4096 ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
4097 .launchLegacyAssist(hint, UserHandle.myUserId(), args);
4101 args = new Bundle();
4103 args.putBoolean(hint, true);
4105 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4106 if (statusbar != null) {
4107 statusbar.startAssist(args);
4112 private void startActivityAsUser(Intent intent, UserHandle handle) {
4113 if (isUserSetupComplete()) {
4114 mContext.startActivityAsUser(intent, handle);
4116 Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent);
4120 private SearchManager getSearchManager() {
4121 if (mSearchManager == null) {
4122 mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
4124 return mSearchManager;
4127 private void preloadRecentApps() {
4128 mPreloadedRecentApps = true;
4129 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4130 if (statusbar != null) {
4131 statusbar.preloadRecentApps();
4135 private void cancelPreloadRecentApps() {
4136 if (mPreloadedRecentApps) {
4137 mPreloadedRecentApps = false;
4138 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4139 if (statusbar != null) {
4140 statusbar.cancelPreloadRecentApps();
4145 private void toggleRecentApps() {
4146 mPreloadedRecentApps = false; // preloading no longer needs to be canceled
4147 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4148 if (statusbar != null) {
4149 statusbar.toggleRecentApps();
4154 public void showRecentApps(boolean fromHome) {
4155 mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
4156 mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget();
4159 private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
4160 mPreloadedRecentApps = false; // preloading no longer needs to be canceled
4161 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4162 if (statusbar != null) {
4163 statusbar.showRecentApps(triggeredFromAltTab, fromHome);
4167 private void toggleKeyboardShortcutsMenu(int deviceId) {
4168 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4169 if (statusbar != null) {
4170 statusbar.toggleKeyboardShortcutsMenu(deviceId);
4174 private void dismissKeyboardShortcutsMenu() {
4175 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4176 if (statusbar != null) {
4177 statusbar.dismissKeyboardShortcutsMenu();
4181 private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
4182 mPreloadedRecentApps = false; // preloading no longer needs to be canceled
4183 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4184 if (statusbar != null) {
4185 statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
4189 void launchHomeFromHotKey() {
4190 launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/);
4194 * A home key -> launch home action was detected. Take the appropriate action
4195 * given the situation with the keyguard.
4197 void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) {
4198 if (respectKeyguard) {
4199 if (isKeyguardShowingAndNotOccluded()) {
4200 // don't launch home if keyguard showing
4204 if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) {
4205 // when in keyguard restricted mode, must first verify unlock
4206 // before launching home
4207 mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
4209 public void onKeyguardExitResult(boolean success) {
4212 ActivityManagerNative.getDefault().stopAppSwitches();
4213 } catch (RemoteException e) {
4215 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
4216 startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
4224 // no keyguard stuff to worry about, just launch home!
4226 ActivityManagerNative.getDefault().stopAppSwitches();
4227 } catch (RemoteException e) {
4229 if (mRecentsVisible) {
4230 // Hide Recents and notify it to launch Home
4231 if (awakenFromDreams) {
4234 hideRecentApps(false, true);
4235 } else if (mScreenOnFully) {
4236 // check if screen is fully on before going home
4237 // to avoid hardware home button wake going home
4238 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
4239 startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
4243 private final Runnable mClearHideNavigationFlag = new Runnable() {
4246 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
4248 mForceClearedSystemUiFlags &=
4249 ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
4251 mWindowManagerFuncs.reevaluateStatusBarVisibility();
4256 * Input handler used while nav bar is hidden. Captures any touch on the screen,
4257 * to determine when the nav bar should be shown and prevent applications from
4258 * receiving those touches.
4260 final class HideNavInputEventReceiver extends InputEventReceiver {
4261 public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
4262 super(inputChannel, looper);
4266 public void onInputEvent(InputEvent event) {
4267 boolean handled = false;
4269 if (event instanceof MotionEvent
4270 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
4271 final MotionEvent motionEvent = (MotionEvent)event;
4272 if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
4273 // When the user taps down, we re-show the nav bar.
4274 boolean changed = false;
4275 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
4276 if (mInputConsumer == null) {
4279 // Any user activity always causes us to show the
4280 // navigation controls, if they had been hidden.
4281 // We also clear the low profile and only content
4282 // flags so that tapping on the screen will atomically
4283 // restore all currently hidden screen decorations.
4284 int newVal = mResettingSystemUiFlags |
4285 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
4286 View.SYSTEM_UI_FLAG_LOW_PROFILE |
4287 View.SYSTEM_UI_FLAG_FULLSCREEN;
4288 if (mResettingSystemUiFlags != newVal) {
4289 mResettingSystemUiFlags = newVal;
4292 // We don't allow the system's nav bar to be hidden
4293 // again for 1 second, to prevent applications from
4294 // spamming us and keeping it from being shown.
4295 newVal = mForceClearedSystemUiFlags |
4296 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
4297 if (mForceClearedSystemUiFlags != newVal) {
4298 mForceClearedSystemUiFlags = newVal;
4300 mHandler.postDelayed(mClearHideNavigationFlag, 1000);
4304 mWindowManagerFuncs.reevaluateStatusBarVisibility();
4309 finishInputEvent(event, handled);
4313 final InputEventReceiver.Factory mHideNavInputEventReceiverFactory =
4314 new InputEventReceiver.Factory() {
4316 public InputEventReceiver createInputEventReceiver(
4317 InputChannel inputChannel, Looper looper) {
4318 return new HideNavInputEventReceiver(inputChannel, looper);
4323 public int adjustSystemUiVisibilityLw(int visibility) {
4324 mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4325 mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4326 mRecentsVisible = (visibility & View.RECENT_APPS_VISIBLE) > 0;
4327 mTvPictureInPictureVisible = (visibility & View.TV_PICTURE_IN_PICTURE_VISIBLE) > 0;
4329 // Reset any bits in mForceClearingStatusBarVisibility that
4331 mResettingSystemUiFlags &= visibility;
4332 // Clear any bits in the new visibility that are currently being
4333 // force cleared, before reporting it.
4334 return visibility & ~mResettingSystemUiFlags
4335 & ~mForceClearedSystemUiFlags;
4339 public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
4340 int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets,
4341 Rect outStableInsets, Rect outOutsets) {
4342 final int fl = PolicyControl.getWindowFlags(null, attrs);
4343 final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
4344 final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
4346 final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
4348 int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
4350 if (displayRotation == Surface.ROTATION_0) {
4351 outOutsets.bottom += outset;
4352 } else if (displayRotation == Surface.ROTATION_90) {
4353 outOutsets.right += outset;
4354 } else if (displayRotation == Surface.ROTATION_180) {
4355 outOutsets.top += outset;
4356 } else if (displayRotation == Surface.ROTATION_270) {
4357 outOutsets.left += outset;
4362 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4363 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4364 int availRight, availBottom;
4365 if (canHideNavigationBar() &&
4366 (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
4367 availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4368 availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4370 availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
4371 availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4373 if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4374 if ((fl & FLAG_FULLSCREEN) != 0) {
4375 outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop,
4376 availRight - mStableFullscreenRight,
4377 availBottom - mStableFullscreenBottom);
4379 outContentInsets.set(mStableLeft, mStableTop,
4380 availRight - mStableRight, availBottom - mStableBottom);
4382 } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
4383 outContentInsets.setEmpty();
4384 } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
4385 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
4386 outContentInsets.set(mCurLeft, mCurTop,
4387 availRight - mCurRight, availBottom - mCurBottom);
4389 outContentInsets.set(mCurLeft, mCurTop,
4390 availRight - mCurRight, availBottom - mCurBottom);
4393 outStableInsets.set(mStableLeft, mStableTop,
4394 availRight - mStableRight, availBottom - mStableBottom);
4395 if (taskBounds != null) {
4396 calculateRelevantTaskInsets(taskBounds, outContentInsets,
4397 displayWidth, displayHeight);
4398 calculateRelevantTaskInsets(taskBounds, outStableInsets,
4399 displayWidth, displayHeight);
4401 return mForceShowSystemBars;
4403 outContentInsets.setEmpty();
4404 outStableInsets.setEmpty();
4405 return mForceShowSystemBars;
4409 * For any given task bounds, the insets relevant for these bounds given the insets relevant
4410 * for the entire display.
4412 private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth,
4413 int displayHeight) {
4414 mTmpRect.set(0, 0, displayWidth, displayHeight);
4415 mTmpRect.inset(inOutInsets);
4416 mTmpRect.intersect(taskBounds);
4417 int leftInset = mTmpRect.left - taskBounds.left;
4418 int topInset = mTmpRect.top - taskBounds.top;
4419 int rightInset = taskBounds.right - mTmpRect.right;
4420 int bottomInset = taskBounds.bottom - mTmpRect.bottom;
4421 inOutInsets.set(leftInset, topInset, rightInset, bottomInset);
4424 private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
4425 return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
4426 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
4429 /** {@inheritDoc} */
4431 public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
4432 int displayRotation, int uiMode) {
4433 mDisplayRotation = displayRotation;
4434 final int overscanLeft, overscanTop, overscanRight, overscanBottom;
4435 if (isDefaultDisplay) {
4436 switch (displayRotation) {
4437 case Surface.ROTATION_90:
4438 overscanLeft = mOverscanTop;
4439 overscanTop = mOverscanRight;
4440 overscanRight = mOverscanBottom;
4441 overscanBottom = mOverscanLeft;
4443 case Surface.ROTATION_180:
4444 overscanLeft = mOverscanRight;
4445 overscanTop = mOverscanBottom;
4446 overscanRight = mOverscanLeft;
4447 overscanBottom = mOverscanTop;
4449 case Surface.ROTATION_270:
4450 overscanLeft = mOverscanBottom;
4451 overscanTop = mOverscanLeft;
4452 overscanRight = mOverscanTop;
4453 overscanBottom = mOverscanRight;
4456 overscanLeft = mOverscanLeft;
4457 overscanTop = mOverscanTop;
4458 overscanRight = mOverscanRight;
4459 overscanBottom = mOverscanBottom;
4468 mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0;
4469 mOverscanScreenTop = mRestrictedOverscanScreenTop = 0;
4470 mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth;
4471 mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight;
4474 mSystemRight = displayWidth;
4475 mSystemBottom = displayHeight;
4476 mUnrestrictedScreenLeft = overscanLeft;
4477 mUnrestrictedScreenTop = overscanTop;
4478 mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight;
4479 mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom;
4480 mRestrictedScreenLeft = mUnrestrictedScreenLeft;
4481 mRestrictedScreenTop = mUnrestrictedScreenTop;
4482 mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth;
4483 mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight;
4484 mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft
4485 = mCurLeft = mUnrestrictedScreenLeft;
4486 mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop
4487 = mCurTop = mUnrestrictedScreenTop;
4488 mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight
4489 = mCurRight = displayWidth - overscanRight;
4490 mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom
4491 = mCurBottom = displayHeight - overscanBottom;
4492 mDockLayer = 0x10000000;
4493 mStatusBarLayer = -1;
4495 // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
4496 final Rect pf = mTmpParentFrame;
4497 final Rect df = mTmpDisplayFrame;
4498 final Rect of = mTmpOverscanFrame;
4499 final Rect vf = mTmpVisibleFrame;
4500 final Rect dcf = mTmpDecorFrame;
4501 pf.left = df.left = of.left = vf.left = mDockLeft;
4502 pf.top = df.top = of.top = vf.top = mDockTop;
4503 pf.right = df.right = of.right = vf.right = mDockRight;
4504 pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom;
4505 dcf.setEmpty(); // Decor frame N/A for system bars.
4507 if (isDefaultDisplay) {
4508 // For purposes of putting out fake window up to steal focus, we will
4509 // drive nav being hidden only by whether it is requested.
4510 final int sysui = mLastSystemUiFlags;
4511 boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
4512 boolean navTranslucent = (sysui
4513 & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
4514 boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
4515 boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
4516 boolean navAllowedHidden = immersive || immersiveSticky;
4517 navTranslucent &= !immersiveSticky; // transient trumps translucent
4518 boolean isKeyguardShowing = isStatusBarKeyguard() && !mHideLockScreen;
4519 if (!isKeyguardShowing) {
4520 navTranslucent &= areTranslucentBarsAllowed();
4522 boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null
4523 && mStatusBar.getAttrs().height == MATCH_PARENT
4524 && mStatusBar.getAttrs().width == MATCH_PARENT;
4526 // When the navigation bar isn't visible, we put up a fake
4527 // input window to catch all touch events. This way we can
4528 // detect when the user presses anywhere to bring back the nav
4529 // bar and ensure the application doesn't see the event.
4530 if (navVisible || navAllowedHidden) {
4531 if (mInputConsumer != null) {
4532 mHandler.sendMessage(
4533 mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
4534 mInputConsumer = null;
4536 } else if (mInputConsumer == null) {
4537 mInputConsumer = mWindowManagerFuncs.addInputConsumer(mHandler.getLooper(),
4538 mHideNavInputEventReceiverFactory);
4541 // For purposes of positioning and showing the nav bar, if we have
4542 // decided that it can't be hidden (because of the screen aspect ratio),
4543 // then take that into account.
4544 navVisible |= !canHideNavigationBar();
4546 boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight,
4547 displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom,
4548 dcf, navVisible, navTranslucent, navAllowedHidden, statusBarExpandedNotKeyguard);
4549 if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
4550 mDockLeft, mDockTop, mDockRight, mDockBottom));
4551 updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing);
4552 if (updateSysUiVisibility) {
4553 updateSystemUiVisibilityLw();
4558 private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui,
4559 boolean isKeyguardShowing) {
4560 // decide where the status bar goes ahead of time
4561 if (mStatusBar != null) {
4562 // apply any navigation bar insets
4563 pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4564 pf.top = df.top = of.top = mUnrestrictedScreenTop;
4565 pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4566 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
4567 + mUnrestrictedScreenTop;
4568 vf.left = mStableLeft;
4569 vf.top = mStableTop;
4570 vf.right = mStableRight;
4571 vf.bottom = mStableBottom;
4573 mStatusBarLayer = mStatusBar.getSurfaceLayer();
4575 // Let the status bar determine its size.
4576 mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
4577 vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
4578 dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */);
4580 // For layout, the status bar is always at the top with our fixed height.
4581 mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
4583 boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
4584 boolean statusBarTranslucent = (sysui
4585 & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
4586 if (!isKeyguardShowing) {
4587 statusBarTranslucent &= areTranslucentBarsAllowed();
4590 // If the status bar is hidden, we don't want to cause
4591 // windows behind it to scroll.
4592 if (mStatusBar.isVisibleLw() && !statusBarTransient) {
4593 // Status bar may go away, so the screen area it occupies
4594 // is available to apps but just covering them when the
4595 // status bar is visible.
4596 mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
4598 mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4599 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4600 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4601 mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4603 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " +
4605 "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
4606 mDockLeft, mDockTop, mDockRight, mDockBottom,
4607 mContentLeft, mContentTop, mContentRight, mContentBottom,
4608 mCurLeft, mCurTop, mCurRight, mCurBottom));
4610 if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
4611 && !statusBarTransient && !statusBarTranslucent
4612 && !mStatusBarController.wasRecentlyTranslucent()) {
4613 // If the opaque status bar is currently requested to be visible,
4614 // and not in the process of animating on or off, then
4615 // we can tell the app that it is covered by it.
4616 mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
4618 if (mStatusBarController.checkHiddenLw()) {
4625 private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation,
4626 int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf,
4627 boolean navVisible, boolean navTranslucent, boolean navAllowedHidden,
4628 boolean statusBarExpandedNotKeyguard) {
4629 if (mNavigationBar != null) {
4630 boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
4631 // Force the navigation bar to its appropriate place and
4632 // size. We need to do this directly, instead of relying on
4633 // it to bubble up from the nav bar, because this needs to
4634 // change atomically with screen rotations.
4635 mNavigationBarOnBottom = isNavigationBarOnBottom(displayWidth, displayHeight);
4636 if (mNavigationBarOnBottom) {
4637 // It's a system nav bar or a portrait screen; nav bar goes on bottom.
4638 int top = displayHeight - overscanBottom
4639 - getNavigationBarHeight(displayRotation, uiMode);
4640 mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
4641 mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
4642 if (transientNavBarShowing) {
4643 mNavigationBarController.setBarShowingLw(true);
4644 } else if (navVisible) {
4645 mNavigationBarController.setBarShowingLw(true);
4646 mDockBottom = mTmpNavigationFrame.top;
4647 mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
4648 mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
4650 // We currently want to hide the navigation UI - unless we expanded the status
4652 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4654 if (navVisible && !navTranslucent && !navAllowedHidden
4655 && !mNavigationBar.isAnimatingLw()
4656 && !mNavigationBarController.wasRecentlyTranslucent()) {
4657 // If the opaque nav bar is currently requested to be visible,
4658 // and not in the process of animating on or off, then
4659 // we can tell the app that it is covered by it.
4660 mSystemBottom = mTmpNavigationFrame.top;
4662 } else if (mNavigationBarLeftInLandscape) {
4663 // Landscape screen; nav bar goes to the left.
4664 int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode);
4665 mTmpNavigationFrame.set(0, 0, right, displayHeight);
4666 mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right;
4667 if (transientNavBarShowing) {
4668 mNavigationBarController.setBarShowingLw(true);
4669 } else if (navVisible) {
4670 mNavigationBarController.setBarShowingLw(true);
4671 mDockLeft = mTmpNavigationFrame.right;
4672 mRestrictedScreenLeft = mDockLeft;
4673 mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4674 mRestrictedOverscanScreenLeft = mRestrictedScreenLeft;
4675 mRestrictedOverscanScreenWidth = mDockRight
4676 - mRestrictedOverscanScreenLeft;
4678 // We currently want to hide the navigation UI - unless we expanded the status
4680 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4682 if (navVisible && !navTranslucent && !navAllowedHidden
4683 && !mNavigationBar.isAnimatingLw()
4684 && !mNavigationBarController.wasRecentlyTranslucent()) {
4685 // If the nav bar is currently requested to be visible,
4686 // and not in the process of animating on or off, then
4687 // we can tell the app that it is covered by it.
4688 mSystemLeft = mTmpNavigationFrame.right;
4691 // Landscape screen; nav bar goes to the right.
4692 int left = displayWidth - overscanRight
4693 - getNavigationBarWidth(displayRotation, uiMode);
4694 mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
4695 mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
4696 if (transientNavBarShowing) {
4697 mNavigationBarController.setBarShowingLw(true);
4698 } else if (navVisible) {
4699 mNavigationBarController.setBarShowingLw(true);
4700 mDockRight = mTmpNavigationFrame.left;
4701 mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4702 mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4704 // We currently want to hide the navigation UI - unless we expanded the status
4706 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4708 if (navVisible && !navTranslucent && !navAllowedHidden
4709 && !mNavigationBar.isAnimatingLw()
4710 && !mNavigationBarController.wasRecentlyTranslucent()) {
4711 // If the nav bar is currently requested to be visible,
4712 // and not in the process of animating on or off, then
4713 // we can tell the app that it is covered by it.
4714 mSystemRight = mTmpNavigationFrame.left;
4717 // Make sure the content and current rectangles are updated to
4718 // account for the restrictions from the navigation bar.
4719 mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4720 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4721 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4722 mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4723 mStatusBarLayer = mNavigationBar.getSurfaceLayer();
4724 // And compute the final frame.
4725 mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
4726 mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
4727 mTmpNavigationFrame, mTmpNavigationFrame);
4728 if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
4729 if (mNavigationBarController.checkHiddenLw()) {
4736 private boolean isNavigationBarOnBottom(int displayWidth, int displayHeight) {
4737 return !mNavigationBarCanMove || displayWidth < displayHeight;
4740 /** {@inheritDoc} */
4742 public int getSystemDecorLayerLw() {
4743 if (mStatusBar != null && mStatusBar.isVisibleLw()) {
4744 return mStatusBar.getSurfaceLayer();
4747 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) {
4748 return mNavigationBar.getSurfaceLayer();
4755 public void getContentRectLw(Rect r) {
4756 r.set(mContentLeft, mContentTop, mContentRight, mContentBottom);
4759 void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
4760 boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
4761 if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
4762 // Here's a special case: if this attached window is a panel that is
4763 // above the dock window, and the window it is attached to is below
4764 // the dock window, then the frames we computed for the window it is
4765 // attached to can not be used because the dock is effectively part
4766 // of the underlying window and the attached window is floating on top
4767 // of the whole thing. So, we ignore the attached window and explicitly
4768 // compute the frames that would be appropriate without the dock.
4769 df.left = of.left = cf.left = vf.left = mDockLeft;
4770 df.top = of.top = cf.top = vf.top = mDockTop;
4771 df.right = of.right = cf.right = vf.right = mDockRight;
4772 df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom;
4774 // The effective display frame of the attached window depends on
4775 // whether it is taking care of insetting its content. If not,
4776 // we need to use the parent's content frame so that the entire
4777 // window is positioned within that content. Otherwise we can use
4778 // the overscan frame and let the attached window take care of
4779 // positioning its content appropriately.
4780 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4781 // Set the content frame of the attached window to the parent's decor frame
4782 // (same as content frame when IME isn't present) if specifically requested by
4783 // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
4784 // Otherwise, use the overscan frame.
4785 cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
4786 ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
4788 // If the window is resizing, then we want to base the content
4789 // frame on our attached content frame to resize... however,
4790 // things can be tricky if the attached window is NOT in resize
4791 // mode, in which case its content frame will be larger.
4792 // Ungh. So to deal with that, make sure the content frame
4793 // we end up using is not covering the IM dock.
4794 cf.set(attached.getContentFrameLw());
4795 if (attached.isVoiceInteraction()) {
4796 if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft;
4797 if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop;
4798 if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight;
4799 if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom;
4800 } else if (attached.getSurfaceLayer() < mDockLayer) {
4801 if (cf.left < mContentLeft) cf.left = mContentLeft;
4802 if (cf.top < mContentTop) cf.top = mContentTop;
4803 if (cf.right > mContentRight) cf.right = mContentRight;
4804 if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
4807 df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
4808 of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
4809 vf.set(attached.getVisibleFrameLw());
4811 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
4812 // window should be positioned relative to its parent or the entire
4814 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
4815 ? attached.getFrameLw() : df);
4818 private void applyStableConstraints(int sysui, int fl, Rect r) {
4819 if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4820 // If app is requesting a stable layout, don't let the
4821 // content insets go below the stable values.
4822 if ((fl & FLAG_FULLSCREEN) != 0) {
4823 if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft;
4824 if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop;
4825 if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight;
4826 if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom;
4828 if (r.left < mStableLeft) r.left = mStableLeft;
4829 if (r.top < mStableTop) r.top = mStableTop;
4830 if (r.right > mStableRight) r.right = mStableRight;
4831 if (r.bottom > mStableBottom) r.bottom = mStableBottom;
4836 private boolean canReceiveInput(WindowState win) {
4837 boolean notFocusable =
4838 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
4839 boolean altFocusableIm =
4840 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
4841 boolean notFocusableForIm = notFocusable ^ altFocusableIm;
4842 return !notFocusableForIm;
4845 /** {@inheritDoc} */
4847 public void layoutWindowLw(WindowState win, WindowState attached) {
4848 // We've already done the navigation bar and status bar. If the status bar can receive
4849 // input, we need to layout it again to accomodate for the IME window.
4850 if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) {
4853 final WindowManager.LayoutParams attrs = win.getAttrs();
4854 final boolean isDefaultDisplay = win.isDefaultDisplay();
4855 final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
4856 (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
4857 if (needsToOffsetInputMethodTarget) {
4858 if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
4859 offsetInputMethodWindowLw(mLastInputMethodWindow);
4862 final int fl = PolicyControl.getWindowFlags(win, attrs);
4863 final int pfl = attrs.privateFlags;
4864 final int sim = attrs.softInputMode;
4865 final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
4867 final Rect pf = mTmpParentFrame;
4868 final Rect df = mTmpDisplayFrame;
4869 final Rect of = mTmpOverscanFrame;
4870 final Rect cf = mTmpContentFrame;
4871 final Rect vf = mTmpVisibleFrame;
4872 final Rect dcf = mTmpDecorFrame;
4873 final Rect sf = mTmpStableFrame;
4877 final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
4878 && mNavigationBar != null && mNavigationBar.isVisibleLw());
4880 final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
4882 if (isDefaultDisplay) {
4883 sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom);
4885 sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom);
4888 if (!isDefaultDisplay) {
4889 if (attached != null) {
4890 // If this window is attached to another, our display
4891 // frame is the same as the one we are attached to.
4892 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4894 // Give the window full screen.
4895 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4896 pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4897 pf.right = df.right = of.right = cf.right
4898 = mOverscanScreenLeft + mOverscanScreenWidth;
4899 pf.bottom = df.bottom = of.bottom = cf.bottom
4900 = mOverscanScreenTop + mOverscanScreenHeight;
4902 } else if (attrs.type == TYPE_INPUT_METHOD) {
4903 pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
4904 pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
4905 pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
4906 // IM dock windows layout below the nav bar...
4907 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4908 // ...with content insets above the nav bar
4909 cf.bottom = vf.bottom = mStableBottom;
4910 if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
4911 // The status bar forces the navigation bar while it's visible. Make sure the IME
4912 // avoids the navigation bar in that case.
4913 pf.right = df.right = of.right = cf.right = vf.right = mStableRight;
4915 // IM dock windows always go to the bottom of the screen.
4916 attrs.gravity = Gravity.BOTTOM;
4917 mDockLayer = win.getSurfaceLayer();
4918 } else if (attrs.type == TYPE_VOICE_INTERACTION) {
4919 pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4920 pf.top = df.top = of.top = mUnrestrictedScreenTop;
4921 pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4922 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4923 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4924 cf.left = mDockLeft;
4926 cf.right = mDockRight;
4927 cf.bottom = mDockBottom;
4929 cf.left = mContentLeft;
4930 cf.top = mContentTop;
4931 cf.right = mContentRight;
4932 cf.bottom = mContentBottom;
4934 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4937 vf.right = mCurRight;
4938 vf.bottom = mCurBottom;
4942 } else if (win == mStatusBar) {
4943 pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4944 pf.top = df.top = of.top = mUnrestrictedScreenTop;
4945 pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4946 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop;
4947 cf.left = vf.left = mStableLeft;
4948 cf.top = vf.top = mStableTop;
4949 cf.right = vf.right = mStableRight;
4950 vf.bottom = mStableBottom;
4952 if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
4953 cf.bottom = mContentBottom;
4955 cf.bottom = mDockBottom;
4956 vf.bottom = mContentBottom;
4960 // Default policy decor for the default display
4961 dcf.left = mSystemLeft;
4962 dcf.top = mSystemTop;
4963 dcf.right = mSystemRight;
4964 dcf.bottom = mSystemBottom;
4965 final boolean inheritTranslucentDecor = (attrs.privateFlags
4966 & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0;
4967 final boolean isAppWindow =
4968 attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW &&
4969 attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
4970 final boolean topAtRest =
4971 win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
4972 if (isAppWindow && !inheritTranslucentDecor && !topAtRest) {
4973 if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
4974 && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0
4975 && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
4976 && (fl & WindowManager.LayoutParams.
4977 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
4978 && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) {
4979 // Ensure policy decor includes status bar
4980 dcf.top = mStableTop;
4982 if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0
4983 && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
4984 && (fl & WindowManager.LayoutParams.
4985 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
4986 // Ensure policy decor includes navigation bar
4987 dcf.bottom = mStableBottom;
4988 dcf.right = mStableRight;
4992 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4993 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4994 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
4995 + "): IN_SCREEN, INSET_DECOR");
4996 // This is the case for a normal activity window: we want it
4997 // to cover all of the screen space, and it can take care of
4998 // moving its contents to account for screen decorations that
4999 // intrude into that space.
5000 if (attached != null) {
5001 // If this window is attached to another, our display
5002 // frame is the same as the one we are attached to.
5003 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
5005 if (attrs.type == TYPE_STATUS_BAR_PANEL
5006 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
5007 // Status bar panels are the only windows who can go on top of
5008 // the status bar. They are protected by the STATUS_BAR_SERVICE
5009 // permission, so they have the same privileges as the status
5012 // However, they should still dodge the navigation bar if it exists.
5014 pf.left = df.left = of.left = hasNavBar
5015 ? mDockLeft : mUnrestrictedScreenLeft;
5016 pf.top = df.top = of.top = mUnrestrictedScreenTop;
5017 pf.right = df.right = of.right = hasNavBar
5018 ? mRestrictedScreenLeft+mRestrictedScreenWidth
5019 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5020 pf.bottom = df.bottom = of.bottom = hasNavBar
5021 ? mRestrictedScreenTop+mRestrictedScreenHeight
5022 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5024 if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
5025 "Laying out status bar window: (%d,%d - %d,%d)",
5026 pf.left, pf.top, pf.right, pf.bottom));
5027 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
5028 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
5029 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
5030 // Asking to layout into the overscan region, so give it that pure
5031 // unrestricted area.
5032 pf.left = df.left = of.left = mOverscanScreenLeft;
5033 pf.top = df.top = of.top = mOverscanScreenTop;
5034 pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth;
5035 pf.bottom = df.bottom = of.bottom = mOverscanScreenTop
5036 + mOverscanScreenHeight;
5037 } else if (canHideNavigationBar()
5038 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
5039 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
5040 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
5041 // Asking for layout as if the nav bar is hidden, lets the
5042 // application extend into the unrestricted overscan screen area. We
5043 // only do this for application windows to ensure no window that
5044 // can be above the nav bar can do this.
5045 pf.left = df.left = mOverscanScreenLeft;
5046 pf.top = df.top = mOverscanScreenTop;
5047 pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
5048 pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
5049 // We need to tell the app about where the frame inside the overscan
5050 // is, so it can inset its content by that amount -- it didn't ask
5051 // to actually extend itself into the overscan region.
5052 of.left = mUnrestrictedScreenLeft;
5053 of.top = mUnrestrictedScreenTop;
5054 of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5055 of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5057 pf.left = df.left = mRestrictedOverscanScreenLeft;
5058 pf.top = df.top = mRestrictedOverscanScreenTop;
5059 pf.right = df.right = mRestrictedOverscanScreenLeft
5060 + mRestrictedOverscanScreenWidth;
5061 pf.bottom = df.bottom = mRestrictedOverscanScreenTop
5062 + mRestrictedOverscanScreenHeight;
5063 // We need to tell the app about where the frame inside the overscan
5064 // is, so it can inset its content by that amount -- it didn't ask
5065 // to actually extend itself into the overscan region.
5066 of.left = mUnrestrictedScreenLeft;
5067 of.top = mUnrestrictedScreenTop;
5068 of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5069 of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5072 if ((fl & FLAG_FULLSCREEN) == 0) {
5073 if (win.isVoiceInteraction()) {
5074 cf.left = mVoiceContentLeft;
5075 cf.top = mVoiceContentTop;
5076 cf.right = mVoiceContentRight;
5077 cf.bottom = mVoiceContentBottom;
5079 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5080 cf.left = mDockLeft;
5082 cf.right = mDockRight;
5083 cf.bottom = mDockBottom;
5085 cf.left = mContentLeft;
5086 cf.top = mContentTop;
5087 cf.right = mContentRight;
5088 cf.bottom = mContentBottom;
5092 // Full screen windows are always given a layout that is as if the
5093 // status bar and other transient decors are gone. This is to avoid
5094 // bad states when moving from a window that is not hding the
5095 // status bar to one that is.
5096 cf.left = mRestrictedScreenLeft;
5097 cf.top = mRestrictedScreenTop;
5098 cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
5099 cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight;
5101 applyStableConstraints(sysUiFl, fl, cf);
5102 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5105 vf.right = mCurRight;
5106 vf.bottom = mCurBottom;
5111 } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
5112 & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
5113 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
5114 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5116 // A window that has requested to fill the entire screen just
5117 // gets everything, period.
5118 if (attrs.type == TYPE_STATUS_BAR_PANEL
5119 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL
5120 || attrs.type == TYPE_VOLUME_OVERLAY) {
5121 pf.left = df.left = of.left = cf.left = hasNavBar
5122 ? mDockLeft : mUnrestrictedScreenLeft;
5123 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
5124 pf.right = df.right = of.right = cf.right = hasNavBar
5125 ? mRestrictedScreenLeft+mRestrictedScreenWidth
5126 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5127 pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar
5128 ? mRestrictedScreenTop+mRestrictedScreenHeight
5129 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5130 if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
5131 "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
5132 pf.left, pf.top, pf.right, pf.bottom));
5133 } else if (attrs.type == TYPE_NAVIGATION_BAR
5134 || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
5135 // The navigation bar has Real Ultimate Power.
5136 pf.left = df.left = of.left = mUnrestrictedScreenLeft;
5137 pf.top = df.top = of.top = mUnrestrictedScreenTop;
5138 pf.right = df.right = of.right = mUnrestrictedScreenLeft
5139 + mUnrestrictedScreenWidth;
5140 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop
5141 + mUnrestrictedScreenHeight;
5142 if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
5143 "Laying out navigation bar window: (%d,%d - %d,%d)",
5144 pf.left, pf.top, pf.right, pf.bottom));
5145 } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
5146 || attrs.type == TYPE_BOOT_PROGRESS
5147 || attrs.type == TYPE_SCREENSHOT)
5148 && ((fl & FLAG_FULLSCREEN) != 0)) {
5149 // Fullscreen secure system overlays get what they ask for. Screenshot region
5150 // selection overlay should also expand to full screen.
5151 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
5152 pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
5153 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
5154 + mOverscanScreenWidth;
5155 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
5156 + mOverscanScreenHeight;
5157 } else if (attrs.type == TYPE_BOOT_PROGRESS) {
5158 // Boot progress screen always covers entire display.
5159 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
5160 pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
5161 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
5162 + mOverscanScreenWidth;
5163 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
5164 + mOverscanScreenHeight;
5165 } else if (attrs.type == TYPE_WALLPAPER) {
5166 // The wallpaper also has Real Ultimate Power, but we want to tell
5167 // it about the overscan area.
5168 pf.left = df.left = mOverscanScreenLeft;
5169 pf.top = df.top = mOverscanScreenTop;
5170 pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
5171 pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
5172 of.left = cf.left = mUnrestrictedScreenLeft;
5173 of.top = cf.top = mUnrestrictedScreenTop;
5174 of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5175 of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5176 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
5177 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
5178 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
5179 // Asking to layout into the overscan region, so give it that pure
5180 // unrestricted area.
5181 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
5182 pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
5183 pf.right = df.right = of.right = cf.right
5184 = mOverscanScreenLeft + mOverscanScreenWidth;
5185 pf.bottom = df.bottom = of.bottom = cf.bottom
5186 = mOverscanScreenTop + mOverscanScreenHeight;
5187 } else if (canHideNavigationBar()
5188 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
5189 && (attrs.type == TYPE_STATUS_BAR
5190 || attrs.type == TYPE_TOAST
5191 || attrs.type == TYPE_DOCK_DIVIDER
5192 || attrs.type == TYPE_VOICE_INTERACTION_STARTING
5193 || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
5194 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
5195 // Asking for layout as if the nav bar is hidden, lets the
5196 // application extend into the unrestricted screen area. We
5197 // only do this for application windows (or toasts) to ensure no window that
5198 // can be above the nav bar can do this.
5199 // XXX This assumes that an app asking for this will also
5200 // ask for layout in only content. We can't currently figure out
5201 // what the screen would be if only laying out to hide the nav bar.
5202 pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
5203 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
5204 pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft
5205 + mUnrestrictedScreenWidth;
5206 pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
5207 + mUnrestrictedScreenHeight;
5208 } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
5209 pf.left = df.left = of.left = mRestrictedScreenLeft;
5210 pf.top = df.top = of.top = mRestrictedScreenTop;
5211 pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
5212 pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop
5213 + mRestrictedScreenHeight;
5214 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5215 cf.left = mDockLeft;
5217 cf.right = mDockRight;
5218 cf.bottom = mDockBottom;
5220 cf.left = mContentLeft;
5221 cf.top = mContentTop;
5222 cf.right = mContentRight;
5223 cf.bottom = mContentBottom;
5226 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
5227 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
5228 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
5229 + mRestrictedScreenWidth;
5230 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
5231 + mRestrictedScreenHeight;
5234 applyStableConstraints(sysUiFl, fl, cf);
5236 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5239 vf.right = mCurRight;
5240 vf.bottom = mCurBottom;
5244 } else if (attached != null) {
5245 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5246 "): attached to " + attached);
5247 // A child window should be placed inside of the same visible
5248 // frame that its parent had.
5249 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf);
5251 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5252 "): normal window");
5253 // Otherwise, a normal window must be placed inside the content
5254 // of all screen decorations.
5255 if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) {
5256 // Status bar panels and the volume dialog are the only windows who can go on
5257 // top of the status bar. They are protected by the STATUS_BAR_SERVICE
5258 // permission, so they have the same privileges as the status
5260 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
5261 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
5262 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
5263 + mRestrictedScreenWidth;
5264 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
5265 + mRestrictedScreenHeight;
5266 } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) {
5267 // These dialogs are stable to interim decor changes.
5268 pf.left = df.left = of.left = cf.left = mStableLeft;
5269 pf.top = df.top = of.top = cf.top = mStableTop;
5270 pf.right = df.right = of.right = cf.right = mStableRight;
5271 pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom;
5273 pf.left = mContentLeft;
5274 pf.top = mContentTop;
5275 pf.right = mContentRight;
5276 pf.bottom = mContentBottom;
5277 if (win.isVoiceInteraction()) {
5278 df.left = of.left = cf.left = mVoiceContentLeft;
5279 df.top = of.top = cf.top = mVoiceContentTop;
5280 df.right = of.right = cf.right = mVoiceContentRight;
5281 df.bottom = of.bottom = cf.bottom = mVoiceContentBottom;
5282 } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5283 df.left = of.left = cf.left = mDockLeft;
5284 df.top = of.top = cf.top = mDockTop;
5285 df.right = of.right = cf.right = mDockRight;
5286 df.bottom = of.bottom = cf.bottom = mDockBottom;
5288 df.left = of.left = cf.left = mContentLeft;
5289 df.top = of.top = cf.top = mContentTop;
5290 df.right = of.right = cf.right = mContentRight;
5291 df.bottom = of.bottom = cf.bottom = mContentBottom;
5293 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5296 vf.right = mCurRight;
5297 vf.bottom = mCurBottom;
5305 // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
5306 // Also, we don't allow windows in multi-window mode to extend out of the screen.
5307 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR
5308 && !win.isInMultiWindowMode()) {
5309 df.left = df.top = -10000;
5310 df.right = df.bottom = 10000;
5311 if (attrs.type != TYPE_WALLPAPER) {
5312 of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
5313 of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
5317 // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we
5318 // need to provide information to the clients that want to pretend that you can draw there.
5319 // We only want to apply outsets to certain types of windows. For example, we never want to
5320 // apply the outsets to floating dialogs, because they wouldn't make sense there.
5321 final boolean useOutsets = shouldUseOutsets(attrs, fl);
5322 if (isDefaultDisplay && useOutsets) {
5323 osf = mTmpOutsetFrame;
5324 osf.set(cf.left, cf.top, cf.right, cf.bottom);
5325 int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
5327 int rotation = mDisplayRotation;
5328 if (rotation == Surface.ROTATION_0) {
5329 osf.bottom += outset;
5330 } else if (rotation == Surface.ROTATION_90) {
5331 osf.right += outset;
5332 } else if (rotation == Surface.ROTATION_180) {
5334 } else if (rotation == Surface.ROTATION_270) {
5337 if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset
5338 + " with rotation " + rotation + ", result: " + osf);
5342 if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
5343 + ": sim=#" + Integer.toHexString(sim)
5344 + " attach=" + attached + " type=" + attrs.type
5345 + String.format(" flags=0x%08x", fl)
5346 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
5347 + " of=" + of.toShortString()
5348 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
5349 + " dcf=" + dcf.toShortString()
5350 + " sf=" + sf.toShortString()
5351 + " osf=" + (osf == null ? "null" : osf.toShortString()));
5353 win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf);
5355 // Dock windows carve out the bottom of the screen, so normal windows
5356 // can't appear underneath them.
5357 if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleOrBehindKeyguardLw()
5358 && win.isDisplayedLw() && !win.getGivenInsetsPendingLw()) {
5359 setLastInputMethodWindowLw(null, null);
5360 offsetInputMethodWindowLw(win);
5362 if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleOrBehindKeyguardLw()
5363 && !win.getGivenInsetsPendingLw()) {
5364 offsetVoiceInputWindowLw(win);
5368 private void offsetInputMethodWindowLw(WindowState win) {
5369 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5370 top += win.getGivenContentInsetsLw().top;
5371 if (mContentBottom > top) {
5372 mContentBottom = top;
5374 if (mVoiceContentBottom > top) {
5375 mVoiceContentBottom = top;
5377 top = win.getVisibleFrameLw().top;
5378 top += win.getGivenVisibleInsetsLw().top;
5379 if (mCurBottom > top) {
5382 if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
5383 + mDockBottom + " mContentBottom="
5384 + mContentBottom + " mCurBottom=" + mCurBottom);
5387 private void offsetVoiceInputWindowLw(WindowState win) {
5388 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5389 top += win.getGivenContentInsetsLw().top;
5390 if (mVoiceContentBottom > top) {
5391 mVoiceContentBottom = top;
5395 /** {@inheritDoc} */
5397 public void finishLayoutLw() {
5401 /** {@inheritDoc} */
5403 public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
5404 mTopFullscreenOpaqueWindowState = null;
5405 mTopFullscreenOpaqueOrDimmingWindowState = null;
5406 mTopDockedOpaqueWindowState = null;
5407 mTopDockedOpaqueOrDimmingWindowState = null;
5408 mAppsToBeHidden.clear();
5409 mAppsThatDismissKeyguard.clear();
5410 mForceStatusBar = false;
5411 mForceStatusBarFromKeyguard = false;
5412 mForceStatusBarTransparent = false;
5413 mForcingShowNavBar = false;
5414 mForcingShowNavBarLayer = -1;
5416 mHideLockScreen = false;
5417 mAllowLockscreenWhenOn = false;
5418 mDismissKeyguard = DISMISS_KEYGUARD_NONE;
5419 mShowingLockscreen = false;
5420 mShowingDream = false;
5421 mWinShowWhenLocked = null;
5422 mKeyguardSecure = isKeyguardSecure(mCurrentUserId);
5423 mKeyguardSecureIncludingHidden = mKeyguardSecure
5424 && (mKeyguardDelegate != null && mKeyguardDelegate.isShowing());
5427 /** {@inheritDoc} */
5429 public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
5430 WindowState attached) {
5431 if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
5432 + win.isVisibleOrBehindKeyguardLw());
5433 final int fl = PolicyControl.getWindowFlags(win, attrs);
5434 if (mTopFullscreenOpaqueWindowState == null
5435 && win.isVisibleLw() && attrs.type == TYPE_INPUT_METHOD) {
5436 mForcingShowNavBar = true;
5437 mForcingShowNavBarLayer = win.getSurfaceLayer();
5439 if (attrs.type == TYPE_STATUS_BAR) {
5440 if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
5441 mForceStatusBarFromKeyguard = true;
5442 mShowingLockscreen = true;
5444 if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
5445 mForceStatusBarTransparent = true;
5449 boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
5450 && attrs.type < FIRST_SYSTEM_WINDOW;
5451 final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0;
5452 final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0;
5453 final int stackId = win.getStackId();
5454 if (mTopFullscreenOpaqueWindowState == null &&
5455 win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
5456 if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
5457 if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
5458 mForceStatusBarFromKeyguard = true;
5460 mForceStatusBar = true;
5463 if (attrs.type == TYPE_DREAM) {
5464 // If the lockscreen was showing when the dream started then wait
5465 // for the dream to draw before hiding the lockscreen.
5466 if (!mDreamingLockscreen
5467 || (win.isVisibleLw() && win.hasDrawnLw())) {
5468 mShowingDream = true;
5473 final IApplicationToken appToken = win.getAppToken();
5475 // For app windows that are not attached, we decide if all windows in the app they
5476 // represent should be hidden or if we should hide the lockscreen. For attached app
5477 // windows we defer the decision to the window it is attached to.
5478 if (appWindow && attached == null) {
5479 if (showWhenLocked) {
5480 // Remove any previous windows with the same appToken.
5481 mAppsToBeHidden.remove(appToken);
5482 mAppsThatDismissKeyguard.remove(appToken);
5483 if (mAppsToBeHidden.isEmpty()) {
5484 if (dismissKeyguard && !mKeyguardSecure) {
5485 mAppsThatDismissKeyguard.add(appToken);
5486 } else if (win.isDrawnLw() || win.hasAppShownWindows()) {
5487 mWinShowWhenLocked = win;
5488 mHideLockScreen = true;
5489 mForceStatusBarFromKeyguard = false;
5492 } else if (dismissKeyguard) {
5493 if (mKeyguardSecure) {
5494 mAppsToBeHidden.add(appToken);
5496 mAppsToBeHidden.remove(appToken);
5498 mAppsThatDismissKeyguard.add(appToken);
5500 mAppsToBeHidden.add(appToken);
5502 if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
5503 if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
5504 mTopFullscreenOpaqueWindowState = win;
5505 if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5506 mTopFullscreenOpaqueOrDimmingWindowState = win;
5508 if (!mAppsThatDismissKeyguard.isEmpty() &&
5509 mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
5510 if (DEBUG_LAYOUT) Slog.v(TAG,
5511 "Setting mDismissKeyguard true by win " + win);
5512 mDismissKeyguard = (mWinDismissingKeyguard == win
5513 && mSecureDismissingKeyguard == mKeyguardSecure)
5514 ? DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
5515 mWinDismissingKeyguard = win;
5516 mSecureDismissingKeyguard = mKeyguardSecure;
5517 mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure;
5518 } else if (mAppsToBeHidden.isEmpty() && showWhenLocked
5519 && (win.isDrawnLw() || win.hasAppShownWindows())) {
5520 if (DEBUG_LAYOUT) Slog.v(TAG,
5521 "Setting mHideLockScreen to true by win " + win);
5522 mHideLockScreen = true;
5523 mForceStatusBarFromKeyguard = false;
5525 if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
5526 mAllowLockscreenWhenOn = true;
5530 if (!mKeyguardHidden && mWinShowWhenLocked != null &&
5531 mWinShowWhenLocked.getAppToken() != win.getAppToken() &&
5532 (attrs.flags & FLAG_SHOW_WHEN_LOCKED) == 0) {
5536 } else if (mTopFullscreenOpaqueWindowState == null && mWinShowWhenLocked == null) {
5537 // No TopFullscreenOpaqueWindow is showing, but we found a SHOW_WHEN_LOCKED window
5538 // that is being hidden in an animation - keep the
5539 // keyguard hidden until the new window shows up and
5540 // we know whether to show the keyguard or not.
5541 if (win.isAnimatingLw() && appWindow && showWhenLocked && mKeyguardHidden) {
5542 mHideLockScreen = true;
5543 mWinShowWhenLocked = win;
5547 // Keep track of the window if it's dimming but not necessarily fullscreen.
5548 final boolean reallyVisible = win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw();
5549 if (mTopFullscreenOpaqueOrDimmingWindowState == null && reallyVisible
5550 && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
5551 mTopFullscreenOpaqueOrDimmingWindowState = win;
5554 // We need to keep track of the top "fullscreen" opaque window for the docked stack
5555 // separately, because both the "real fullscreen" opaque window and the one for the docked
5556 // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
5557 if (mTopDockedOpaqueWindowState == null && reallyVisible && appWindow && attached == null
5558 && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
5559 mTopDockedOpaqueWindowState = win;
5560 if (mTopDockedOpaqueOrDimmingWindowState == null) {
5561 mTopDockedOpaqueOrDimmingWindowState = win;
5565 // Also keep track of any windows that are dimming but not necessarily fullscreen in the
5567 if (mTopDockedOpaqueOrDimmingWindowState == null && reallyVisible && win.isDimming()
5568 && stackId == DOCKED_STACK_ID) {
5569 mTopDockedOpaqueOrDimmingWindowState = win;
5573 private boolean isFullscreen(WindowManager.LayoutParams attrs) {
5574 return attrs.x == 0 && attrs.y == 0
5575 && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
5576 && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
5579 /** {@inheritDoc} */
5581 public int finishPostLayoutPolicyLw() {
5582 if (mWinShowWhenLocked != null && mTopFullscreenOpaqueWindowState != null &&
5583 mWinShowWhenLocked.getAppToken() != mTopFullscreenOpaqueWindowState.getAppToken()
5584 && isKeyguardLocked()) {
5585 // A dialog is dismissing the keyguard. Put the wallpaper behind it and hide the
5586 // fullscreen window.
5587 // TODO: Make sure FLAG_SHOW_WALLPAPER is restored when dialog is dismissed. Or not.
5588 mWinShowWhenLocked.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5589 mTopFullscreenOpaqueWindowState.hideLw(false);
5590 mTopFullscreenOpaqueWindowState = mWinShowWhenLocked;
5594 boolean topIsFullscreen = false;
5596 final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
5597 ? mTopFullscreenOpaqueWindowState.getAttrs()
5600 // If we are not currently showing a dream then remember the current
5601 // lockscreen state. We will use this to determine whether the dream
5602 // started while the lockscreen was showing and remember this state
5603 // while the dream is showing.
5604 if (!mShowingDream) {
5605 mDreamingLockscreen = mShowingLockscreen;
5606 if (mDreamingSleepTokenNeeded) {
5607 mDreamingSleepTokenNeeded = false;
5608 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
5611 if (!mDreamingSleepTokenNeeded) {
5612 mDreamingSleepTokenNeeded = true;
5613 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget();
5617 if (mStatusBar != null) {
5618 if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
5619 + " forcefkg=" + mForceStatusBarFromKeyguard
5620 + " top=" + mTopFullscreenOpaqueWindowState);
5621 boolean shouldBeTransparent = mForceStatusBarTransparent
5623 && !mForceStatusBarFromKeyguard;
5624 if (!shouldBeTransparent) {
5625 mStatusBarController.setShowTransparent(false /* transparent */);
5626 } else if (!mStatusBar.isVisibleLw()) {
5627 mStatusBarController.setShowTransparent(true /* transparent */);
5630 WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs();
5631 boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT
5632 && statusBarAttrs.width == MATCH_PARENT;
5633 if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
5634 || statusBarExpanded) {
5635 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
5636 if (mStatusBarController.setBarShowingLw(true)) {
5637 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5639 // Maintain fullscreen layout until incoming animation is complete.
5640 topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
5641 // Transient status bar on the lockscreen is not allowed
5642 if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) {
5643 mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
5644 mLastSystemUiFlags, mLastSystemUiFlags);
5646 if (statusBarExpanded && mNavigationBar != null) {
5647 if (mNavigationBarController.setBarShowingLw(true)) {
5648 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5651 } else if (mTopFullscreenOpaqueWindowState != null) {
5652 final int fl = PolicyControl.getWindowFlags(null, lp);
5654 Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
5655 + " shown position: "
5656 + mTopFullscreenOpaqueWindowState.getShownPositionLw());
5657 Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
5658 + " lp.flags=0x" + Integer.toHexString(fl));
5660 topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
5661 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
5662 // The subtle difference between the window for mTopFullscreenOpaqueWindowState
5663 // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
5664 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the
5666 if (mStatusBarController.isTransientShowing()) {
5667 if (mStatusBarController.setBarShowingLw(true)) {
5668 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5670 } else if (topIsFullscreen
5671 && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)
5672 && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) {
5673 if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
5674 if (mStatusBarController.setBarShowingLw(false)) {
5675 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5677 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
5680 if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
5681 if (mStatusBarController.setBarShowingLw(true)) {
5682 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5688 if (mTopIsFullscreen != topIsFullscreen) {
5689 if (!topIsFullscreen) {
5690 // Force another layout when status bar becomes fully shown.
5691 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5693 mTopIsFullscreen = topIsFullscreen;
5696 // Hide the key guard if a visible window explicitly specifies that it wants to be
5697 // displayed when the screen is locked.
5698 if (mKeyguardDelegate != null && mStatusBar != null) {
5699 if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
5701 if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardSecure) {
5702 mKeyguardHidden = true;
5703 if (setKeyguardOccludedLw(true)) {
5704 changes |= FINISH_LAYOUT_REDO_LAYOUT
5705 | FINISH_LAYOUT_REDO_CONFIG
5706 | FINISH_LAYOUT_REDO_WALLPAPER;
5708 if (mKeyguardDelegate.isShowing()) {
5709 mHandler.post(new Runnable() {
5712 mKeyguardDelegate.keyguardDone(false, false);
5716 } else if (mHideLockScreen) {
5717 mKeyguardHidden = true;
5718 mWinDismissingKeyguard = null;
5719 if (setKeyguardOccludedLw(true)) {
5720 changes |= FINISH_LAYOUT_REDO_LAYOUT
5721 | FINISH_LAYOUT_REDO_CONFIG
5722 | FINISH_LAYOUT_REDO_WALLPAPER;
5724 } else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) {
5725 mKeyguardHidden = false;
5726 if (setKeyguardOccludedLw(false)) {
5727 changes |= FINISH_LAYOUT_REDO_LAYOUT
5728 | FINISH_LAYOUT_REDO_CONFIG
5729 | FINISH_LAYOUT_REDO_WALLPAPER;
5731 if (mDismissKeyguard == DISMISS_KEYGUARD_START) {
5732 // Only launch the next keyguard unlock window once per window.
5733 mHandler.post(new Runnable() {
5736 mKeyguardDelegate.dismiss();
5741 mWinDismissingKeyguard = null;
5742 mSecureDismissingKeyguard = false;
5743 mKeyguardHidden = false;
5744 if (setKeyguardOccludedLw(false)) {
5745 changes |= FINISH_LAYOUT_REDO_LAYOUT
5746 | FINISH_LAYOUT_REDO_CONFIG
5747 | FINISH_LAYOUT_REDO_WALLPAPER;
5752 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5753 // If the navigation bar has been hidden or shown, we need to do another
5754 // layout pass to update that window.
5755 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5758 // update since mAllowLockscreenWhenOn might have changed
5759 updateLockScreenTimeout();
5764 * Updates the occluded state of the Keyguard.
5766 * @return Whether the flags have changed and we have to redo the layout.
5768 private boolean setKeyguardOccludedLw(boolean isOccluded) {
5769 boolean wasOccluded = mKeyguardOccluded;
5770 boolean showing = mKeyguardDelegate.isShowing();
5771 if (wasOccluded && !isOccluded && showing) {
5772 mKeyguardOccluded = false;
5773 mKeyguardDelegate.setOccluded(false);
5774 mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
5776 } else if (!wasOccluded && isOccluded && showing) {
5777 mKeyguardOccluded = true;
5778 mKeyguardDelegate.setOccluded(true);
5779 mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
5780 mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
5787 private boolean isStatusBarKeyguard() {
5788 return mStatusBar != null
5789 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
5793 public boolean allowAppAnimationsLw() {
5794 if (isStatusBarKeyguard() || mShowingDream) {
5795 // If keyguard or dreams is currently visible, no reason to animate behind it.
5802 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
5803 mFocusedWindow = newFocus;
5804 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5805 // If the navigation bar has been hidden or shown, we need to do another
5806 // layout pass to update that window.
5807 return FINISH_LAYOUT_REDO_LAYOUT;
5812 /** {@inheritDoc} */
5814 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
5815 // lid changed state
5816 final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
5817 if (newLidState == mLidState) {
5821 mLidState = newLidState;
5822 applyLidSwitchState();
5823 updateRotation(true);
5826 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
5827 "android.policy:LID");
5828 } else if (!mLidControlsSleep) {
5829 mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
5834 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
5835 int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
5836 if (mCameraLensCoverState == lensCoverState) {
5839 if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
5840 lensCoverState == CAMERA_LENS_UNCOVERED) {
5842 final boolean keyguardActive = mKeyguardDelegate == null ? false :
5843 mKeyguardDelegate.isShowing();
5844 if (keyguardActive) {
5845 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
5847 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
5849 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
5850 "android.policy:CAMERA_COVER");
5851 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
5853 mCameraLensCoverState = lensCoverState;
5856 void setHdmiPlugged(boolean plugged) {
5857 if (mHdmiPlugged != plugged) {
5858 mHdmiPlugged = plugged;
5859 updateRotation(true, true);
5860 Intent intent = new Intent(ACTION_HDMI_PLUGGED);
5861 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
5862 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
5863 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
5867 void initializeHdmiState() {
5868 boolean plugged = false;
5869 // watch for HDMI plug messages if the hdmi switch exists
5870 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
5871 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
5873 final String filename = "/sys/class/switch/hdmi/state";
5874 FileReader reader = null;
5876 reader = new FileReader(filename);
5877 char[] buf = new char[15];
5878 int n = reader.read(buf);
5880 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
5882 } catch (IOException ex) {
5883 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5884 } catch (NumberFormatException ex) {
5885 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5887 if (reader != null) {
5890 } catch (IOException ex) {
5895 // This dance forces the code in setHdmiPlugged to run.
5896 // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
5897 mHdmiPlugged = !plugged;
5898 setHdmiPlugged(!mHdmiPlugged);
5902 * @return Whether music is being played right now "locally" (e.g. on the device's speakers
5903 * or wired headphones) or "remotely" (e.g. on a device using the Cast protocol and
5904 * controlled by this device, or through remote submix).
5906 private boolean isMusicActive() {
5907 final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
5909 Log.w(TAG, "isMusicActive: couldn't get AudioManager reference");
5912 return am.isMusicActive();
5915 final Object mScreenshotLock = new Object();
5916 ServiceConnection mScreenshotConnection = null;
5918 final Runnable mScreenshotTimeout = new Runnable() {
5919 @Override public void run() {
5920 synchronized (mScreenshotLock) {
5921 if (mScreenshotConnection != null) {
5922 mContext.unbindService(mScreenshotConnection);
5923 mScreenshotConnection = null;
5924 notifyScreenshotError();
5930 // Assume this is called from the Handler thread.
5931 private void takeScreenshot(final int screenshotType) {
5932 synchronized (mScreenshotLock) {
5933 if (mScreenshotConnection != null) {
5936 final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
5937 SYSUI_SCREENSHOT_SERVICE);
5938 final Intent serviceIntent = new Intent();
5939 serviceIntent.setComponent(serviceComponent);
5940 ServiceConnection conn = new ServiceConnection() {
5942 public void onServiceConnected(ComponentName name, IBinder service) {
5943 synchronized (mScreenshotLock) {
5944 if (mScreenshotConnection != this) {
5947 Messenger messenger = new Messenger(service);
5948 Message msg = Message.obtain(null, screenshotType);
5949 final ServiceConnection myConn = this;
5950 Handler h = new Handler(mHandler.getLooper()) {
5952 public void handleMessage(Message msg) {
5953 synchronized (mScreenshotLock) {
5954 if (mScreenshotConnection == myConn) {
5955 mContext.unbindService(mScreenshotConnection);
5956 mScreenshotConnection = null;
5957 mHandler.removeCallbacks(mScreenshotTimeout);
5962 msg.replyTo = new Messenger(h);
5963 msg.arg1 = msg.arg2 = 0;
5964 if (mStatusBar != null && mStatusBar.isVisibleLw())
5966 if (mNavigationBar != null && mNavigationBar.isVisibleLw())
5969 messenger.send(msg);
5970 } catch (RemoteException e) {
5976 public void onServiceDisconnected(ComponentName name) {
5977 notifyScreenshotError();
5980 if (mContext.bindServiceAsUser(serviceIntent, conn,
5981 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
5982 UserHandle.CURRENT)) {
5983 mScreenshotConnection = conn;
5984 mHandler.postDelayed(mScreenshotTimeout, 10000);
5990 * Notifies the screenshot service to show an error.
5992 private void notifyScreenshotError() {
5993 // If the service process is killed, then ask it to clean up after itself
5994 final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
5995 SYSUI_SCREENSHOT_ERROR_RECEIVER);
5996 Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
5997 errorIntent.setComponent(errorComponent);
5998 errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
5999 Intent.FLAG_RECEIVER_FOREGROUND);
6000 mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT);
6003 private void setVolumeWakeTriggered(final int keyCode, boolean triggered) {
6005 case KeyEvent.KEYCODE_VOLUME_DOWN:
6006 mVolumeDownWakeTriggered = triggered;
6008 case KeyEvent.KEYCODE_VOLUME_UP:
6009 mVolumeUpWakeTriggered = triggered;
6011 case KeyEvent.KEYCODE_VOLUME_MUTE:
6012 mVolumeMuteWakeTriggered = triggered;
6015 Log.w(TAG, "setVolumeWakeTriggered: unexpected keyCode=" + keyCode);
6019 private boolean getVolumeWakeTriggered(final int keyCode) {
6021 case KeyEvent.KEYCODE_VOLUME_DOWN:
6022 return mVolumeDownWakeTriggered;
6023 case KeyEvent.KEYCODE_VOLUME_UP:
6024 return mVolumeUpWakeTriggered;
6025 case KeyEvent.KEYCODE_VOLUME_MUTE:
6026 return mVolumeMuteWakeTriggered;
6028 Log.w(TAG, "getVolumeWakeTriggered: unexpected keyCode=" + keyCode);
6033 /** {@inheritDoc} */
6035 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
6036 if (!mSystemBooted) {
6037 // If we have not yet booted, don't let key events do anything.
6041 final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
6042 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
6043 final boolean canceled = event.isCanceled();
6044 final int keyCode = event.getKeyCode();
6045 final int scanCode = event.getScanCode();
6047 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
6049 // If screen is off then we treat the case where the keyguard is open but hidden
6050 // the same as if it were open and in front.
6051 // This will prevent any keys other than the power button from waking the screen
6052 // when the keyguard is hidden by another activity.
6053 final boolean keyguardActive = (mKeyguardDelegate == null ? false :
6055 isKeyguardShowingAndNotOccluded() :
6056 mKeyguardDelegate.isShowing()));
6059 Log.d(TAG, "interceptKeyTq keycode=" + keyCode
6060 + " interactive=" + interactive + " keyguardActive=" + keyguardActive
6061 + " policyFlags=" + Integer.toHexString(policyFlags));
6064 // Basic policy based on interactive state.
6066 boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
6067 || event.isWakeKey();
6068 if (interactive || (isInjected && !isWakeKey)) {
6069 // When the device is interactive or the key is injected pass the
6070 // key to the application.
6071 result = ACTION_PASS_TO_USER;
6073 } else if (!interactive && shouldDispatchInputWhenNonInteractive()) {
6074 // If we're currently dozing with the screen on and the keyguard showing, pass the key
6075 // to the application but preserve its wake key status to make sure we still move
6076 // from dozing to fully interactive if we would normally go from off to fully
6077 // interactive, unless the user has explicitly disabled this wake key.
6078 result = ACTION_PASS_TO_USER;
6079 isWakeKey = isWakeKey && isWakeKeyEnabled(keyCode);
6081 // When the screen is off and the key is not injected, determine whether
6082 // to wake the device but don't pass the key to the application.
6084 if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
6089 // If the key would be handled globally, just return the result, don't worry about special
6091 if (isValidGlobalKey(keyCode)
6092 && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
6094 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
6099 boolean useHapticFeedback = down
6100 && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
6101 && event.getRepeatCount() == 0;
6103 // Specific device key handling
6104 if (mDeviceKeyHandler != null) {
6106 // The device only should consume known keys.
6107 if (mDeviceKeyHandler.handleKeyEvent(event)) {
6110 } catch (Exception e) {
6111 Slog.w(TAG, "Could not dispatch event to device key handler", e);
6115 // Handle special keys.
6117 case KeyEvent.KEYCODE_BACK: {
6119 mBackKeyHandled = false;
6120 if (hasLongPressOnBackBehavior()) {
6121 Message msg = mHandler.obtainMessage(MSG_BACK_LONG_PRESS);
6122 msg.setAsynchronous(true);
6123 mHandler.sendMessageDelayed(msg,
6124 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
6127 boolean handled = mBackKeyHandled;
6129 // Reset back key state
6130 cancelPendingBackKeyAction();
6132 // Don't pass back press to app if we've already handled it
6134 result &= ~ACTION_PASS_TO_USER;
6140 case KeyEvent.KEYCODE_VOLUME_DOWN:
6141 case KeyEvent.KEYCODE_VOLUME_UP:
6142 case KeyEvent.KEYCODE_VOLUME_MUTE: {
6143 // Eat all down & up keys when using volume wake.
6144 // This disables volume control, music control, and "beep" on key up.
6145 if (isWakeKey && mVolumeWakeScreen) {
6146 setVolumeWakeTriggered(keyCode, true);
6148 } else if (getVolumeWakeTriggered(keyCode) && !down) {
6149 result &= ~ACTION_PASS_TO_USER;
6150 setVolumeWakeTriggered(keyCode, false);
6154 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
6156 if (interactive && !mScreenshotChordVolumeDownKeyTriggered
6157 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
6158 mScreenshotChordVolumeDownKeyTriggered = true;
6159 mScreenshotChordVolumeDownKeyTime = event.getDownTime();
6160 mScreenshotChordVolumeDownKeyConsumed = false;
6161 cancelPendingPowerKeyAction();
6162 interceptScreenshotChord();
6165 mScreenshotChordVolumeDownKeyTriggered = false;
6166 cancelPendingScreenshotChordAction();
6168 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
6170 if (interactive && !mScreenshotChordVolumeUpKeyTriggered
6171 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
6172 mScreenshotChordVolumeUpKeyTriggered = true;
6173 cancelPendingPowerKeyAction();
6174 cancelPendingScreenshotChordAction();
6177 mScreenshotChordVolumeUpKeyTriggered = false;
6178 cancelPendingScreenshotChordAction();
6182 TelecomManager telecomManager = getTelecommService();
6183 if (telecomManager != null) {
6184 if (telecomManager.isRinging()) {
6185 // If an incoming call is ringing, either VOLUME key means
6186 // "silence ringer". We handle these keys here, rather than
6187 // in the InCallScreen, to make sure we'll respond to them
6188 // even if the InCallScreen hasn't come to the foreground yet.
6189 // Look for the DOWN event here, to agree with the "fallback"
6190 // behavior in the InCallScreen.
6191 Log.i(TAG, "interceptKeyBeforeQueueing:"
6192 + " VOLUME key-down while ringing: Silence ringer!");
6194 // Silence the ringer. (It's safe to call this
6195 // even if the ringer has already been silenced.)
6196 telecomManager.silenceRinger();
6198 // And *don't* pass this key thru to the current activity
6199 // (which is probably the InCallScreen.)
6200 result &= ~ACTION_PASS_TO_USER;
6203 if (telecomManager.isInCall()
6204 && (result & ACTION_PASS_TO_USER) == 0) {
6205 // If we are in call but we decided not to pass the key to
6206 // the application, just pass it to the session service.
6208 MediaSessionLegacyHelper.getHelper(mContext)
6209 .sendVolumeKeyEvent(event, false);
6214 if (mUseTvRouting) {
6215 // On TVs, defer special key handlings to
6216 // {@link interceptKeyBeforeDispatching()}.
6217 result |= ACTION_PASS_TO_USER;
6218 } else if ((result & ACTION_PASS_TO_USER) == 0) {
6219 // If we aren't passing to the user and no one else
6220 // handled it send it to the session manager to
6222 MediaSessionLegacyHelper.getHelper(mContext)
6223 .sendVolumeKeyEvent(event, true);
6226 // Disable music and volume control when used as wake key
6227 if ((result & ACTION_PASS_TO_USER) == 0 && !mVolumeWakeScreen) {
6228 boolean mayChangeVolume = false;
6230 if (isMusicActive()) {
6231 if (mVolBtnMusicControls && (keyCode != KeyEvent.KEYCODE_VOLUME_MUTE)) {
6232 // Detect long key presses.
6234 mIsLongPress = false;
6235 // TODO: Long press of MUTE could be mapped to KEYCODE_MEDIA_PLAY_PAUSE
6236 int newKeyCode = event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP ?
6237 KeyEvent.KEYCODE_MEDIA_NEXT : KeyEvent.KEYCODE_MEDIA_PREVIOUS;
6238 scheduleLongPressKeyEvent(event, newKeyCode);
6239 // Consume key down events of all presses.
6242 mHandler.removeMessages(MSG_DISPATCH_VOLKEY_WITH_WAKE_LOCK);
6243 // Consume key up events of long presses only.
6247 // Change volume only on key up events of short presses.
6248 mayChangeVolume = true;
6251 // Long key press detection not applicable, change volume only
6252 // on key down events
6253 mayChangeVolume = down;
6257 if (mayChangeVolume) {
6258 if (mUseTvRouting) {
6259 dispatchDirectAudioEvent(event);
6261 // If we aren't passing to the user and no one else
6262 // handled it send it to the session manager to figure
6265 // Rewrite the event to use key-down as sendVolumeKeyEvent will
6266 // only change the volume on key down.
6267 KeyEvent newEvent = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
6268 MediaSessionLegacyHelper.getHelper(mContext)
6269 .sendVolumeKeyEvent(newEvent, true);
6277 case KeyEvent.KEYCODE_HOME:
6278 if (down && !interactive && mHomeWakeScreen) {
6283 case KeyEvent.KEYCODE_FOCUS:
6284 if (down && !interactive && mCameraSleepOnRelease) {
6285 mIsFocusPressed = true;
6286 } else if ((event.getAction() == KeyEvent.ACTION_UP)
6287 && mScreenOnFully && mIsFocusPressed) {
6288 // Check if screen is fully on before letting the device go to sleep
6289 mPowerManager.goToSleep(SystemClock.uptimeMillis());
6290 mIsFocusPressed = false;
6294 case KeyEvent.KEYCODE_CAMERA:
6295 if (down && mIsFocusPressed) {
6296 mIsFocusPressed = false;
6299 mIsLongPress = false;
6300 scheduleLongPressKeyEvent(event, KeyEvent.KEYCODE_CAMERA);
6301 // Consume key down events of all presses.
6304 mHandler.removeMessages(MSG_CAMERA_LONG_PRESS);
6305 // Consume key up events of long presses only.
6306 if (mIsLongPress && mCameraLaunch) {
6308 if (keyguardActive) {
6309 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
6311 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
6314 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
6319 case KeyEvent.KEYCODE_ENDCALL: {
6320 result &= ~ACTION_PASS_TO_USER;
6322 TelecomManager telecomManager = getTelecommService();
6323 boolean hungUp = false;
6324 if (telecomManager != null) {
6325 hungUp = telecomManager.endCall();
6327 if (interactive && !hungUp) {
6328 mEndCallKeyHandled = false;
6329 mHandler.postDelayed(mEndCallLongPress,
6330 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
6332 mEndCallKeyHandled = true;
6335 if (!mEndCallKeyHandled) {
6336 mHandler.removeCallbacks(mEndCallLongPress);
6338 if ((mEndcallBehavior
6339 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
6344 if ((mEndcallBehavior
6345 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
6346 mPowerManager.goToSleep(event.getEventTime(),
6347 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
6356 case KeyEvent.KEYCODE_POWER: {
6357 if ((mTopFullscreenOpaqueWindowState.getAttrs().privateFlags
6358 & WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_POWER_KEY) != 0
6359 && mScreenOnFully) {
6362 result &= ~ACTION_PASS_TO_USER;
6363 isWakeKey = false; // wake-up will be handled separately
6365 interceptPowerKeyDown(event, interactive);
6367 interceptPowerKeyUp(event, interactive, canceled);
6372 case KeyEvent.KEYCODE_SLEEP: {
6373 result &= ~ACTION_PASS_TO_USER;
6375 if (!mPowerManager.isInteractive()) {
6376 useHapticFeedback = false; // suppress feedback if already non-interactive
6379 sleepPress(event.getEventTime());
6381 sleepRelease(event.getEventTime());
6386 case KeyEvent.KEYCODE_SOFT_SLEEP: {
6387 result &= ~ACTION_PASS_TO_USER;
6390 mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
6395 case KeyEvent.KEYCODE_WAKEUP: {
6396 result &= ~ACTION_PASS_TO_USER;
6401 case KeyEvent.KEYCODE_MEDIA_PLAY:
6402 case KeyEvent.KEYCODE_MEDIA_PAUSE:
6403 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6404 case KeyEvent.KEYCODE_HEADSETHOOK:
6405 case KeyEvent.KEYCODE_MUTE:
6406 case KeyEvent.KEYCODE_MEDIA_STOP:
6407 case KeyEvent.KEYCODE_MEDIA_NEXT:
6408 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6409 case KeyEvent.KEYCODE_MEDIA_REWIND:
6410 case KeyEvent.KEYCODE_MEDIA_RECORD:
6411 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6412 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
6413 if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
6414 // If the global session is active pass all media keys to it
6415 // instead of the active window.
6416 result &= ~ACTION_PASS_TO_USER;
6418 if ((result & ACTION_PASS_TO_USER) == 0) {
6419 // Only do this if we would otherwise not pass it to the user. In that
6420 // case, the PhoneWindow class will do the same thing, except it will
6421 // only do it if the showing app doesn't process the key on its own.
6422 // Note that we need to make a copy of the key event here because the
6423 // original key event will be recycled when we return.
6424 mBroadcastWakeLock.acquire();
6425 Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
6426 new KeyEvent(event));
6427 msg.setAsynchronous(true);
6433 case KeyEvent.KEYCODE_CALL: {
6435 TelecomManager telecomManager = getTelecommService();
6436 if (telecomManager != null) {
6437 if (telecomManager.isRinging()) {
6438 Log.i(TAG, "interceptKeyBeforeQueueing:"
6439 + " CALL key-down while ringing: Answer the call!");
6440 telecomManager.acceptRingingCall();
6442 // And *don't* pass this key thru to the current activity
6443 // (which is presumably the InCallScreen.)
6444 result &= ~ACTION_PASS_TO_USER;
6450 case KeyEvent.KEYCODE_VOICE_ASSIST: {
6451 // Only do this if we would otherwise not pass it to the user. In that case,
6452 // interceptKeyBeforeDispatching would apply a similar but different policy in
6453 // order to invoke voice assist actions. Note that we need to make a copy of the
6454 // key event here because the original key event will be recycled when we return.
6455 if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
6456 mBroadcastWakeLock.acquire();
6457 Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
6458 keyguardActive ? 1 : 0, 0);
6459 msg.setAsynchronous(true);
6464 case KeyEvent.KEYCODE_WINDOW: {
6465 if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
6466 if (mTvPictureInPictureVisible) {
6467 // Consumes the key only if picture-in-picture is visible
6468 // to show picture-in-picture control menu.
6469 // This gives a chance to the foreground activity
6470 // to customize PIP key behavior.
6472 showTvPictureInPictureMenu(event);
6474 result &= ~ACTION_PASS_TO_USER;
6481 if (useHapticFeedback) {
6482 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
6486 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
6492 private void scheduleLongPressKeyEvent(KeyEvent origEvent, int keyCode) {
6493 KeyEvent event = new KeyEvent(origEvent.getDownTime(), origEvent.getEventTime(),
6494 origEvent.getAction(), keyCode, 0);
6496 if (keyCode == KeyEvent.KEYCODE_CAMERA) {
6497 msg = mHandler.obtainMessage(MSG_CAMERA_LONG_PRESS, event);
6499 msg = mHandler.obtainMessage(MSG_DISPATCH_VOLKEY_WITH_WAKE_LOCK, event);
6501 msg.setAsynchronous(true);
6502 mHandler.sendMessageDelayed(msg, ViewConfiguration.getLongPressTimeout());
6506 * Returns true if the key can have global actions attached to it.
6507 * We reserve all power management keys for the system since they require
6508 * very careful handling.
6510 private static boolean isValidGlobalKey(int keyCode) {
6512 case KeyEvent.KEYCODE_POWER:
6513 case KeyEvent.KEYCODE_WAKEUP:
6514 case KeyEvent.KEYCODE_SLEEP:
6522 * Check if the given keyCode represents a key that is considered a wake key
6523 * and is currently enabled by the user in Settings or for another reason.
6525 private boolean isWakeKeyEnabled(int keyCode) {
6527 case KeyEvent.KEYCODE_VOLUME_UP:
6528 case KeyEvent.KEYCODE_VOLUME_DOWN:
6529 case KeyEvent.KEYCODE_VOLUME_MUTE:
6530 // Volume keys are still wake keys if the device is docked.
6531 return mVolumeWakeScreen || mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
6532 case KeyEvent.KEYCODE_BACK:
6533 return mBackWakeScreen;
6534 case KeyEvent.KEYCODE_MENU:
6535 return mMenuWakeScreen;
6536 case KeyEvent.KEYCODE_ASSIST:
6537 return mAssistWakeScreen;
6538 case KeyEvent.KEYCODE_APP_SWITCH:
6539 return mAppSwitchWakeScreen;
6540 case KeyEvent.KEYCODE_CAMERA:
6541 case KeyEvent.KEYCODE_FOCUS:
6542 return mCameraWakeScreen;
6548 * When the screen is off we ignore some keys that might otherwise typically
6549 * be considered wake keys. We filter them out here.
6551 * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
6552 * is always considered a wake key.
6554 private boolean isWakeKeyWhenScreenOff(int keyCode) {
6556 // ignore volume keys unless docked
6557 case KeyEvent.KEYCODE_VOLUME_UP:
6558 case KeyEvent.KEYCODE_VOLUME_DOWN:
6559 case KeyEvent.KEYCODE_VOLUME_MUTE:
6560 return mVolumeWakeScreen || mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
6562 // ignore media keys
6563 case KeyEvent.KEYCODE_MUTE:
6564 case KeyEvent.KEYCODE_HEADSETHOOK:
6565 case KeyEvent.KEYCODE_MEDIA_PLAY:
6566 case KeyEvent.KEYCODE_MEDIA_PAUSE:
6567 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6568 case KeyEvent.KEYCODE_MEDIA_STOP:
6569 case KeyEvent.KEYCODE_MEDIA_NEXT:
6570 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6571 case KeyEvent.KEYCODE_MEDIA_REWIND:
6572 case KeyEvent.KEYCODE_MEDIA_RECORD:
6573 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6574 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
6577 case KeyEvent.KEYCODE_BACK:
6578 return mBackWakeScreen;
6579 case KeyEvent.KEYCODE_MENU:
6580 return mMenuWakeScreen;
6581 case KeyEvent.KEYCODE_ASSIST:
6582 return mAssistWakeScreen;
6583 case KeyEvent.KEYCODE_APP_SWITCH:
6584 return mAppSwitchWakeScreen;
6585 case KeyEvent.KEYCODE_CAMERA:
6586 case KeyEvent.KEYCODE_FOCUS:
6587 return mCameraWakeScreen;
6593 /** {@inheritDoc} */
6595 public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
6596 if ((policyFlags & FLAG_WAKE) != 0) {
6597 if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
6598 "android.policy:MOTION")) {
6603 if (shouldDispatchInputWhenNonInteractive()) {
6604 return ACTION_PASS_TO_USER;
6607 // If we have not passed the action up and we are in theater mode without dreaming,
6608 // there will be no dream to intercept the touch and wake into ambient. The device should
6609 // wake up in this case.
6610 if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
6611 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
6612 "android.policy:MOTION");
6618 private boolean shouldDispatchInputWhenNonInteractive() {
6619 final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
6621 if (displayOff && !mHasFeatureWatch) {
6625 // Send events to keyguard while the screen is on and it's showing.
6626 if (isKeyguardShowingAndNotOccluded() && !displayOff) {
6630 // Send events to a dozing dream even if the screen is off since the dream
6631 // is in control of the state of the screen.
6632 IDreamManager dreamManager = getDreamManager();
6635 if (dreamManager != null && dreamManager.isDreaming() && !dreamManager.isDozing()) {
6638 } catch (RemoteException e) {
6639 Slog.e(TAG, "RemoteException when checking if dreaming", e);
6642 // Otherwise, consume events since the user can't see what is being
6647 private void dispatchDirectAudioEvent(KeyEvent event) {
6648 if (event.getAction() != KeyEvent.ACTION_DOWN) {
6651 int keyCode = event.getKeyCode();
6652 int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
6653 | AudioManager.FLAG_FROM_KEY;
6654 String pkgName = mContext.getOpPackageName();
6656 case KeyEvent.KEYCODE_VOLUME_UP:
6658 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
6659 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6660 } catch (RemoteException e) {
6661 Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
6664 case KeyEvent.KEYCODE_VOLUME_DOWN:
6666 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
6667 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6668 } catch (RemoteException e) {
6669 Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
6672 case KeyEvent.KEYCODE_VOLUME_MUTE:
6674 if (event.getRepeatCount() == 0) {
6675 getAudioService().adjustSuggestedStreamVolume(
6676 AudioManager.ADJUST_TOGGLE_MUTE,
6677 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6679 } catch (RemoteException e) {
6680 Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
6686 void dispatchMediaKeyWithWakeLock(KeyEvent event) {
6688 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
6691 if (mHavePendingMediaKeyRepeatWithWakeLock) {
6693 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
6696 mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
6697 mHavePendingMediaKeyRepeatWithWakeLock = false;
6698 mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
6701 dispatchMediaKeyWithWakeLockToAudioService(event);
6703 if (event.getAction() == KeyEvent.ACTION_DOWN
6704 && event.getRepeatCount() == 0) {
6705 mHavePendingMediaKeyRepeatWithWakeLock = true;
6707 Message msg = mHandler.obtainMessage(
6708 MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
6709 msg.setAsynchronous(true);
6710 mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
6712 mBroadcastWakeLock.release();
6716 void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
6717 mHavePendingMediaKeyRepeatWithWakeLock = false;
6719 KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
6720 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6722 Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
6725 dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
6726 mBroadcastWakeLock.release();
6729 void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
6730 if (ActivityManagerNative.isSystemReady()) {
6731 MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
6735 void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
6736 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
6737 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
6740 dic.exitIdle("voice-search");
6741 } catch (RemoteException e) {
6744 Intent voiceIntent =
6745 new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
6746 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
6747 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
6748 mBroadcastWakeLock.release();
6751 BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
6753 public void onReceive(Context context, Intent intent) {
6754 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
6755 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6756 Intent.EXTRA_DOCK_STATE_UNDOCKED);
6759 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
6760 ServiceManager.getService(Context.UI_MODE_SERVICE));
6761 mUiMode = uiModeService.getCurrentModeType();
6762 } catch (RemoteException e) {
6765 updateRotation(true);
6766 synchronized (mLock) {
6767 updateOrientationListenerLp();
6772 BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
6774 public void onReceive(Context context, Intent intent) {
6775 if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
6776 if (mKeyguardDelegate != null) {
6777 mKeyguardDelegate.onDreamingStarted();
6779 } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
6780 if (mKeyguardDelegate != null) {
6781 mKeyguardDelegate.onDreamingStopped();
6787 BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
6789 public void onReceive(Context context, Intent intent) {
6790 if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
6791 // tickle the settings observer: this first ensures that we're
6792 // observing the relevant settings for the newly-active user,
6793 // and then updates our own bookkeeping based on the now-
6795 mSettingsObserver.onChange(false);
6797 if (mGlobalActions != null) {
6798 mGlobalActions.updatePowerMenuActions();
6801 // force a re-application of focused window sysui visibility.
6802 // the window may never have been shown for this user
6803 // e.g. the keyguard when going through the new-user setup flow
6804 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6805 mLastSystemUiFlags = 0;
6806 updateSystemUiVisibilityLw();
6812 private final Runnable mHiddenNavPanic = new Runnable() {
6815 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6816 if (!isUserSetupComplete()) {
6817 // Swipe-up for navigation bar is disabled during setup
6820 mPendingPanicGestureUptime = SystemClock.uptimeMillis();
6821 mNavigationBarController.showTransient();
6826 private void requestTransientBars(WindowState swipeTarget) {
6827 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6828 if (!isUserSetupComplete()) {
6829 // Swipe-up for navigation bar is disabled during setup
6832 boolean sb = mStatusBarController.checkShowTransientBarLw();
6833 boolean nb = mNavigationBarController.checkShowTransientBarLw();
6835 // Don't show status bar when swiping on already visible navigation bar
6836 if (!nb && swipeTarget == mNavigationBar) {
6837 if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
6840 if (sb) mStatusBarController.showTransient();
6841 if (nb) mNavigationBarController.showTransient();
6842 mImmersiveModeConfirmation.confirmCurrentPrompt();
6843 updateSystemUiVisibilityLw();
6849 BroadcastReceiver mWifiDisplayReceiver = new BroadcastReceiver() {
6850 public void onReceive(Context context, Intent intent) {
6851 String action = intent.getAction();
6852 if (action.equals(ACTION_WIFI_DISPLAY_VIDEO)) {
6853 int state = intent.getIntExtra("state", 0);
6855 mWifiDisplayConnected = true;
6857 mWifiDisplayConnected = false;
6859 mWifiDisplayCustomRotation =
6860 intent.getIntExtra("wfd_UIBC_rot", -1);
6861 updateRotation(true);
6866 // Called on the PowerManager's Notifier thread.
6868 public void startedGoingToSleep(int why) {
6869 if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
6870 mCameraGestureTriggeredDuringGoingToSleep = false;
6871 mGoingToSleep = true;
6872 if (mKeyguardDelegate != null) {
6873 mKeyguardDelegate.onStartedGoingToSleep(why);
6877 // Called on the PowerManager's Notifier thread.
6879 public void finishedGoingToSleep(int why) {
6880 EventLog.writeEvent(70000, 0);
6881 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
6882 MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
6884 mGoingToSleep = false;
6886 // We must get this work done here because the power manager will drop
6887 // the wake lock and let the system suspend once this function returns.
6888 synchronized (mLock) {
6890 updateWakeGestureListenerLp();
6891 updateOrientationListenerLp();
6892 updateLockScreenTimeout();
6894 if (mKeyguardDelegate != null) {
6895 mKeyguardDelegate.onFinishedGoingToSleep(why,
6896 mCameraGestureTriggeredDuringGoingToSleep);
6898 mCameraGestureTriggeredDuringGoingToSleep = false;
6901 // Called on the PowerManager's Notifier thread.
6903 public void startedWakingUp() {
6904 EventLog.writeEvent(70000, 1);
6905 if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
6907 // Since goToSleep performs these functions synchronously, we must
6908 // do the same here. We cannot post this work to a handler because
6909 // that might cause it to become reordered with respect to what
6910 // may happen in a future call to goToSleep.
6911 synchronized (mLock) {
6914 updateWakeGestureListenerLp();
6915 updateOrientationListenerLp();
6916 updateLockScreenTimeout();
6919 if (mKeyguardDelegate != null) {
6920 mKeyguardDelegate.onStartedWakingUp();
6924 // Called on the PowerManager's Notifier thread.
6926 public void finishedWakingUp() {
6927 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
6930 private void wakeUpFromPowerKey(long eventTime) {
6931 wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
6934 private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
6935 final boolean theaterModeEnabled = isTheaterModeEnabled();
6936 if (!wakeInTheaterMode && theaterModeEnabled) {
6940 if (theaterModeEnabled) {
6941 Settings.Global.putInt(mContext.getContentResolver(),
6942 Settings.Global.THEATER_MODE_ON, 0);
6945 mPowerManager.wakeUp(wakeTime, reason);
6949 private void finishKeyguardDrawn() {
6950 synchronized (mLock) {
6951 if (!mScreenOnEarly || mKeyguardDrawComplete) {
6952 return; // We are not awake yet or we have already informed of this event.
6955 mKeyguardDrawComplete = true;
6956 if (mKeyguardDelegate != null) {
6957 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6959 mWindowManagerDrawComplete = false;
6962 // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
6963 // as well as enabling the orientation change logic/sensor.
6964 mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
6965 WAITING_FOR_DRAWN_TIMEOUT);
6968 // Called on the DisplayManager's DisplayPowerController thread.
6970 public void screenTurnedOff() {
6971 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
6973 updateScreenOffSleepToken(true);
6974 synchronized (mLock) {
6975 mScreenOnEarly = false;
6976 mScreenOnFully = false;
6977 mKeyguardDrawComplete = false;
6978 mWindowManagerDrawComplete = false;
6979 mScreenOnListener = null;
6980 updateOrientationListenerLp();
6982 if (mKeyguardDelegate != null) {
6983 mKeyguardDelegate.onScreenTurnedOff();
6988 // Called on the DisplayManager's DisplayPowerController thread.
6990 public void screenTurningOn(final ScreenOnListener screenOnListener) {
6991 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
6993 updateScreenOffSleepToken(false);
6994 synchronized (mLock) {
6995 mScreenOnEarly = true;
6996 mScreenOnFully = false;
6997 mKeyguardDrawComplete = false;
6998 mWindowManagerDrawComplete = false;
6999 mScreenOnListener = screenOnListener;
7001 if (mKeyguardDelegate != null) {
7002 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
7003 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
7004 mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
7006 if (DEBUG_WAKEUP) Slog.d(TAG,
7007 "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
7008 finishKeyguardDrawn();
7013 // Called on the DisplayManager's DisplayPowerController thread.
7015 public void screenTurnedOn() {
7016 synchronized (mLock) {
7017 if (mKeyguardDelegate != null) {
7018 mKeyguardDelegate.onScreenTurnedOn();
7023 private void finishWindowsDrawn() {
7024 synchronized (mLock) {
7025 if (!mScreenOnEarly || mWindowManagerDrawComplete) {
7026 return; // Screen is not turned on or we did already handle this case earlier.
7029 mWindowManagerDrawComplete = true;
7032 finishScreenTurningOn();
7035 private void finishScreenTurningOn() {
7036 synchronized (mLock) {
7037 // We have just finished drawing screen content. Since the orientation listener
7038 // gets only installed when all windows are drawn, we try to install it again.
7039 updateOrientationListenerLp();
7041 final ScreenOnListener listener;
7042 final boolean enableScreen;
7043 synchronized (mLock) {
7044 if (DEBUG_WAKEUP) Slog.d(TAG,
7045 "finishScreenTurningOn: mAwake=" + mAwake
7046 + ", mScreenOnEarly=" + mScreenOnEarly
7047 + ", mScreenOnFully=" + mScreenOnFully
7048 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
7049 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
7051 if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
7052 || (mAwake && !mKeyguardDrawComplete)) {
7053 return; // spurious or not ready yet
7056 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
7057 listener = mScreenOnListener;
7058 mScreenOnListener = null;
7059 mScreenOnFully = true;
7061 // Remember the first time we draw the keyguard so we know when we're done with
7062 // the main part of booting and can enable the screen and hide boot messages.
7063 if (!mKeyguardDrawnOnce && mAwake) {
7064 mKeyguardDrawnOnce = true;
7065 enableScreen = true;
7066 if (mBootMessageNeedsHiding) {
7067 mBootMessageNeedsHiding = false;
7071 enableScreen = false;
7075 if (listener != null) {
7076 listener.onScreenOn();
7081 mWindowManager.enableScreenIfNeeded();
7082 } catch (RemoteException unhandled) {
7087 private void handleHideBootMessage() {
7088 synchronized (mLock) {
7089 if (!mKeyguardDrawnOnce) {
7090 mBootMessageNeedsHiding = true;
7091 return; // keyguard hasn't drawn the first time yet, not done booting
7095 if (mBootMsgDialog != null) {
7096 if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
7097 mBootMsgDialog.dismiss();
7098 mBootMsgDialog = null;
7103 public boolean isScreenOn() {
7104 return mScreenOnFully;
7107 /** {@inheritDoc} */
7109 public void enableKeyguard(boolean enabled) {
7110 if (mKeyguardDelegate != null) {
7111 mKeyguardDelegate.setKeyguardEnabled(enabled);
7115 /** {@inheritDoc} */
7117 public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
7118 if (mKeyguardDelegate != null) {
7119 mKeyguardDelegate.verifyUnlock(callback);
7123 private boolean isKeyguardShowingAndNotOccluded() {
7124 if (mKeyguardDelegate == null) return false;
7125 return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
7128 /** {@inheritDoc} */
7130 public boolean isKeyguardLocked() {
7131 return keyguardOn();
7134 /** {@inheritDoc} */
7136 public boolean isKeyguardSecure(int userId) {
7137 if (mKeyguardDelegate == null) return false;
7138 return mKeyguardDelegate.isSecure(userId);
7141 /** {@inheritDoc} */
7143 public boolean isKeyguardShowingOrOccluded() {
7144 return mKeyguardDelegate == null ? false : mKeyguardDelegate.isShowing();
7147 /** {@inheritDoc} */
7149 public boolean inKeyguardRestrictedKeyInputMode() {
7150 if (mKeyguardDelegate == null) return false;
7151 return mKeyguardDelegate.isInputRestricted();
7155 public void dismissKeyguardLw() {
7156 if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
7157 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
7158 mHandler.post(new Runnable() {
7161 // ask the keyguard to prompt the user to authenticate if necessary
7162 mKeyguardDelegate.dismiss();
7169 public void notifyActivityDrawnForKeyguardLw() {
7170 if (mKeyguardDelegate != null) {
7171 mHandler.post(new Runnable() {
7174 mKeyguardDelegate.onActivityDrawn();
7181 public boolean isKeyguardDrawnLw() {
7182 synchronized (mLock) {
7183 return mKeyguardDrawnOnce;
7188 public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
7189 if (mKeyguardDelegate != null) {
7190 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
7191 mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
7196 public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
7198 outInsets.setEmpty();
7200 // Navigation bar and status bar.
7201 getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
7202 if (mStatusBar != null) {
7203 outInsets.top = mStatusBarHeight;
7208 public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
7210 outInsets.setEmpty();
7212 // Only navigation bar
7213 if (mNavigationBar != null) {
7214 if (isNavigationBarOnBottom(displayWidth, displayHeight)) {
7215 outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
7217 outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
7223 public boolean isNavBarForcedShownLw(WindowState windowState) {
7224 return mForceShowSystemBars;
7228 public boolean isDockSideAllowed(int dockSide) {
7230 // We do not allow all dock sides at which the navigation bar touches the docked stack.
7231 if (!mNavigationBarCanMove) {
7232 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT;
7234 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT;
7238 void sendCloseSystemWindows() {
7239 PhoneWindow.sendCloseSystemWindows(mContext, null);
7242 void sendCloseSystemWindows(String reason) {
7243 PhoneWindow.sendCloseSystemWindows(mContext, reason);
7247 public int rotationForOrientationLw(int orientation, int lastRotation) {
7249 Slog.v(TAG, "rotationForOrientationLw(orient="
7250 + orientation + ", last=" + lastRotation
7251 + "); user=" + mUserRotation + " "
7252 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
7253 ? "USER_ROTATION_LOCKED" : "")
7257 if (mForceDefaultOrientation) {
7258 return Surface.ROTATION_0;
7261 synchronized (mLock) {
7262 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
7263 if (sensorRotation < 0) {
7264 sensorRotation = lastRotation;
7267 final int preferredRotation;
7268 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
7269 // Ignore sensor when lid switch is open and rotation is forced.
7270 preferredRotation = mLidOpenRotation;
7271 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
7272 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
7273 // Ignore sensor when in car dock unless explicitly enabled.
7274 // This case can override the behavior of NOSENSOR, and can also
7275 // enable 180 degree rotation while docked.
7276 preferredRotation = mCarDockEnablesAccelerometer
7277 ? sensorRotation : mCarDockRotation;
7278 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7279 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
7280 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
7281 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
7282 // Ignore sensor when in desk dock unless explicitly enabled.
7283 // This case can override the behavior of NOSENSOR, and can also
7284 // enable 180 degree rotation while docked.
7285 preferredRotation = mDeskDockEnablesAccelerometer
7286 ? sensorRotation : mDeskDockRotation;
7287 } else if ((mHdmiPlugged || mWifiDisplayConnected) && mDemoHdmiRotationLock) {
7288 // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
7289 // Note that the dock orientation overrides the HDMI orientation.
7290 preferredRotation = mDemoHdmiRotation;
7291 } else if (mWifiDisplayConnected && (mWifiDisplayCustomRotation > -1)) {
7292 // Ignore sensor when WFD is active and UIBC rotation is enabled
7293 preferredRotation = mWifiDisplayCustomRotation;
7294 } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
7295 && mUndockedHdmiRotation >= 0) {
7296 // Ignore sensor when plugged into HDMI and an undocked orientation has
7297 // been specified in the configuration (only for legacy devices without
7298 // full multi-display support).
7299 // Note that the dock orientation overrides the HDMI orientation.
7300 preferredRotation = mUndockedHdmiRotation;
7301 } else if (mDemoRotationLock) {
7302 // Ignore sensor when demo rotation lock is enabled.
7303 // Note that the dock orientation and HDMI rotation lock override this.
7304 preferredRotation = mDemoRotation;
7305 } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
7306 // Application just wants to remain locked in the last rotation.
7307 preferredRotation = lastRotation;
7308 } else if (!mSupportAutoRotation) {
7309 // If we don't support auto-rotation then bail out here and ignore
7310 // the sensor and any rotation lock settings.
7311 preferredRotation = -1;
7312 } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
7313 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
7314 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
7315 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
7316 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
7317 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
7318 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
7319 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
7320 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
7321 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
7322 // Otherwise, use sensor only if requested by the application or enabled
7323 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR.
7324 if (mAllowAllRotations < 0) {
7325 // Can't read this during init() because the context doesn't
7326 // have display metrics at that time so we cannot determine
7327 // tablet vs. phone then.
7328 mAllowAllRotations = mContext.getResources().getBoolean(
7329 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
7331 boolean allowed = true;
7332 if (orientation != ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
7333 && orientation != ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
7334 allowed = RotationPolicy.isRotationAllowed(sensorRotation,
7335 mUserRotationAngles, mAllowAllRotations != 0);
7338 preferredRotation = sensorRotation;
7340 preferredRotation = lastRotation;
7342 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
7343 && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
7344 // Apply rotation lock. Does not apply to NOSENSOR.
7345 // The idea is that the user rotation expresses a weak preference for the direction
7346 // of gravity and as NOSENSOR is never affected by gravity, then neither should
7347 // NOSENSOR be affected by rotation lock (although it will be affected by docks).
7348 preferredRotation = mUserRotation;
7350 // No overriding preference.
7351 // We will do exactly what the application asked us to do.
7352 preferredRotation = -1;
7355 switch (orientation) {
7356 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
7357 // Return portrait unless overridden.
7358 if (isAnyPortrait(preferredRotation)) {
7359 return preferredRotation;
7361 return mPortraitRotation;
7363 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
7364 // Return landscape unless overridden.
7365 if (isLandscapeOrSeascape(preferredRotation)) {
7366 return preferredRotation;
7368 return mLandscapeRotation;
7370 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
7371 // Return reverse portrait unless overridden.
7372 if (isAnyPortrait(preferredRotation)) {
7373 return preferredRotation;
7375 return mUpsideDownRotation;
7377 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
7378 // Return seascape unless overridden.
7379 if (isLandscapeOrSeascape(preferredRotation)) {
7380 return preferredRotation;
7382 return mSeascapeRotation;
7384 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
7385 case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
7386 // Return either landscape rotation.
7387 if (isLandscapeOrSeascape(preferredRotation)) {
7388 return preferredRotation;
7390 if (isLandscapeOrSeascape(lastRotation)) {
7391 return lastRotation;
7393 return mLandscapeRotation;
7395 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
7396 case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
7397 // Return either portrait rotation.
7398 if (isAnyPortrait(preferredRotation)) {
7399 return preferredRotation;
7401 if (isAnyPortrait(lastRotation)) {
7402 return lastRotation;
7404 return mPortraitRotation;
7407 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
7408 // just return the preferred orientation we already calculated.
7409 if (preferredRotation >= 0) {
7410 return preferredRotation;
7412 return Surface.ROTATION_0;
7418 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
7419 switch (orientation) {
7420 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
7421 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
7422 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
7423 return isAnyPortrait(rotation);
7425 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
7426 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
7427 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
7428 return isLandscapeOrSeascape(rotation);
7436 public void setRotationLw(int rotation) {
7437 mOrientationListener.setCurrentRotation(rotation);
7440 private boolean isLandscapeOrSeascape(int rotation) {
7441 return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
7444 private boolean isAnyPortrait(int rotation) {
7445 return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
7449 public int getUserRotationMode() {
7450 return Settings.System.getIntForUser(mContext.getContentResolver(),
7451 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
7452 WindowManagerPolicy.USER_ROTATION_FREE :
7453 WindowManagerPolicy.USER_ROTATION_LOCKED;
7456 // User rotation: to be used when all else fails in assigning an orientation to the device
7458 public void setUserRotationMode(int mode, int rot) {
7459 ContentResolver res = mContext.getContentResolver();
7461 // mUserRotationMode and mUserRotation will be assigned by the content observer
7462 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
7463 Settings.System.putIntForUser(res,
7464 Settings.System.USER_ROTATION,
7466 UserHandle.USER_CURRENT);
7467 Settings.System.putIntForUser(res,
7468 Settings.System.ACCELEROMETER_ROTATION,
7470 UserHandle.USER_CURRENT);
7472 Settings.System.putIntForUser(res,
7473 Settings.System.ACCELEROMETER_ROTATION,
7475 UserHandle.USER_CURRENT);
7480 public void setSafeMode(boolean safeMode) {
7481 mSafeMode = safeMode;
7482 performHapticFeedbackLw(null, safeMode
7483 ? HapticFeedbackConstants.SAFE_MODE_ENABLED
7484 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
7487 static long[] getLongIntArray(Resources r, int resid) {
7488 int[] ar = r.getIntArray(resid);
7492 long[] out = new long[ar.length];
7493 for (int i=0; i<ar.length; i++) {
7499 /** {@inheritDoc} */
7501 public void systemReady() {
7502 mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
7503 mKeyguardDelegate.onSystemReady();
7505 mCMHardware = CMHardwareManager.getInstance(mContext);
7506 // Ensure observe happens in systemReady() since we need
7507 // CMHardwareService to be up and running
7508 mSettingsObserver.observe();
7510 readCameraLensCoverState();
7512 boolean bindKeyguardNow;
7513 synchronized (mLock) {
7514 updateOrientationListenerLp();
7515 mSystemReady = true;
7516 mHandler.post(new Runnable() {
7523 bindKeyguardNow = mDeferBindKeyguard;
7524 if (bindKeyguardNow) {
7525 // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now.
7526 mDeferBindKeyguard = false;
7530 if (bindKeyguardNow) {
7531 mKeyguardDelegate.bindService(mContext);
7532 mKeyguardDelegate.onBootCompleted();
7534 mSystemGestures.systemReady();
7535 mImmersiveModeConfirmation.systemReady();
7538 /** {@inheritDoc} */
7540 public void systemBooted() {
7541 boolean bindKeyguardNow = false;
7542 synchronized (mLock) {
7543 // Time to bind Keyguard; take care to only bind it once, either here if ready or
7544 // in systemReady if not.
7545 if (mKeyguardDelegate != null) {
7546 bindKeyguardNow = true;
7548 // Because mKeyguardDelegate is null, we know that the synchronized block in
7549 // systemReady didn't run yet and setting this will actually have an effect.
7550 mDeferBindKeyguard = true;
7553 if (bindKeyguardNow) {
7554 mKeyguardDelegate.bindService(mContext);
7555 mKeyguardDelegate.onBootCompleted();
7557 synchronized (mLock) {
7558 mSystemBooted = true;
7561 screenTurningOn(null);
7565 ProgressDialog mBootMsgDialog = null;
7567 /** {@inheritDoc} */
7569 public void showBootMessage(final CharSequence msg, final boolean always) {
7570 mHandler.post(new Runnable() {
7571 @Override public void run() {
7572 if (mBootMsgDialog == null) {
7574 if (mHasFeatureWatch) {
7575 theme = com.android.internal.R.style.Theme_Micro_Dialog_Alert;
7576 } else if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) {
7577 theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
7582 mBootMsgDialog = new ProgressDialog(mContext, theme) {
7583 // This dialog will consume all events coming in to
7584 // it, to avoid it trying to do things too early in boot.
7585 @Override public boolean dispatchKeyEvent(KeyEvent event) {
7588 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7591 @Override public boolean dispatchTouchEvent(MotionEvent ev) {
7594 @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
7597 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
7600 @Override public boolean dispatchPopulateAccessibilityEvent(
7601 AccessibilityEvent event) {
7605 if (mContext.getPackageManager().isUpgrade()) {
7606 mBootMsgDialog.setTitle(R.string.android_upgrading_title);
7608 mBootMsgDialog.setTitle(R.string.android_start_title);
7610 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
7611 mBootMsgDialog.setIndeterminate(true);
7612 mBootMsgDialog.getWindow().setType(
7613 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
7614 mBootMsgDialog.getWindow().addFlags(
7615 WindowManager.LayoutParams.FLAG_DIM_BEHIND
7616 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
7617 mBootMsgDialog.getWindow().setDimAmount(1);
7618 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
7619 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
7620 mBootMsgDialog.getWindow().setAttributes(lp);
7621 mBootMsgDialog.setCancelable(false);
7622 mBootMsgDialog.show();
7624 mBootMsgDialog.setMessage(msg);
7629 /** {@inheritDoc} */
7631 public void hideBootMessages() {
7632 mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
7635 /** {@inheritDoc} */
7637 public void userActivity() {
7638 // ***************************************
7639 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
7640 // ***************************************
7641 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
7642 // WITH ITS LOCKS HELD.
7644 // This code must be VERY careful about the locks
7646 // In fact, the current code acquires way too many,
7647 // and probably has lurking deadlocks.
7649 synchronized (mScreenLockTimeout) {
7650 if (mLockScreenTimerActive) {
7652 mHandler.removeCallbacks(mScreenLockTimeout);
7653 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7658 class ScreenLockTimeout implements Runnable {
7663 synchronized (this) {
7664 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
7665 if (mKeyguardDelegate != null) {
7666 mKeyguardDelegate.doKeyguardTimeout(options);
7668 mLockScreenTimerActive = false;
7673 public void setLockOptions(Bundle options) {
7674 this.options = options;
7678 ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
7681 public void lockNow(Bundle options) {
7682 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
7683 mHandler.removeCallbacks(mScreenLockTimeout);
7684 if (options != null) {
7685 // In case multiple calls are made to lockNow, we don't wipe out the options
7686 // until the runnable actually executes.
7687 mScreenLockTimeout.setLockOptions(options);
7689 mHandler.post(mScreenLockTimeout);
7692 private void updateLockScreenTimeout() {
7693 synchronized (mScreenLockTimeout) {
7694 boolean enable = (mAllowLockscreenWhenOn && mAwake &&
7695 mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
7696 if (mLockScreenTimerActive != enable) {
7698 if (localLOGV) Log.v(TAG, "setting lockscreen timer");
7699 mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
7700 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7702 if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
7703 mHandler.removeCallbacks(mScreenLockTimeout);
7705 mLockScreenTimerActive = enable;
7710 private void updateDreamingSleepToken(boolean acquire) {
7712 if (mDreamingSleepToken == null) {
7713 mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream");
7716 if (mDreamingSleepToken != null) {
7717 mDreamingSleepToken.release();
7718 mDreamingSleepToken = null;
7723 private void updateScreenOffSleepToken(boolean acquire) {
7725 if (mScreenOffSleepToken == null) {
7726 mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff");
7729 if (mScreenOffSleepToken != null) {
7730 mScreenOffSleepToken.release();
7731 mScreenOffSleepToken = null;
7736 /** {@inheritDoc} */
7738 public void enableScreenAfterBoot() {
7740 applyLidSwitchState();
7741 updateRotation(true);
7744 private void applyLidSwitchState() {
7745 mPowerManager.setKeyboardVisibility(isBuiltInKeyboardVisible());
7747 if (mLidState == LID_CLOSED && mLidControlsSleep) {
7748 mPowerManager.goToSleep(SystemClock.uptimeMillis(),
7749 PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
7750 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
7751 } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
7752 mWindowManagerFuncs.lockDeviceNow();
7755 synchronized (mLock) {
7756 updateWakeGestureListenerLp();
7760 void updateUiMode() {
7761 if (mUiModeManager == null) {
7762 mUiModeManager = IUiModeManager.Stub.asInterface(
7763 ServiceManager.getService(Context.UI_MODE_SERVICE));
7766 mUiMode = mUiModeManager.getCurrentModeType();
7767 } catch (RemoteException e) {
7771 void updateRotation(boolean alwaysSendConfiguration) {
7773 //set orientation on WindowManager
7774 mWindowManager.updateRotation(alwaysSendConfiguration, false);
7775 } catch (RemoteException e) {
7780 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
7782 //set orientation on WindowManager
7783 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
7784 } catch (RemoteException e) {
7790 * Return an Intent to launch the currently active dock app as home. Returns
7791 * null if the standard home should be launched, which is the case if any of the following is
7794 * <li>The device is not in either car mode or desk mode
7795 * <li>The device is in car mode but mEnableCarDockHomeCapture is false
7796 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
7797 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
7798 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
7800 * @return A dock intent.
7802 Intent createHomeDockIntent() {
7803 Intent intent = null;
7805 // What home does is based on the mode, not the dock state. That
7806 // is, when in car mode you should be taken to car home regardless
7807 // of whether we are actually in a car dock.
7808 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
7809 if (mEnableCarDockHomeCapture) {
7810 intent = mCarDockIntent;
7812 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
7813 if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
7814 intent = mDeskDockIntent;
7816 } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
7817 && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7818 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
7819 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
7820 // Always launch dock home from home when watch is docked, if it exists.
7821 intent = mDeskDockIntent;
7824 if (intent == null) {
7828 ActivityInfo ai = null;
7829 ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
7831 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
7834 ai = info.activityInfo;
7837 && ai.metaData != null
7838 && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
7839 intent = new Intent(intent);
7840 intent.setClassName(ai.packageName, ai.name);
7847 void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
7848 if (awakenFromDreams) {
7852 Intent dock = createHomeDockIntent();
7856 dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7858 startActivityAsUser(dock, UserHandle.CURRENT);
7860 } catch (ActivityNotFoundException e) {
7867 intent = new Intent(mHomeIntent);
7868 intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7870 intent = mHomeIntent;
7873 startActivityAsUser(intent, UserHandle.CURRENT);
7877 * goes to the home screen
7878 * @return whether it did anything
7881 if (!isUserSetupComplete()) {
7882 Slog.i(TAG, "Not going home because user setup is in progress.");
7886 // This code always brings home to the front.
7888 ActivityManagerNative.getDefault().stopAppSwitches();
7889 } catch (RemoteException e) {
7891 sendCloseSystemWindows();
7892 startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
7894 // This code brings home to the front or, if it is already
7895 // at the front, puts the device to sleep.
7897 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
7898 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
7899 Log.d(TAG, "UTS-TEST-MODE");
7901 ActivityManagerNative.getDefault().stopAppSwitches();
7902 sendCloseSystemWindows();
7903 Intent dock = createHomeDockIntent();
7905 int result = ActivityManagerNative.getDefault()
7906 .startActivityAsUser(null, null, dock,
7907 dock.resolveTypeIfNeeded(mContext.getContentResolver()),
7909 ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7910 null, null, UserHandle.USER_CURRENT);
7911 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7916 int result = ActivityManagerNative.getDefault()
7917 .startActivityAsUser(null, null, mHomeIntent,
7918 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
7920 ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7921 null, null, UserHandle.USER_CURRENT);
7922 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7925 } catch (RemoteException ex) {
7926 // bummer, the activity manager, which is in this process, is dead
7933 public void setCurrentOrientationLw(int newOrientation) {
7934 synchronized (mLock) {
7935 if (newOrientation != mCurrentAppOrientation) {
7936 mCurrentAppOrientation = newOrientation;
7937 updateOrientationListenerLp();
7942 private void performAuditoryFeedbackForAccessibilityIfNeed() {
7943 if (!isGlobalAccessibilityGestureEnabled()) {
7946 AudioManager audioManager = (AudioManager) mContext.getSystemService(
7947 Context.AUDIO_SERVICE);
7948 if (audioManager.isSilentMode()) {
7951 Ringtone ringTone = RingtoneManager.getRingtone(mContext,
7952 Settings.System.DEFAULT_NOTIFICATION_URI);
7953 ringTone.setStreamType(AudioManager.STREAM_MUSIC);
7957 private boolean isTheaterModeEnabled() {
7958 return Settings.Global.getInt(mContext.getContentResolver(),
7959 Settings.Global.THEATER_MODE_ON, 0) == 1;
7962 private boolean isGlobalAccessibilityGestureEnabled() {
7963 return Settings.Global.getInt(mContext.getContentResolver(),
7964 Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1;
7968 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
7969 if (!mVibrator.hasVibrator()) {
7972 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
7973 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
7974 if (hapticsDisabled && !always) {
7977 long[] pattern = null;
7979 case HapticFeedbackConstants.LONG_PRESS:
7980 pattern = mLongPressVibePattern;
7982 case HapticFeedbackConstants.VIRTUAL_KEY:
7983 pattern = mVirtualKeyVibePattern;
7985 case HapticFeedbackConstants.KEYBOARD_TAP:
7986 pattern = mKeyboardTapVibePattern;
7988 case HapticFeedbackConstants.CLOCK_TICK:
7989 pattern = mClockTickVibePattern;
7991 case HapticFeedbackConstants.CALENDAR_DATE:
7992 pattern = mCalendarDateVibePattern;
7994 case HapticFeedbackConstants.SAFE_MODE_DISABLED:
7995 pattern = mSafeModeDisabledVibePattern;
7997 case HapticFeedbackConstants.SAFE_MODE_ENABLED:
7998 pattern = mSafeModeEnabledVibePattern;
8000 case HapticFeedbackConstants.CONTEXT_CLICK:
8001 pattern = mContextClickVibePattern;
8007 String owningPackage;
8009 owningUid = win.getOwningUid();
8010 owningPackage = win.getOwningPackage();
8012 owningUid = android.os.Process.myUid();
8013 owningPackage = mContext.getOpPackageName();
8015 if (pattern.length == 1) {
8016 // One-shot vibration
8017 mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES);
8019 // Pattern vibration
8020 mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES);
8026 public void keepScreenOnStartedLw() {
8030 public void keepScreenOnStoppedLw() {
8031 if (isKeyguardShowingAndNotOccluded()) {
8032 mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
8036 private int updateSystemUiVisibilityLw() {
8037 // If there is no window focused, there will be nobody to handle the events
8038 // anyway, so just hang on in whatever state we're in until things settle down.
8039 final WindowState win = mFocusedWindow != null ? mFocusedWindow
8040 : mTopFullscreenOpaqueWindowState;
8044 if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) {
8045 // We are updating at a point where the keyguard has gotten
8046 // focus, but we were last in a state where the top window is
8047 // hiding it. This is probably because the keyguard as been
8048 // shown while the top window was displayed, so we want to ignore
8049 // it here because this is just a very transient change and it
8050 // will quickly lose focus once it correctly gets hidden.
8054 int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
8055 & ~mResettingSystemUiFlags
8056 & ~mForceClearedSystemUiFlags;
8057 if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
8058 tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
8061 final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
8062 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
8063 final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
8064 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
8065 mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);
8066 mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);
8067 final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
8068 final int diff = visibility ^ mLastSystemUiFlags;
8069 final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
8070 final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
8071 final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
8072 if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
8073 && mFocusedApp == win.getAppToken()
8074 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
8075 && mLastDockedStackBounds.equals(mDockedStackBounds)) {
8078 mLastSystemUiFlags = visibility;
8079 mLastFullscreenStackSysUiFlags = fullscreenVisibility;
8080 mLastDockedStackSysUiFlags = dockedVisibility;
8081 mLastFocusNeedsMenu = needsMenu;
8082 mFocusedApp = win.getAppToken();
8083 final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
8084 final Rect dockedStackBounds = new Rect(mDockedStackBounds);
8085 mHandler.post(new Runnable() {
8088 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
8089 if (statusbar != null) {
8090 statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
8091 dockedVisibility, 0xffffffff, fullscreenStackBounds,
8092 dockedStackBounds, win.toString());
8093 statusbar.topAppWindowChanged(needsMenu);
8100 private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
8101 WindowState statusColorWin = isStatusBarKeyguard() && !mHideLockScreen
8105 if (statusColorWin != null) {
8106 if (statusColorWin == opaque) {
8107 // If the top fullscreen-or-dimming window is also the top fullscreen, respect
8109 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
8110 vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
8111 & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
8112 } else if (statusColorWin != null && statusColorWin.isDimming()) {
8113 // Otherwise if it's dimming, clear the light flag.
8114 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
8120 private boolean drawsSystemBarBackground(WindowState win) {
8121 return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
8124 private boolean forcesDrawStatusBarBackground(WindowState win) {
8125 return win == null || (win.getAttrs().privateFlags
8126 & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
8129 private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
8130 final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
8131 final boolean freeformStackVisible =
8132 mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
8133 final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
8135 // We need to force system bars when the docked stack is visible, when the freeform stack
8136 // is visible but also when we are resizing for the transitions when docked stack
8137 // visibility changes.
8138 mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
8139 final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
8141 // apply translucent bar vis flags
8142 WindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen
8144 : mTopFullscreenOpaqueWindowState;
8145 vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
8146 vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
8147 final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
8148 mTopDockedOpaqueWindowState, 0, 0);
8150 final boolean fullscreenDrawsStatusBarBackground =
8151 (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
8152 && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
8153 || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
8154 final boolean dockedDrawsStatusBarBackground =
8155 (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
8156 && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
8157 || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
8159 // prevent status bar interaction from clearing certain flags
8160 int type = win.getAttrs().type;
8161 boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
8162 if (statusBarHasFocus && !isStatusBarKeyguard()) {
8163 int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
8164 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
8165 | View.SYSTEM_UI_FLAG_IMMERSIVE
8166 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
8167 | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
8168 if (mHideLockScreen) {
8169 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
8171 vis = (vis & ~flags) | (oldVis & flags);
8174 if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
8175 vis |= View.STATUS_BAR_TRANSPARENT;
8176 vis &= ~View.STATUS_BAR_TRANSLUCENT;
8177 } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
8178 || forceOpaqueStatusBar) {
8179 vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
8182 vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
8184 // update status bar
8185 boolean immersiveSticky =
8186 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
8187 final boolean hideStatusBarWM =
8188 mTopFullscreenOpaqueWindowState != null
8189 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
8190 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
8191 final boolean hideStatusBarSysui =
8192 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
8193 final boolean hideNavBarSysui =
8194 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
8196 final boolean transientStatusBarAllowed = mStatusBar != null
8197 && (statusBarHasFocus || (!mForceShowSystemBars
8198 && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
8200 final boolean transientNavBarAllowed = mNavigationBar != null
8201 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
8203 final long now = SystemClock.uptimeMillis();
8204 final boolean pendingPanic = mPendingPanicGestureUptime != 0
8205 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
8206 if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
8207 // The user performed the panic gesture recently, we're about to hide the bars,
8208 // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
8209 mPendingPanicGestureUptime = 0;
8210 mStatusBarController.showTransient();
8211 mNavigationBarController.showTransient();
8214 final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
8215 && !transientStatusBarAllowed && hideStatusBarSysui;
8216 final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
8217 && !transientNavBarAllowed;
8218 if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
8219 // clear the clearable flags instead
8220 clearClearableFlagsLw();
8221 vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
8224 final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
8225 immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
8226 final boolean navAllowedHidden = immersive || immersiveSticky;
8228 if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType())
8229 > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) {
8230 // We can't hide the navbar from this window otherwise the input consumer would not get
8231 // the input events.
8232 vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
8235 vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
8237 // update navigation bar
8238 boolean oldImmersiveMode = isImmersiveMode(oldVis);
8239 boolean newImmersiveMode = isImmersiveMode(vis);
8240 if (win != null && oldImmersiveMode != newImmersiveMode) {
8241 final String pkg = win.getOwningPackage();
8242 mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
8243 isUserSetupComplete());
8246 vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
8252 * @return the current visibility flags with the nav-bar opacity related flags toggled based
8253 * on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
8255 private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
8256 boolean freeformStackVisible, boolean isDockedDividerResizing) {
8257 if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
8258 if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
8259 visibility = setNavBarOpaqueFlag(visibility);
8261 } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
8262 if (isDockedDividerResizing) {
8263 visibility = setNavBarOpaqueFlag(visibility);
8264 } else if (freeformStackVisible) {
8265 visibility = setNavBarTranslucentFlag(visibility);
8267 visibility = setNavBarOpaqueFlag(visibility);
8271 if (!areTranslucentBarsAllowed()) {
8272 visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
8277 private int setNavBarOpaqueFlag(int visibility) {
8278 return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
8281 private int setNavBarTranslucentFlag(int visibility) {
8282 visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
8283 return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
8286 private void clearClearableFlagsLw() {
8287 int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
8288 if (newVal != mResettingSystemUiFlags) {
8289 mResettingSystemUiFlags = newVal;
8290 mWindowManagerFuncs.reevaluateStatusBarVisibility();
8294 private boolean isImmersiveMode(int vis) {
8295 final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
8296 return mNavigationBar != null
8297 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
8298 && (vis & flags) != 0
8299 && canHideNavigationBar();
8303 * @return whether the navigation or status bar can be made translucent
8305 * This should return true unless touch exploration is not enabled or
8306 * R.boolean.config_enableTranslucentDecor is false.
8308 private boolean areTranslucentBarsAllowed() {
8309 return mTranslucentDecorEnabled;
8312 // Use this instead of checking config_showNavigationBar so that it can be consistently
8313 // overridden by qemu.hw.mainkeys in the emulator.
8315 public boolean hasNavigationBar() {
8316 return mHasNavigationBar || mDevForceNavbar;
8319 public boolean needsNavigationBar() {
8320 return mHasNavigationBar;
8324 public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
8325 mLastInputMethodWindow = ime;
8326 mLastInputMethodTargetWindow = target;
8330 public int getInputMethodWindowVisibleHeightLw() {
8331 return mDockBottom - mCurBottom;
8335 public void setCurrentUserLw(int newUserId) {
8336 mCurrentUserId = newUserId;
8337 if (mKeyguardDelegate != null) {
8338 mKeyguardDelegate.setCurrentUser(newUserId);
8340 StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
8341 if (statusBar != null) {
8342 statusBar.setCurrentUser(newUserId);
8344 setLastInputMethodWindowLw(null, null);
8348 public boolean canMagnifyWindow(int windowType) {
8349 switch (windowType) {
8350 case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
8351 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
8352 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
8353 case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
8361 public boolean isTopLevelWindow(int windowType) {
8362 if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
8363 && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
8364 return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
8370 public void dump(String prefix, PrintWriter pw, String[] args) {
8371 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
8372 pw.print(" mSystemReady="); pw.print(mSystemReady);
8373 pw.print(" mSystemBooted="); pw.println(mSystemBooted);
8374 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
8375 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
8376 pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
8377 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
8378 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
8379 || mForceClearedSystemUiFlags != 0) {
8380 pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
8381 pw.print(Integer.toHexString(mLastSystemUiFlags));
8382 pw.print(" mResettingSystemUiFlags=0x");
8383 pw.print(Integer.toHexString(mResettingSystemUiFlags));
8384 pw.print(" mForceClearedSystemUiFlags=0x");
8385 pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
8387 if (mLastFocusNeedsMenu) {
8388 pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
8389 pw.println(mLastFocusNeedsMenu);
8391 pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
8392 pw.println(mWakeGestureEnabledSetting);
8394 pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
8395 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
8396 pw.print(" mDockMode="); pw.print(mDockMode);
8397 pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
8398 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
8399 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
8400 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
8401 pw.print(" mUserRotation="); pw.print(mUserRotation);
8402 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
8403 pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
8404 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
8405 pw.print(mCarDockEnablesAccelerometer);
8406 pw.print(" mDeskDockEnablesAccelerometer=");
8407 pw.println(mDeskDockEnablesAccelerometer);
8408 pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
8409 pw.print(mLidKeyboardAccessibility);
8410 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
8411 pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
8412 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
8414 pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
8416 pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
8417 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
8419 pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
8420 pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
8421 pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
8422 pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
8423 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
8424 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
8425 pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
8426 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
8427 pw.print(prefix); pw.print("mOrientationSensorEnabled=");
8428 pw.println(mOrientationSensorEnabled);
8429 pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
8430 pw.print(","); pw.print(mOverscanScreenTop);
8431 pw.print(") "); pw.print(mOverscanScreenWidth);
8432 pw.print("x"); pw.println(mOverscanScreenHeight);
8433 if (mOverscanLeft != 0 || mOverscanTop != 0
8434 || mOverscanRight != 0 || mOverscanBottom != 0) {
8435 pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
8436 pw.print(" top="); pw.print(mOverscanTop);
8437 pw.print(" right="); pw.print(mOverscanRight);
8438 pw.print(" bottom="); pw.println(mOverscanBottom);
8440 pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
8441 pw.print(mRestrictedOverscanScreenLeft);
8442 pw.print(","); pw.print(mRestrictedOverscanScreenTop);
8443 pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
8444 pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
8445 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
8446 pw.print(","); pw.print(mUnrestrictedScreenTop);
8447 pw.print(") "); pw.print(mUnrestrictedScreenWidth);
8448 pw.print("x"); pw.println(mUnrestrictedScreenHeight);
8449 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
8450 pw.print(","); pw.print(mRestrictedScreenTop);
8451 pw.print(") "); pw.print(mRestrictedScreenWidth);
8452 pw.print("x"); pw.println(mRestrictedScreenHeight);
8453 pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
8454 pw.print(","); pw.print(mStableFullscreenTop);
8455 pw.print(")-("); pw.print(mStableFullscreenRight);
8456 pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
8457 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
8458 pw.print(","); pw.print(mStableTop);
8459 pw.print(")-("); pw.print(mStableRight);
8460 pw.print(","); pw.print(mStableBottom); pw.println(")");
8461 pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
8462 pw.print(","); pw.print(mSystemTop);
8463 pw.print(")-("); pw.print(mSystemRight);
8464 pw.print(","); pw.print(mSystemBottom); pw.println(")");
8465 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
8466 pw.print(","); pw.print(mCurTop);
8467 pw.print(")-("); pw.print(mCurRight);
8468 pw.print(","); pw.print(mCurBottom); pw.println(")");
8469 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
8470 pw.print(","); pw.print(mContentTop);
8471 pw.print(")-("); pw.print(mContentRight);
8472 pw.print(","); pw.print(mContentBottom); pw.println(")");
8473 pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft);
8474 pw.print(","); pw.print(mVoiceContentTop);
8475 pw.print(")-("); pw.print(mVoiceContentRight);
8476 pw.print(","); pw.print(mVoiceContentBottom); pw.println(")");
8477 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
8478 pw.print(","); pw.print(mDockTop);
8479 pw.print(")-("); pw.print(mDockRight);
8480 pw.print(","); pw.print(mDockBottom); pw.println(")");
8481 pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
8482 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
8483 pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen);
8484 pw.print(" mShowingDream="); pw.print(mShowingDream);
8485 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
8486 pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
8487 if (mLastInputMethodWindow != null) {
8488 pw.print(prefix); pw.print("mLastInputMethodWindow=");
8489 pw.println(mLastInputMethodWindow);
8491 if (mLastInputMethodTargetWindow != null) {
8492 pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
8493 pw.println(mLastInputMethodTargetWindow);
8495 if (mStatusBar != null) {
8496 pw.print(prefix); pw.print("mStatusBar=");
8497 pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
8498 pw.println(isStatusBarKeyguard());
8500 if (mNavigationBar != null) {
8501 pw.print(prefix); pw.print("mNavigationBar=");
8502 pw.println(mNavigationBar);
8504 if (mFocusedWindow != null) {
8505 pw.print(prefix); pw.print("mFocusedWindow=");
8506 pw.println(mFocusedWindow);
8508 if (mFocusedApp != null) {
8509 pw.print(prefix); pw.print("mFocusedApp=");
8510 pw.println(mFocusedApp);
8512 if (mWinDismissingKeyguard != null) {
8513 pw.print(prefix); pw.print("mWinDismissingKeyguard=");
8514 pw.println(mWinDismissingKeyguard);
8516 if (mTopFullscreenOpaqueWindowState != null) {
8517 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
8518 pw.println(mTopFullscreenOpaqueWindowState);
8520 if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
8521 pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
8522 pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
8524 if (mForcingShowNavBar) {
8525 pw.print(prefix); pw.print("mForcingShowNavBar=");
8526 pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
8527 pw.println(mForcingShowNavBarLayer);
8529 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
8530 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
8531 pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
8532 pw.print(" mForceStatusBarFromKeyguard=");
8533 pw.println(mForceStatusBarFromKeyguard);
8534 pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
8535 pw.print(" mWinDismissingKeyguard="); pw.print(mWinDismissingKeyguard);
8536 pw.print(" mHomePressed="); pw.println(mHomePressed);
8537 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
8538 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
8539 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
8540 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
8541 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
8542 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
8543 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
8544 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
8545 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
8546 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
8547 pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
8548 pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
8549 pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
8551 mGlobalKeyManager.dump(prefix, pw);
8552 mStatusBarController.dump(pw, prefix);
8553 mNavigationBarController.dump(pw, prefix);
8554 PolicyControl.dump(prefix, pw);
8556 if (mWakeGestureListener != null) {
8557 mWakeGestureListener.dump(pw, prefix);
8559 if (mOrientationListener != null) {
8560 mOrientationListener.dump(pw, prefix);
8562 if (mBurnInProtectionHelper != null) {
8563 mBurnInProtectionHelper.dump(prefix, pw);
8565 if (mKeyguardDelegate != null) {
8566 mKeyguardDelegate.dump(prefix, pw);