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;
114 import android.util.DisplayMetrics;
115 import android.util.EventLog;
116 import android.util.Log;
117 import android.util.MutableBoolean;
118 import android.util.Slog;
119 import android.util.SparseArray;
120 import android.util.LongSparseArray;
121 import android.view.Display;
122 import android.view.Gravity;
123 import android.view.HapticFeedbackConstants;
124 import android.view.IApplicationToken;
125 import android.view.IWindowManager;
126 import android.view.InputChannel;
127 import android.view.InputDevice;
128 import android.view.InputEvent;
129 import android.view.InputEventReceiver;
130 import android.view.KeyCharacterMap;
131 import android.view.KeyCharacterMap.FallbackAction;
132 import android.view.KeyEvent;
133 import android.view.MotionEvent;
134 import android.view.Surface;
135 import android.view.View;
136 import android.view.ViewConfiguration;
137 import android.view.WindowManager;
138 import android.view.WindowManagerGlobal;
139 import android.view.WindowManagerInternal;
140 import android.view.WindowManagerPolicy;
141 import android.view.accessibility.AccessibilityEvent;
142 import android.view.accessibility.AccessibilityManager;
143 import android.view.animation.Animation;
144 import android.view.animation.AnimationSet;
145 import android.view.animation.AnimationUtils;
146 import android.widget.Toast;
148 import com.android.internal.R;
149 import com.android.internal.logging.MetricsLogger;
150 import com.android.internal.os.DeviceKeyHandler;
151 import com.android.internal.policy.PhoneWindow;
152 import com.android.internal.policy.IKeyguardService;
153 import com.android.internal.policy.IShortcutService;
154 import com.android.internal.statusbar.IStatusBarService;
155 import com.android.internal.util.ScreenShapeHelper;
156 import com.android.internal.widget.PointerLocationView;
157 import com.android.server.GestureLauncherService;
158 import com.android.server.LocalServices;
159 import com.android.server.policy.keyguard.KeyguardServiceDelegate;
160 import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener;
161 import com.android.server.statusbar.StatusBarManagerInternal;
163 import dalvik.system.DexClassLoader;
166 import java.io.FileReader;
167 import java.io.IOException;
168 import java.io.PrintWriter;
169 import java.util.HashSet;
170 import java.util.List;
171 import java.lang.reflect.Constructor;
173 import cyanogenmod.providers.CMSettings;
176 * WindowManagerPolicy implementation for the Android phone UI. This
177 * introduces a new method suffix, Lp, for an internal lock of the
178 * PhoneWindowManager. This is used to protect some internal state, and
179 * can be acquired with either the Lw and Li lock held, so has the restrictions
180 * of both of those when held.
182 public class PhoneWindowManager implements WindowManagerPolicy {
183 static final String TAG = "WindowManager";
184 static final boolean DEBUG = false;
185 static final boolean localLOGV = false;
186 static final boolean DEBUG_INPUT = false;
187 static final boolean DEBUG_KEYGUARD = false;
188 static final boolean DEBUG_LAYOUT = false;
189 static final boolean DEBUG_STARTING_WINDOW = false;
190 static final boolean DEBUG_WAKEUP = false;
191 static final boolean SHOW_STARTING_ANIMATIONS = true;
192 static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
194 // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
195 // No longer recommended for desk docks;
196 static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
198 static final int SHORT_PRESS_POWER_NOTHING = 0;
199 static final int SHORT_PRESS_POWER_GO_TO_SLEEP = 1;
200 static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2;
201 static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3;
202 static final int SHORT_PRESS_POWER_GO_HOME = 4;
204 static final int LONG_PRESS_POWER_NOTHING = 0;
205 static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
206 static final int LONG_PRESS_POWER_SHUT_OFF = 2;
207 static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
209 static final int LONG_PRESS_BACK_NOTHING = 0;
210 static final int LONG_PRESS_BACK_GO_TO_VOICE_ASSIST = 1;
212 static final int MULTI_PRESS_POWER_NOTHING = 0;
213 static final int MULTI_PRESS_POWER_THEATER_MODE = 1;
214 static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2;
216 // These need to match the documentation/constant in
217 // core/res/res/values/config.xml
218 static final int LONG_PRESS_HOME_NOTHING = 0;
219 static final int LONG_PRESS_HOME_RECENT_SYSTEM_UI = 1;
220 static final int LONG_PRESS_HOME_ASSIST = 2;
221 static final int LAST_LONG_PRESS_HOME_BEHAVIOR = LONG_PRESS_HOME_ASSIST;
223 static final int DOUBLE_TAP_HOME_NOTHING = 0;
224 static final int DOUBLE_TAP_HOME_RECENT_SYSTEM_UI = 1;
226 static final int SHORT_PRESS_WINDOW_NOTHING = 0;
227 static final int SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE = 1;
229 static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP = 0;
230 static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME = 1;
232 // Controls navigation bar opacity depending on which workspace stacks are currently
234 // Nav bar is always opaque when either the freeform stack or docked stack is visible.
235 static final int NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED = 0;
236 // Nav bar is always translucent when the freeform stack is visible, otherwise always opaque.
237 static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1;
239 static final int APPLICATION_MEDIA_SUBLAYER = -2;
240 static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
241 static final int APPLICATION_PANEL_SUBLAYER = 1;
242 static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
243 static final int APPLICATION_ABOVE_SUB_PANEL_SUBLAYER = 3;
245 static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
246 static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
247 static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
248 static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
249 static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";
251 // Available custom actions to perform on a key press.
252 // Must match values for KEY_HOME_LONG_PRESS_ACTION in:
253 // core/java/android/provider/Settings.java
254 private static final int KEY_ACTION_NOTHING = 0;
255 private static final int KEY_ACTION_MENU = 1;
256 private static final int KEY_ACTION_APP_SWITCH = 2;
257 private static final int KEY_ACTION_SEARCH = 3;
258 private static final int KEY_ACTION_VOICE_SEARCH = 4;
259 private static final int KEY_ACTION_IN_APP_SEARCH = 5;
260 private static final int KEY_ACTION_LAUNCH_CAMERA = 6;
261 private static final int KEY_ACTION_SLEEP = 7;
263 // Masks for checking presence of hardware keys.
264 // Must match values in core/res/res/values/config.xml
265 private static final int KEY_MASK_HOME = 0x01;
266 private static final int KEY_MASK_BACK = 0x02;
267 private static final int KEY_MASK_MENU = 0x04;
268 private static final int KEY_MASK_ASSIST = 0x08;
269 private static final int KEY_MASK_APP_SWITCH = 0x10;
270 private static final int KEY_MASK_CAMERA = 0x20;
271 private static final int KEY_MASK_VOLUME = 0x40;
275 * These are the system UI flags that, when changing, can cause the layout
276 * of the screen to change.
278 static final int SYSTEM_UI_CHANGING_LAYOUT =
279 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
280 | View.SYSTEM_UI_FLAG_FULLSCREEN
281 | View.STATUS_BAR_TRANSLUCENT
282 | View.NAVIGATION_BAR_TRANSLUCENT
283 | View.STATUS_BAR_TRANSPARENT
284 | View.NAVIGATION_BAR_TRANSPARENT;
286 private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
287 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
288 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
292 * Broadcast Action: WiFi Display video is enabled or disabled
294 * <p>The intent will have the following extra values:</p>
296 * <li><em>state</em> - 0 for disabled, 1 for enabled. </li>
300 private static final String ACTION_WIFI_DISPLAY_VIDEO =
301 "org.codeaurora.intent.action.WIFI_DISPLAY_VIDEO";
304 // The panic gesture may become active only after the keyguard is dismissed and the immersive
305 // app shows again. If that doesn't happen for 30s we drop the gesture.
306 private static final long PANIC_GESTURE_EXPIRATION = 30000;
308 private static final String SYSUI_PACKAGE = "com.android.systemui";
309 private static final String SYSUI_SCREENSHOT_SERVICE =
310 "com.android.systemui.screenshot.TakeScreenshotService";
311 private static final String SYSUI_SCREENSHOT_ERROR_RECEIVER =
312 "com.android.systemui.screenshot.ScreenshotServiceErrorReceiver";
317 private WindowState mKeyguardScrim;
318 private boolean mKeyguardHidden;
319 private boolean mKeyguardDrawnOnce;
321 /* Table of Application Launch keys. Maps from key codes to intent categories.
323 * These are special keys that are used to launch particular kinds of applications,
324 * such as a web browser. HID defines nearly a hundred of them in the Consumer (0x0C)
325 * usage page. We don't support quite that many yet...
327 static SparseArray<String> sApplicationLaunchKeyCategories;
329 sApplicationLaunchKeyCategories = new SparseArray<String>();
330 sApplicationLaunchKeyCategories.append(
331 KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER);
332 sApplicationLaunchKeyCategories.append(
333 KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL);
334 sApplicationLaunchKeyCategories.append(
335 KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS);
336 sApplicationLaunchKeyCategories.append(
337 KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR);
338 sApplicationLaunchKeyCategories.append(
339 KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC);
340 sApplicationLaunchKeyCategories.append(
341 KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
344 /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
345 static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;
347 private DeviceKeyHandler mDeviceKeyHandler;
350 * Lock protecting internal state. Must not call out into window
351 * manager with lock held. (This lock will be acquired in places
352 * where the window manager is calling in with its own lock held.)
354 private final Object mLock = new Object();
357 IWindowManager mWindowManager;
358 WindowManagerFuncs mWindowManagerFuncs;
359 WindowManagerInternal mWindowManagerInternal;
360 PowerManager mPowerManager;
361 ActivityManagerInternal mActivityManagerInternal;
362 InputManagerInternal mInputManagerInternal;
363 DreamManagerInternal mDreamManagerInternal;
364 PowerManagerInternal mPowerManagerInternal;
365 IStatusBarService mStatusBarService;
366 StatusBarManagerInternal mStatusBarManagerInternal;
367 boolean mPreloadedRecentApps;
368 final Object mServiceAquireLock = new Object();
369 Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
370 SearchManager mSearchManager;
371 AccessibilityManager mAccessibilityManager;
372 BurnInProtectionHelper mBurnInProtectionHelper;
373 AppOpsManager mAppOpsManager;
374 private boolean mHasFeatureWatch;
376 // Vibrator pattern for haptic feedback of a long press.
377 long[] mLongPressVibePattern;
379 // Vibrator pattern for haptic feedback of virtual key press.
380 long[] mVirtualKeyVibePattern;
382 // Vibrator pattern for a short vibration.
383 long[] mKeyboardTapVibePattern;
385 // Vibrator pattern for a short vibration when tapping on an hour/minute tick of a Clock.
386 long[] mClockTickVibePattern;
388 // Vibrator pattern for a short vibration when tapping on a day/month/year date of a Calendar.
389 long[] mCalendarDateVibePattern;
391 // Vibrator pattern for haptic feedback during boot when safe mode is disabled.
392 long[] mSafeModeDisabledVibePattern;
394 // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
395 long[] mSafeModeEnabledVibePattern;
397 // Vibrator pattern for haptic feedback of a context click.
398 long[] mContextClickVibePattern;
400 /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
401 boolean mEnableShiftMenuBugReports = false;
404 WindowState mStatusBar = null;
405 int mStatusBarHeight;
406 WindowState mNavigationBar = null;
407 boolean mHasNavigationBar = false;
408 boolean mCanHideNavigationBar = false;
409 boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?
410 boolean mNavigationBarOnBottom = true; // is the navigation bar on the bottom *right now*?
411 int[] mNavigationBarHeightForRotationDefault = new int[4];
412 int[] mNavigationBarWidthForRotationDefault = new int[4];
413 int[] mNavigationBarHeightForRotationInCarMode = new int[4];
414 int[] mNavigationBarWidthForRotationInCarMode = new int[4];
416 private LongSparseArray<IShortcutService> mShortcutKeyServices = new LongSparseArray<>();
418 // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
419 // This is for car dock and this is updated from resource.
420 private boolean mEnableCarDockHomeCapture = true;
422 boolean mBootMessageNeedsHiding;
423 KeyguardServiceDelegate mKeyguardDelegate;
424 final Runnable mWindowManagerDrawCallback = new Runnable() {
427 if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!");
428 mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);
431 final DrawnListener mKeyguardDrawnCallback = new DrawnListener() {
433 public void onDrawn() {
434 if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn.");
435 mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
439 GlobalActions mGlobalActions;
441 WindowState mLastInputMethodWindow = null;
442 WindowState mLastInputMethodTargetWindow = null;
444 // FIXME This state is shared between the input reader and handler thread.
445 // Technically it's broken and buggy but it has been like this for many years
446 // and we have not yet seen any problems. Someday we'll rewrite this logic
447 // so that only one thread is involved in handling input policy. Unfortunately
448 // it's on a critical path for power management so we can't just post the work to the
449 // handler thread. We'll need to resolve this someday by teaching the input dispatcher
450 // to hold wakelocks during dispatch and eliminating the critical path.
451 volatile boolean mPowerKeyHandled;
452 volatile boolean mBackKeyHandled;
453 volatile boolean mBeganFromNonInteractive;
454 volatile int mPowerKeyPressCounter;
455 volatile boolean mEndCallKeyHandled;
456 volatile boolean mCameraGestureTriggeredDuringGoingToSleep;
457 volatile boolean mGoingToSleep;
458 volatile boolean mRecentsVisible;
459 volatile boolean mTvPictureInPictureVisible;
461 int mRecentAppsHeldModifiers;
462 boolean mLanguageSwitchKeyPressed;
464 int mLidState = LID_ABSENT;
465 int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT;
466 boolean mHaveBuiltInKeyboard;
468 boolean mSystemReady;
469 boolean mSystemBooted;
470 private boolean mDeferBindKeyguard;
471 boolean mHdmiPlugged;
472 HdmiControl mHdmiControl;
473 IUiModeManager mUiModeManager;
475 int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
476 int mLidOpenRotation;
477 int mCarDockRotation;
478 int mDeskDockRotation;
479 int mUndockedHdmiRotation;
480 int mDemoHdmiRotation;
481 boolean mDemoHdmiRotationLock;
483 boolean mDemoRotationLock;
485 boolean mWakeGestureEnabledSetting;
486 MyWakeGestureListener mWakeGestureListener;
488 // Default display does not rotate, apps that require non-default orientation will have to
489 // have the orientation emulated.
490 private boolean mForceDefaultOrientation = false;
492 int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
493 int mUserRotation = Surface.ROTATION_0;
494 boolean mAccelerometerDefault;
496 boolean mSupportAutoRotation;
497 int mAllowAllRotations = -1;
498 boolean mCarDockEnablesAccelerometer;
499 boolean mDeskDockEnablesAccelerometer;
500 int mLidKeyboardAccessibility;
501 int mLidNavigationAccessibility;
502 boolean mLidControlsScreenLock;
503 boolean mLidControlsSleep;
504 int mShortPressOnPowerBehavior;
505 int mLongPressOnPowerBehavior;
506 int mDoublePressOnPowerBehavior;
507 int mTriplePressOnPowerBehavior;
508 int mLongPressOnBackBehavior;
509 int mShortPressOnSleepBehavior;
510 int mShortPressWindowBehavior;
512 boolean mScreenOnEarly;
513 boolean mScreenOnFully;
514 ScreenOnListener mScreenOnListener;
515 boolean mKeyguardDrawComplete;
516 boolean mWindowManagerDrawComplete;
517 boolean mOrientationSensorEnabled = false;
518 int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
519 boolean mHasSoftInput = false;
520 boolean mTranslucentDecorEnabled = true;
521 boolean mUseTvRouting;
522 int mBackKillTimeout;
524 int mDeviceHardwareKeys;
526 // Button wake control flags
527 boolean mHomeWakeScreen;
528 boolean mBackWakeScreen;
529 boolean mMenuWakeScreen;
530 boolean mAssistWakeScreen;
531 boolean mAppSwitchWakeScreen;
532 boolean mCameraWakeScreen;
533 boolean mVolumeWakeScreen;
535 // Camera button control flags and actions
536 boolean mCameraSleepOnRelease;
537 boolean mIsFocusPressed;
538 boolean mCameraLaunch;
540 // During wakeup by volume keys, we still need to capture subsequent events
541 // until the key is released. This is required since the beep sound is produced
543 boolean mVolumeWakeTriggered;
545 int mPointerLocationMode = 0; // guarded by mLock
547 // The last window we were told about in focusChanged.
548 WindowState mFocusedWindow;
549 IApplicationToken mFocusedApp;
551 // Behavior of volbtn music controls
552 boolean mVolBtnMusicControls;
553 boolean mIsLongPress;
555 // Volume wake control flag
556 boolean mVolumeWakeScreen;
558 PointerLocationView mPointerLocationView;
560 // The current size of the screen; really; extends into the overscan area of
561 // the screen and doesn't account for any system elements like the status bar.
562 int mOverscanScreenLeft, mOverscanScreenTop;
563 int mOverscanScreenWidth, mOverscanScreenHeight;
564 // The current visible size of the screen; really; (ir)regardless of whether the status
565 // bar can be hidden but not extending into the overscan area.
566 int mUnrestrictedScreenLeft, mUnrestrictedScreenTop;
567 int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight;
568 // Like mOverscanScreen*, but allowed to move into the overscan region where appropriate.
569 int mRestrictedOverscanScreenLeft, mRestrictedOverscanScreenTop;
570 int mRestrictedOverscanScreenWidth, mRestrictedOverscanScreenHeight;
571 // The current size of the screen; these may be different than (0,0)-(dw,dh)
572 // if the status bar can't be hidden; in that case it effectively carves out
573 // that area of the display from all other windows.
574 int mRestrictedScreenLeft, mRestrictedScreenTop;
575 int mRestrictedScreenWidth, mRestrictedScreenHeight;
576 // During layout, the current screen borders accounting for any currently
577 // visible system UI elements.
578 int mSystemLeft, mSystemTop, mSystemRight, mSystemBottom;
579 // For applications requesting stable content insets, these are them.
580 int mStableLeft, mStableTop, mStableRight, mStableBottom;
581 // For applications requesting stable content insets but have also set the
582 // fullscreen window flag, these are the stable dimensions without the status bar.
583 int mStableFullscreenLeft, mStableFullscreenTop;
584 int mStableFullscreenRight, mStableFullscreenBottom;
585 // During layout, the current screen borders with all outer decoration
586 // (status bar, input method dock) accounted for.
587 int mCurLeft, mCurTop, mCurRight, mCurBottom;
588 // During layout, the frame in which content should be displayed
589 // to the user, accounting for all screen decoration except for any
590 // space they deem as available for other content. This is usually
591 // the same as mCur*, but may be larger if the screen decor has supplied
593 int mContentLeft, mContentTop, mContentRight, mContentBottom;
594 // During layout, the frame in which voice content should be displayed
595 // to the user, accounting for all screen decoration except for any
596 // space they deem as available for other content.
597 int mVoiceContentLeft, mVoiceContentTop, mVoiceContentRight, mVoiceContentBottom;
598 // During layout, the current screen borders along which input method
599 // windows are placed.
600 int mDockLeft, mDockTop, mDockRight, mDockBottom;
601 // During layout, the layer at which the doc window is placed.
603 // During layout, this is the layer of the status bar.
605 int mLastSystemUiFlags;
606 // Bits that we are in the process of clearing, so we want to prevent
607 // them from being set by applications until everything has been updated
608 // to have them clear.
609 int mResettingSystemUiFlags = 0;
610 // Bits that we are currently always keeping cleared.
611 int mForceClearedSystemUiFlags = 0;
612 int mLastFullscreenStackSysUiFlags;
613 int mLastDockedStackSysUiFlags;
614 final Rect mNonDockedStackBounds = new Rect();
615 final Rect mDockedStackBounds = new Rect();
616 final Rect mLastNonDockedStackBounds = new Rect();
617 final Rect mLastDockedStackBounds = new Rect();
619 // What we last reported to system UI about whether the compatibility
620 // menu needs to be displayed.
621 boolean mLastFocusNeedsMenu = false;
622 // If nonzero, a panic gesture was performed at that time in uptime millis and is still pending.
623 private long mPendingPanicGestureUptime;
625 InputConsumer mInputConsumer = null;
627 static final Rect mTmpParentFrame = new Rect();
628 static final Rect mTmpDisplayFrame = new Rect();
629 static final Rect mTmpOverscanFrame = new Rect();
630 static final Rect mTmpContentFrame = new Rect();
631 static final Rect mTmpVisibleFrame = new Rect();
632 static final Rect mTmpDecorFrame = new Rect();
633 static final Rect mTmpStableFrame = new Rect();
634 static final Rect mTmpNavigationFrame = new Rect();
635 static final Rect mTmpOutsetFrame = new Rect();
636 private static final Rect mTmpRect = new Rect();
638 WindowState mTopFullscreenOpaqueWindowState;
639 WindowState mTopFullscreenOpaqueOrDimmingWindowState;
640 WindowState mTopDockedOpaqueWindowState;
641 WindowState mTopDockedOpaqueOrDimmingWindowState;
642 HashSet<IApplicationToken> mAppsToBeHidden = new HashSet<IApplicationToken>();
643 HashSet<IApplicationToken> mAppsThatDismissKeyguard = new HashSet<IApplicationToken>();
644 boolean mTopIsFullscreen;
645 boolean mForceStatusBar;
646 boolean mForceStatusBarFromKeyguard;
647 private boolean mForceStatusBarTransparent;
648 int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
649 boolean mHideLockScreen;
650 boolean mForcingShowNavBar;
651 int mForcingShowNavBarLayer;
653 // States of keyguard dismiss.
654 private static final int DISMISS_KEYGUARD_NONE = 0; // Keyguard not being dismissed.
655 private static final int DISMISS_KEYGUARD_START = 1; // Keyguard needs to be dismissed.
656 private static final int DISMISS_KEYGUARD_CONTINUE = 2; // Keyguard has been dismissed.
657 int mDismissKeyguard = DISMISS_KEYGUARD_NONE;
659 /** The window that is currently dismissing the keyguard. Dismissing the keyguard must only
660 * be done once per window. */
661 private WindowState mWinDismissingKeyguard;
663 /** When window is currently dismissing the keyguard, dismissing the keyguard must handle
664 * the keygaurd secure state change instantly case, e.g. the use case of inserting a PIN
665 * lock SIM card. This variable is used to record the previous keyguard secure state for
666 * monitoring secure state change on window dismissing keyguard. */
667 private boolean mSecureDismissingKeyguard;
669 /** The window that is currently showing "over" the keyguard. If there is an app window
670 * belonging to another app on top of this the keyguard shows. If there is a fullscreen
671 * app window under this, still dismiss the keyguard but don't show the app underneath. Show
673 private WindowState mWinShowWhenLocked;
675 boolean mShowingLockscreen;
676 boolean mShowingDream;
677 boolean mDreamingLockscreen;
678 boolean mDreamingSleepTokenNeeded;
679 SleepToken mDreamingSleepToken;
680 SleepToken mScreenOffSleepToken;
681 boolean mKeyguardSecure;
682 boolean mKeyguardSecureIncludingHidden;
683 volatile boolean mKeyguardOccluded;
684 boolean mHomePressed;
685 boolean mHomeConsumed;
686 boolean mHomeDoubleTapPending;
687 boolean mMenuPressed;
688 boolean mAppSwitchLongPressed;
690 Intent mCarDockIntent;
691 Intent mDeskDockIntent;
692 boolean mSearchKeyShortcutPending;
693 boolean mConsumeSearchKeyUp;
694 boolean mAssistKeyLongPressed;
695 boolean mPendingMetaAction;
696 boolean mPendingCapsLockToggle;
698 int mInitialMetaState;
699 boolean mForceShowSystemBars;
701 // Tracks user-customisable behavior for certain key events
702 private int mLongPressOnHomeBehavior = -1;
703 private int mPressOnMenuBehavior = -1;
704 private int mLongPressOnMenuBehavior = -1;
705 private int mPressOnAssistBehavior = -1;
706 private int mLongPressOnAssistBehavior = -1;
707 private int mPressOnAppSwitchBehavior = -1;
708 private int mLongPressOnAppSwitchBehavior = -1;
710 // support for activating the lock screen while the screen is on
711 boolean mAllowLockscreenWhenOn;
712 int mLockScreenTimeout;
713 boolean mLockScreenTimerActive;
715 // Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.)
716 int mEndcallBehavior;
718 // Behavior of POWER button while in-call and screen on.
719 // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
720 int mIncallPowerBehavior;
724 private int mDisplayRotation;
726 int mLandscapeRotation = 0; // default landscape rotation
727 int mSeascapeRotation = 0; // "other" landscape rotation, 180 degrees from mLandscapeRotation
728 int mPortraitRotation = 0; // default portrait rotation
729 int mUpsideDownRotation = 0; // "other" portrait rotation
731 int mOverscanLeft = 0;
732 int mOverscanTop = 0;
733 int mOverscanRight = 0;
734 int mOverscanBottom = 0;
736 // What we do when the user double-taps on home
737 private int mDoubleTapOnHomeBehavior;
739 // Allowed theater mode wake actions
740 private boolean mAllowTheaterModeWakeFromKey;
741 private boolean mAllowTheaterModeWakeFromPowerKey;
742 private boolean mAllowTheaterModeWakeFromMotion;
743 private boolean mAllowTheaterModeWakeFromMotionWhenNotDreaming;
744 private boolean mAllowTheaterModeWakeFromCameraLens;
745 private boolean mAllowTheaterModeWakeFromLidSwitch;
746 private boolean mAllowTheaterModeWakeFromWakeGesture;
748 // Whether to support long press from power button in non-interactive mode
749 private boolean mSupportLongPressPowerWhenNonInteractive;
751 // Whether to go to sleep entering theater mode from power button
752 private boolean mGoToSleepOnButtonPressTheaterMode;
754 // Screenshot trigger states
755 // Time to volume and power must be pressed within this interval of each other.
756 private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
757 // Increase the chord delay when taking a screenshot from the keyguard
758 private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f;
759 private boolean mScreenshotChordEnabled;
760 private boolean mScreenshotChordVolumeDownKeyTriggered;
761 private long mScreenshotChordVolumeDownKeyTime;
762 private boolean mScreenshotChordVolumeDownKeyConsumed;
763 private boolean mScreenshotChordVolumeUpKeyTriggered;
764 private boolean mScreenshotChordPowerKeyTriggered;
765 private long mScreenshotChordPowerKeyTime;
767 /* The number of steps between min and max brightness */
768 private static final int BRIGHTNESS_STEPS = 10;
770 SettingsObserver mSettingsObserver;
771 ShortcutManager mShortcutManager;
772 PowerManager.WakeLock mBroadcastWakeLock;
773 PowerManager.WakeLock mPowerKeyWakeLock;
774 boolean mHavePendingMediaKeyRepeatWithWakeLock;
776 private int mCurrentUserId;
778 // Maps global key codes to the components that will handle them.
779 private GlobalKeyManager mGlobalKeyManager;
781 // Fallback actions by key code.
782 private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions =
783 new SparseArray<KeyCharacterMap.FallbackAction>();
785 private final LogDecelerateInterpolator mLogDecelerateInterpolator
786 = new LogDecelerateInterpolator(100, 0);
788 private final MutableBoolean mTmpBoolean = new MutableBoolean(false);
790 private static final int MSG_ENABLE_POINTER_LOCATION = 1;
791 private static final int MSG_DISABLE_POINTER_LOCATION = 2;
792 private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
793 private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
794 private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
795 private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6;
796 private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7;
797 private static final int MSG_DISPATCH_SHOW_RECENTS = 9;
798 private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10;
799 private static final int MSG_HIDE_BOOT_MESSAGE = 11;
800 private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12;
801 private static final int MSG_POWER_DELAYED_PRESS = 13;
802 private static final int MSG_POWER_LONG_PRESS = 14;
803 private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 15;
804 private static final int MSG_REQUEST_TRANSIENT_BARS = 16;
805 private static final int MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU = 17;
806 private static final int MSG_BACK_LONG_PRESS = 18;
807 private static final int MSG_DISPOSE_INPUT_CONSUMER = 19;
808 private static final int MSG_DISPATCH_VOLKEY_WITH_WAKE_LOCK = 20;
809 private static final int MSG_CAMERA_LONG_PRESS = 21;
811 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
812 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
813 boolean mWifiDisplayConnected = false;
814 int mWifiDisplayCustomRotation = -1;
816 private class PolicyHandler extends Handler {
818 public void handleMessage(Message msg) {
820 case MSG_ENABLE_POINTER_LOCATION:
821 enablePointerLocation();
823 case MSG_DISABLE_POINTER_LOCATION:
824 disablePointerLocation();
826 case MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK:
827 dispatchMediaKeyWithWakeLock((KeyEvent)msg.obj);
829 case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK:
830 dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj);
832 case MSG_DISPATCH_SHOW_RECENTS:
833 showRecentApps(false, msg.arg1 != 0);
835 case MSG_DISPATCH_SHOW_GLOBAL_ACTIONS:
836 showGlobalActionsInternal();
838 case MSG_KEYGUARD_DRAWN_COMPLETE:
839 if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete");
840 finishKeyguardDrawn();
842 case MSG_KEYGUARD_DRAWN_TIMEOUT:
843 Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete");
844 finishKeyguardDrawn();
846 case MSG_WINDOW_MANAGER_DRAWN_COMPLETE:
847 if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete");
848 finishWindowsDrawn();
850 case MSG_HIDE_BOOT_MESSAGE:
851 handleHideBootMessage();
853 case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK:
854 launchVoiceAssistWithWakeLock(msg.arg1 != 0);
856 case MSG_POWER_DELAYED_PRESS:
857 powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2);
858 finishPowerKeyPress();
860 case MSG_POWER_LONG_PRESS:
863 case MSG_UPDATE_DREAMING_SLEEP_TOKEN:
864 updateDreamingSleepToken(msg.arg1 != 0);
866 case MSG_REQUEST_TRANSIENT_BARS:
867 WindowState targetBar = (msg.arg1 == MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS) ?
868 mStatusBar : mNavigationBar;
869 if (targetBar != null) {
870 requestTransientBars(targetBar);
873 case MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU:
874 showTvPictureInPictureMenuInternal();
876 case MSG_BACK_LONG_PRESS:
879 case MSG_DISPOSE_INPUT_CONSUMER:
880 disposeInputConsumer((InputConsumer) msg.obj);
882 case MSG_DISPATCH_VOLKEY_WITH_WAKE_LOCK: {
883 KeyEvent event = (KeyEvent) msg.obj;
885 dispatchMediaKeyWithWakeLockToAudioService(event);
886 dispatchMediaKeyWithWakeLockToAudioService(
887 KeyEvent.changeAction(event, KeyEvent.ACTION_UP));
890 case MSG_CAMERA_LONG_PRESS: {
891 KeyEvent event = (KeyEvent) msg.obj;
899 private UEventObserver mHDMIObserver = new UEventObserver() {
901 public void onUEvent(UEventObserver.UEvent event) {
902 setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
906 class SettingsObserver extends ContentObserver {
907 SettingsObserver(Handler handler) {
912 // Observe all users' changes
913 ContentResolver resolver = mContext.getContentResolver();
914 resolver.registerContentObserver(Settings.System.getUriFor(
915 Settings.System.END_BUTTON_BEHAVIOR), false, this,
916 UserHandle.USER_ALL);
917 resolver.registerContentObserver(Settings.Secure.getUriFor(
918 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this,
919 UserHandle.USER_ALL);
920 resolver.registerContentObserver(Settings.Secure.getUriFor(
921 Settings.Secure.WAKE_GESTURE_ENABLED), false, this,
922 UserHandle.USER_ALL);
923 resolver.registerContentObserver(Settings.System.getUriFor(
924 Settings.System.ACCELEROMETER_ROTATION), false, this,
925 UserHandle.USER_ALL);
926 resolver.registerContentObserver(Settings.System.getUriFor(
927 Settings.System.USER_ROTATION), false, this,
928 UserHandle.USER_ALL);
929 resolver.registerContentObserver(Settings.System.getUriFor(
930 Settings.System.SCREEN_OFF_TIMEOUT), false, this,
931 UserHandle.USER_ALL);
932 resolver.registerContentObserver(Settings.System.getUriFor(
933 Settings.System.POINTER_LOCATION), false, this,
934 UserHandle.USER_ALL);
935 resolver.registerContentObserver(CMSettings.System.getUriFor(
936 CMSettings.System.KEY_HOME_LONG_PRESS_ACTION), false, this,
937 UserHandle.USER_ALL);
938 resolver.registerContentObserver(CMSettings.System.getUriFor(
939 CMSettings.System.KEY_HOME_DOUBLE_TAP_ACTION), false, this,
940 UserHandle.USER_ALL);
941 resolver.registerContentObserver(CMSettings.System.getUriFor(
942 CMSettings.System.KEY_MENU_ACTION), false, this,
943 UserHandle.USER_ALL);
944 resolver.registerContentObserver(CMSettings.System.getUriFor(
945 CMSettings.System.KEY_MENU_LONG_PRESS_ACTION), false, this,
946 UserHandle.USER_ALL);
947 resolver.registerContentObserver(CMSettings.System.getUriFor(
948 CMSettings.System.KEY_ASSIST_ACTION), false, this,
949 UserHandle.USER_ALL);
950 resolver.registerContentObserver(CMSettings.System.getUriFor(
951 CMSettings.System.KEY_ASSIST_LONG_PRESS_ACTION), false, this,
952 UserHandle.USER_ALL);
953 resolver.registerContentObserver(CMSettings.System.getUriFor(
954 CMSettings.System.KEY_APP_SWITCH_ACTION), false, this,
955 UserHandle.USER_ALL);
956 resolver.registerContentObserver(CMSettings.System.getUriFor(
957 CMSettings.System.KEY_APP_SWITCH_LONG_PRESS_ACTION), false, this,
958 UserHandle.USER_ALL);
959 resolver.registerContentObserver(Settings.Secure.getUriFor(
960 Settings.Secure.DEFAULT_INPUT_METHOD), false, this,
961 UserHandle.USER_ALL);
962 resolver.registerContentObserver(Settings.Secure.getUriFor(
963 Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this,
964 UserHandle.USER_ALL);
965 resolver.registerContentObserver(Settings.Global.getUriFor(
966 Settings.Global.POLICY_CONTROL), false, this,
967 UserHandle.USER_ALL);
968 resolver.registerContentObserver(Settings.System.getUriFor(
969 Settings.System.VOLBTN_MUSIC_CONTROLS), false, this,
970 UserHandle.USER_ALL);
971 resolver.registerContentObserver(Settings.System.getUriFor(
972 CMSettings.System.BACK_WAKE_SCREEN), false, this,
973 UserHandle.USER_ALL);
974 resolver.registerContentObserver(CMSettings.System.getUriFor(
975 CMSettings.System.MENU_WAKE_SCREEN), false, this,
976 UserHandle.USER_ALL);
977 resolver.registerContentObserver(CMSettings.System.getUriFor(
978 CMSettings.System.ASSIST_WAKE_SCREEN), false, this,
979 UserHandle.USER_ALL);
980 resolver.registerContentObserver(CMSettings.System.getUriFor(
981 CMSettings.System.APP_SWITCH_WAKE_SCREEN), false, this,
982 UserHandle.USER_ALL);
983 resolver.registerContentObserver(CMSettings.System.getUriFor(
984 CMSettings.System.CAMERA_WAKE_SCREEN), false, this,
985 UserHandle.USER_ALL);
986 resolver.registerContentObserver(CMSettings.System.getUriFor(
987 CMSettings.System.CAMERA_SLEEP_ON_RELEASE), false, this,
988 UserHandle.USER_ALL);
989 resolver.registerContentObserver(CMSettings.System.getUriFor(
990 CMSettings.System.CAMERA_LAUNCH), false, this,
991 UserHandle.USER_ALL);
992 resolver.registerContentObserver(CMSettings.System.getUriFor(
993 CMSettings.System.VOLUME_WAKE_SCREEN), false, this,
994 UserHandle.USER_ALL);
995 resolver.registerContentObserver(CMSettings.System.getUriFor(
996 CMSettings.System.HOME_WAKE_SCREEN), false, this,
997 UserHandle.USER_ALL);
998 resolver.registerContentObserver(CMSettings.System.getUriFor(
999 CMSettings.System.VOLUME_WAKE_SCREEN), false, this,
1000 UserHandle.USER_ALL);
1004 @Override public void onChange(boolean selfChange) {
1006 updateRotation(false);
1010 class MyWakeGestureListener extends WakeGestureListener {
1011 MyWakeGestureListener(Context context, Handler handler) {
1012 super(context, handler);
1016 public void onWakeUp() {
1017 synchronized (mLock) {
1018 if (shouldEnableWakeGestureLp()) {
1019 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
1020 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture,
1021 "android.policy:GESTURE");
1027 class MyOrientationListener extends WindowOrientationListener {
1028 private final Runnable mUpdateRotationRunnable = new Runnable() {
1031 // send interaction hint to improve redraw performance
1032 mPowerManagerInternal.powerHint(PowerManagerInternal.POWER_HINT_INTERACTION, 0);
1033 updateRotation(false);
1037 MyOrientationListener(Context context, Handler handler) {
1038 super(context, handler);
1042 public void onProposedRotationChanged(int rotation) {
1043 if (localLOGV) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
1044 mHandler.post(mUpdateRotationRunnable);
1047 MyOrientationListener mOrientationListener;
1049 private final StatusBarController mStatusBarController = new StatusBarController();
1051 private final BarController mNavigationBarController = new BarController("NavigationBar",
1052 View.NAVIGATION_BAR_TRANSIENT,
1053 View.NAVIGATION_BAR_UNHIDE,
1054 View.NAVIGATION_BAR_TRANSLUCENT,
1055 StatusBarManager.WINDOW_NAVIGATION_BAR,
1056 WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
1057 View.NAVIGATION_BAR_TRANSPARENT);
1059 private ImmersiveModeConfirmation mImmersiveModeConfirmation;
1061 private SystemGesturesPointerEventListener mSystemGestures;
1063 IStatusBarService getStatusBarService() {
1064 synchronized (mServiceAquireLock) {
1065 if (mStatusBarService == null) {
1066 mStatusBarService = IStatusBarService.Stub.asInterface(
1067 ServiceManager.getService("statusbar"));
1069 return mStatusBarService;
1073 StatusBarManagerInternal getStatusBarManagerInternal() {
1074 synchronized (mServiceAquireLock) {
1075 if (mStatusBarManagerInternal == null) {
1076 mStatusBarManagerInternal =
1077 LocalServices.getService(StatusBarManagerInternal.class);
1079 return mStatusBarManagerInternal;
1084 * We always let the sensor be switched on by default except when
1085 * the user has explicitly disabled sensor based rotation or when the
1086 * screen is switched off.
1088 boolean needSensorRunningLp() {
1089 if (mSupportAutoRotation) {
1090 if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
1091 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
1092 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
1093 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
1094 // If the application has explicitly requested to follow the
1095 // orientation, then we need to turn the sensor on.
1099 if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
1100 (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
1101 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
1102 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
1103 // enable accelerometer if we are docked in a dock that enables accelerometer
1104 // orientation management,
1107 if (mUserRotationMode == USER_ROTATION_LOCKED) {
1108 // If the setting for using the sensor by default is enabled, then
1109 // we will always leave it on. Note that the user could go to
1110 // a window that forces an orientation that does not use the
1111 // sensor and in theory we could turn it off... however, when next
1112 // turning it on we won't have a good value for the current
1113 // orientation for a little bit, which can cause orientation
1114 // changes to lag, so we'd like to keep it always on. (It will
1115 // still be turned off when the screen is off.)
1118 return mSupportAutoRotation;
1122 * Various use cases for invoking this function
1123 * screen turning off, should always disable listeners if already enabled
1124 * screen turned on and current app has sensor based orientation, enable listeners
1125 * if not already enabled
1126 * screen turned on and current app does not have sensor orientation, disable listeners if
1128 * screen turning on and current app has sensor based orientation, enable listeners if needed
1129 * screen turning on and current app has nosensor based orientation, do nothing
1131 void updateOrientationListenerLp() {
1132 if (!mOrientationListener.canDetectOrientation()) {
1133 // If sensor is turned off or nonexistent for some reason
1136 // Could have been invoked due to screen turning on or off or
1137 // change of the currently visible window's orientation.
1138 if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly
1139 + ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation
1140 + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled
1141 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
1142 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
1143 boolean disable = true;
1144 // Note: We postpone the rotating of the screen until the keyguard as well as the
1145 // window manager have reported a draw complete.
1146 if (mScreenOnEarly && mAwake &&
1147 mKeyguardDrawComplete && mWindowManagerDrawComplete) {
1148 if (needSensorRunningLp()) {
1150 //enable listener if not already enabled
1151 if (!mOrientationSensorEnabled) {
1152 mOrientationListener.enable();
1153 if(localLOGV) Slog.v(TAG, "Enabling listeners");
1154 mOrientationSensorEnabled = true;
1158 //check if sensors need to be disabled
1159 if (disable && mOrientationSensorEnabled) {
1160 mOrientationListener.disable();
1161 if(localLOGV) Slog.v(TAG, "Disabling listeners");
1162 mOrientationSensorEnabled = false;
1166 private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
1167 // Hold a wake lock until the power key is released.
1168 if (!mPowerKeyWakeLock.isHeld()) {
1169 mPowerKeyWakeLock.acquire();
1172 // Cancel multi-press detection timeout.
1173 if (mPowerKeyPressCounter != 0) {
1174 mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);
1177 // Detect user pressing the power button in panic when an application has
1178 // taken over the whole screen.
1179 boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
1180 SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags));
1182 mHandler.post(mHiddenNavPanic);
1185 // Latch power key state to detect screenshot chord.
1186 if (interactive && !mScreenshotChordPowerKeyTriggered
1187 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
1188 mScreenshotChordPowerKeyTriggered = true;
1189 mScreenshotChordPowerKeyTime = event.getDownTime();
1190 interceptScreenshotChord();
1193 // Stop ringing or end call if configured to do so when power is pressed.
1194 TelecomManager telecomManager = getTelecommService();
1195 boolean hungUp = false;
1196 if (telecomManager != null) {
1197 if (telecomManager.isRinging()) {
1198 // Pressing Power while there's a ringing incoming
1199 // call should silence the ringer.
1200 telecomManager.silenceRinger();
1201 } else if ((mIncallPowerBehavior
1202 & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
1203 && telecomManager.isInCall() && interactive) {
1204 // Otherwise, if "Power button ends call" is enabled,
1205 // the Power button will hang up any current active call.
1206 hungUp = telecomManager.endCall();
1210 GestureLauncherService gestureService = LocalServices.getService(
1211 GestureLauncherService.class);
1212 boolean gesturedServiceIntercepted = false;
1213 if (gestureService != null) {
1214 gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive,
1216 if (mTmpBoolean.value && mGoingToSleep) {
1217 mCameraGestureTriggeredDuringGoingToSleep = true;
1221 // If the power key has still not yet been handled, then detect short
1222 // press, long press, or multi press and decide what to do.
1223 mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
1224 || mScreenshotChordVolumeUpKeyTriggered || gesturedServiceIntercepted;
1225 if (!mPowerKeyHandled) {
1227 // When interactive, we're already awake.
1228 // Wait for a long press or for the button to be released to decide what to do.
1229 if (hasLongPressOnPowerBehavior()) {
1230 Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
1231 msg.setAsynchronous(true);
1232 mHandler.sendMessageDelayed(msg,
1233 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1236 wakeUpFromPowerKey(event.getDownTime());
1238 if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
1239 Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
1240 msg.setAsynchronous(true);
1241 mHandler.sendMessageDelayed(msg,
1242 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1243 mBeganFromNonInteractive = true;
1245 final int maxCount = getMaxMultiPressPowerCount();
1247 if (maxCount <= 1) {
1248 mPowerKeyHandled = true;
1250 mBeganFromNonInteractive = true;
1257 private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
1258 final boolean handled = canceled || mPowerKeyHandled;
1259 mScreenshotChordPowerKeyTriggered = false;
1260 cancelPendingScreenshotChordAction();
1261 cancelPendingPowerKeyAction();
1264 // Figure out how to handle the key now that it has been released.
1265 mPowerKeyPressCounter += 1;
1267 final int maxCount = getMaxMultiPressPowerCount();
1268 final long eventTime = event.getDownTime();
1269 if (mPowerKeyPressCounter < maxCount) {
1270 // This could be a multi-press. Wait a little bit longer to confirm.
1271 // Continue holding the wake lock.
1272 Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
1273 interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
1274 msg.setAsynchronous(true);
1275 mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
1279 // No other actions. Handle it immediately.
1280 powerPress(eventTime, interactive, mPowerKeyPressCounter);
1283 // Done. Reset our state.
1284 finishPowerKeyPress();
1287 private void finishPowerKeyPress() {
1288 mBeganFromNonInteractive = false;
1289 mPowerKeyPressCounter = 0;
1290 if (mPowerKeyWakeLock.isHeld()) {
1291 mPowerKeyWakeLock.release();
1295 private void cancelPendingPowerKeyAction() {
1296 if (!mPowerKeyHandled) {
1297 mPowerKeyHandled = true;
1298 mHandler.removeMessages(MSG_POWER_LONG_PRESS);
1302 private void cancelPendingBackKeyAction() {
1303 if (!mBackKeyHandled) {
1304 mBackKeyHandled = true;
1305 mHandler.removeMessages(MSG_BACK_LONG_PRESS);
1309 private void powerPress(long eventTime, boolean interactive, int count) {
1310 if (mScreenOnEarly && !mScreenOnFully) {
1311 Slog.i(TAG, "Suppressed redundant power key press while "
1312 + "already in the process of turning the screen on.");
1317 powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
1318 } else if (count == 3) {
1319 powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
1320 } else if (interactive && !mBeganFromNonInteractive) {
1321 switch (mShortPressOnPowerBehavior) {
1322 case SHORT_PRESS_POWER_NOTHING:
1324 case SHORT_PRESS_POWER_GO_TO_SLEEP:
1325 mPowerManager.goToSleep(eventTime,
1326 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
1328 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
1329 mPowerManager.goToSleep(eventTime,
1330 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
1331 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
1333 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
1334 mPowerManager.goToSleep(eventTime,
1335 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
1336 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
1337 launchHomeFromHotKey();
1339 case SHORT_PRESS_POWER_GO_HOME:
1340 launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
1346 private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) {
1348 case MULTI_PRESS_POWER_NOTHING:
1350 case MULTI_PRESS_POWER_THEATER_MODE:
1351 if (!isUserSetupComplete()) {
1352 Slog.i(TAG, "Ignoring toggling theater mode - device not setup.");
1356 if (isTheaterModeEnabled()) {
1357 Slog.i(TAG, "Toggling theater mode off.");
1358 Settings.Global.putInt(mContext.getContentResolver(),
1359 Settings.Global.THEATER_MODE_ON, 0);
1361 wakeUpFromPowerKey(eventTime);
1364 Slog.i(TAG, "Toggling theater mode on.");
1365 Settings.Global.putInt(mContext.getContentResolver(),
1366 Settings.Global.THEATER_MODE_ON, 1);
1368 if (mGoToSleepOnButtonPressTheaterMode && interactive) {
1369 mPowerManager.goToSleep(eventTime,
1370 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
1374 case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
1375 Slog.i(TAG, "Starting brightness boost.");
1377 wakeUpFromPowerKey(eventTime);
1379 mPowerManager.boostScreenBrightness(eventTime);
1384 private int getMaxMultiPressPowerCount() {
1385 if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
1388 if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
1394 private void powerLongPress() {
1395 final int behavior = getResolvedLongPressOnPowerBehavior();
1397 case LONG_PRESS_POWER_NOTHING:
1399 case LONG_PRESS_POWER_GLOBAL_ACTIONS:
1400 mPowerKeyHandled = true;
1401 if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
1402 performAuditoryFeedbackForAccessibilityIfNeed();
1404 showGlobalActionsInternal();
1406 case LONG_PRESS_POWER_SHUT_OFF:
1407 case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
1408 mPowerKeyHandled = true;
1409 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1410 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
1411 mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
1416 private void backLongPress() {
1417 mBackKeyHandled = true;
1419 switch (mLongPressOnBackBehavior) {
1420 case LONG_PRESS_BACK_NOTHING:
1422 case LONG_PRESS_BACK_GO_TO_VOICE_ASSIST:
1423 Intent intent = new Intent(Intent.ACTION_VOICE_ASSIST);
1424 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
1429 private void disposeInputConsumer(InputConsumer inputConsumer) {
1430 if (inputConsumer != null) {
1431 inputConsumer.dismiss();
1435 private void sleepPress(long eventTime) {
1436 if (mShortPressOnSleepBehavior == SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME) {
1437 launchHomeFromHotKey(false /* awakenDreams */, true /*respectKeyguard*/);
1441 private void sleepRelease(long eventTime) {
1442 switch (mShortPressOnSleepBehavior) {
1443 case SHORT_PRESS_SLEEP_GO_TO_SLEEP:
1444 case SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME:
1445 Slog.i(TAG, "sleepRelease() calling goToSleep(GO_TO_SLEEP_REASON_SLEEP_BUTTON)");
1446 mPowerManager.goToSleep(eventTime,
1447 PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON, 0);
1452 private int getResolvedLongPressOnPowerBehavior() {
1453 if (FactoryTest.isLongPressOnPowerOffEnabled()) {
1454 return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
1456 return mLongPressOnPowerBehavior;
1459 private boolean hasLongPressOnPowerBehavior() {
1460 return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;
1463 private boolean hasLongPressOnBackBehavior() {
1464 return mLongPressOnBackBehavior != LONG_PRESS_BACK_NOTHING;
1467 private void interceptScreenshotChord() {
1468 if (mScreenshotChordEnabled
1469 && mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered
1470 && !mScreenshotChordVolumeUpKeyTriggered) {
1471 final long now = SystemClock.uptimeMillis();
1472 if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
1473 && now <= mScreenshotChordPowerKeyTime
1474 + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
1475 mScreenshotChordVolumeDownKeyConsumed = true;
1476 cancelPendingPowerKeyAction();
1477 mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
1478 mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
1483 private long getScreenshotChordLongPressDelay() {
1484 if (mKeyguardDelegate.isShowing()) {
1485 // Double the time it takes to take a screenshot from the keyguard
1486 return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER *
1487 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1489 return ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout();
1492 private void cancelPendingScreenshotChordAction() {
1493 mHandler.removeCallbacks(mScreenshotRunnable);
1496 private final Runnable mEndCallLongPress = new Runnable() {
1499 mEndCallKeyHandled = true;
1500 if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
1501 performAuditoryFeedbackForAccessibilityIfNeed();
1503 showGlobalActionsInternal();
1507 private class ScreenshotRunnable implements Runnable {
1508 private int mScreenshotType = TAKE_SCREENSHOT_FULLSCREEN;
1510 public void setScreenshotType(int screenshotType) {
1511 mScreenshotType = screenshotType;
1516 takeScreenshot(mScreenshotType);
1520 private final ScreenshotRunnable mScreenshotRunnable = new ScreenshotRunnable();
1523 public void showGlobalActions() {
1524 mHandler.removeMessages(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
1525 mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
1528 Runnable mBackLongPress = new Runnable() {
1531 final Intent intent = new Intent(Intent.ACTION_MAIN);
1532 String defaultHomePackage = "com.android.launcher";
1533 intent.addCategory(Intent.CATEGORY_HOME);
1534 final ResolveInfo res = mContext.getPackageManager().resolveActivity(intent, 0);
1535 if (res.activityInfo != null && !res.activityInfo.packageName.equals("android")) {
1536 defaultHomePackage = res.activityInfo.packageName;
1538 boolean targetKilled = false;
1539 IActivityManager am = ActivityManagerNative.getDefault();
1540 List<RunningAppProcessInfo> apps = am.getRunningAppProcesses();
1541 for (RunningAppProcessInfo appInfo : apps) {
1542 int uid = appInfo.uid;
1543 // Make sure it's a foreground user application (not system,
1544 // root, phone, etc.)
1545 if (uid >= Process.FIRST_APPLICATION_UID && uid <= Process.LAST_APPLICATION_UID
1546 && appInfo.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
1547 if (appInfo.pkgList != null && (appInfo.pkgList.length > 0)) {
1548 for (String pkg : appInfo.pkgList) {
1549 if (!pkg.equals("com.android.systemui") && !pkg.equals(defaultHomePackage)) {
1550 am.forceStopPackage(pkg, UserHandle.USER_CURRENT);
1551 targetKilled = true;
1556 Process.killProcess(appInfo.pid);
1557 targetKilled = true;
1561 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1562 Toast.makeText(mContext, R.string.app_killed_message, Toast.LENGTH_SHORT).show();
1566 } catch (RemoteException remoteException) {
1567 // Do nothing; just let it go.
1572 void showGlobalActionsInternal() {
1573 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
1574 if (mGlobalActions == null) {
1575 mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
1577 final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();
1578 mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
1579 if (keyguardShowing) {
1580 // since it took two seconds of long press to bring this up,
1581 // poke the wake lock so they have some time to see the dialog.
1582 mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
1586 boolean isDeviceProvisioned() {
1587 return Settings.Global.getInt(
1588 mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
1591 boolean isUserSetupComplete() {
1592 return Settings.Secure.getIntForUser(mContext.getContentResolver(),
1593 Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
1596 private void handleShortPressOnHome() {
1597 // Turn on the connected TV and switch HDMI input if we're a HDMI playback device.
1598 getHdmiControl().turnOnTv();
1600 // If there's a dream running then use home to escape the dream
1601 // but don't actually go home.
1602 if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) {
1603 mDreamManagerInternal.stopDream(false /*immediate*/);
1608 launchHomeFromHotKey();
1612 * Creates an accessor to HDMI control service that performs the operation of
1613 * turning on TV (optional) and switching input to us. If HDMI control service
1614 * is not available or we're not a HDMI playback device, the operation is no-op.
1616 private HdmiControl getHdmiControl() {
1617 if (null == mHdmiControl) {
1618 HdmiControlManager manager = (HdmiControlManager) mContext.getSystemService(
1619 Context.HDMI_CONTROL_SERVICE);
1620 HdmiPlaybackClient client = null;
1621 if (manager != null) {
1622 client = manager.getPlaybackClient();
1624 mHdmiControl = new HdmiControl(client);
1626 return mHdmiControl;
1629 private static class HdmiControl {
1630 private final HdmiPlaybackClient mClient;
1632 private HdmiControl(HdmiPlaybackClient client) {
1636 public void turnOnTv() {
1637 if (mClient == null) {
1640 mClient.oneTouchPlay(new OneTouchPlayCallback() {
1642 public void onComplete(int result) {
1643 if (result != HdmiControlManager.RESULT_SUCCESS) {
1644 Log.w(TAG, "One touch play failed: " + result);
1651 private void triggerVirtualKeypress(final int keyCode) {
1652 InputManager im = InputManager.getInstance();
1653 long now = SystemClock.uptimeMillis();
1654 final KeyEvent downEvent = new KeyEvent(now, now, KeyEvent.ACTION_DOWN,
1655 keyCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
1656 KeyEvent.FLAG_FROM_SYSTEM, InputDevice.SOURCE_KEYBOARD);
1657 final KeyEvent upEvent = KeyEvent.changeAction(downEvent, KeyEvent.ACTION_UP);
1659 im.injectInputEvent(downEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
1660 im.injectInputEvent(upEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
1663 private void launchCameraAction() {
1664 sendCloseSystemWindows();
1665 Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null);
1666 mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT_OR_SELF,
1667 null, null, null, 0, null, null);
1670 private void showTvPictureInPictureMenu(KeyEvent event) {
1671 if (DEBUG_INPUT) Log.d(TAG, "showTvPictureInPictureMenu event=" + event);
1672 mHandler.removeMessages(MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU);
1673 Message msg = mHandler.obtainMessage(MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU);
1674 msg.setAsynchronous(true);
1678 private void showTvPictureInPictureMenuInternal() {
1679 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
1680 if (statusbar != null) {
1681 statusbar.showTvPictureInPictureMenu();
1685 private void performKeyAction(int behavior, KeyEvent event) {
1687 case KEY_ACTION_NOTHING:
1689 case KEY_ACTION_MENU:
1690 triggerVirtualKeypress(KeyEvent.KEYCODE_MENU);
1692 case KEY_ACTION_APP_SWITCH:
1695 case KEY_ACTION_SEARCH:
1696 launchAssistAction(null, event.getDeviceId());
1698 case KEY_ACTION_VOICE_SEARCH:
1699 launchAssistLongPressAction();
1701 case KEY_ACTION_IN_APP_SEARCH:
1702 triggerVirtualKeypress(KeyEvent.KEYCODE_SEARCH);
1704 case KEY_ACTION_LAUNCH_CAMERA:
1705 launchCameraAction();
1707 case KEY_ACTION_SLEEP:
1708 mPowerManager.goToSleep(SystemClock.uptimeMillis());
1715 private final Runnable mHomeDoubleTapTimeoutRunnable = new Runnable() {
1718 if (mHomeDoubleTapPending) {
1719 mHomeDoubleTapPending = false;
1720 handleShortPressOnHome();
1725 private boolean isRoundWindow() {
1726 return mContext.getResources().getConfiguration().isScreenRound();
1729 /** {@inheritDoc} */
1731 public void init(Context context, IWindowManager windowManager,
1732 WindowManagerFuncs windowManagerFuncs) {
1734 mWindowManager = windowManager;
1735 mWindowManagerFuncs = windowManagerFuncs;
1736 mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
1737 mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
1738 mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
1739 mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
1740 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
1741 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
1742 mHasFeatureWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH);
1744 // Init display burn-in protection
1745 boolean burnInProtectionEnabled = context.getResources().getBoolean(
1746 com.android.internal.R.bool.config_enableBurnInProtection);
1747 // Allow a system property to override this. Used by developer settings.
1748 boolean burnInProtectionDevMode =
1749 SystemProperties.getBoolean("persist.debug.force_burn_in", false);
1750 if (burnInProtectionEnabled || burnInProtectionDevMode) {
1751 final int minHorizontal;
1752 final int maxHorizontal;
1753 final int minVertical;
1754 final int maxVertical;
1755 final int maxRadius;
1756 if (burnInProtectionDevMode) {
1761 maxRadius = (isRoundWindow()) ? 6 : -1;
1763 Resources resources = context.getResources();
1764 minHorizontal = resources.getInteger(
1765 com.android.internal.R.integer.config_burnInProtectionMinHorizontalOffset);
1766 maxHorizontal = resources.getInteger(
1767 com.android.internal.R.integer.config_burnInProtectionMaxHorizontalOffset);
1768 minVertical = resources.getInteger(
1769 com.android.internal.R.integer.config_burnInProtectionMinVerticalOffset);
1770 maxVertical = resources.getInteger(
1771 com.android.internal.R.integer.config_burnInProtectionMaxVerticalOffset);
1772 maxRadius = resources.getInteger(
1773 com.android.internal.R.integer.config_burnInProtectionMaxRadius);
1775 mBurnInProtectionHelper = new BurnInProtectionHelper(
1776 context, minHorizontal, maxHorizontal, minVertical, maxVertical, maxRadius);
1779 mHandler = new PolicyHandler();
1780 mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
1781 mOrientationListener = new MyOrientationListener(mContext, mHandler);
1783 mOrientationListener.setCurrentRotation(windowManager.getRotation());
1784 } catch (RemoteException ex) { }
1785 mSettingsObserver = new SettingsObserver(mHandler);
1786 mSettingsObserver.observe();
1787 mShortcutManager = new ShortcutManager(context);
1788 mUiMode = context.getResources().getInteger(
1789 com.android.internal.R.integer.config_defaultUiModeType);
1790 mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
1791 mHomeIntent.addCategory(Intent.CATEGORY_HOME);
1792 mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1793 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1794 mEnableCarDockHomeCapture = context.getResources().getBoolean(
1795 com.android.internal.R.bool.config_enableCarDockHomeLaunch);
1796 mCarDockIntent = new Intent(Intent.ACTION_MAIN, null);
1797 mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
1798 mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1799 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1800 mDeskDockIntent = new Intent(Intent.ACTION_MAIN, null);
1801 mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
1802 mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1803 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1805 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1806 mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1807 "PhoneWindowManager.mBroadcastWakeLock");
1808 mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1809 "PhoneWindowManager.mPowerKeyWakeLock");
1810 mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
1811 mSupportAutoRotation = mContext.getResources().getBoolean(
1812 com.android.internal.R.bool.config_supportAutoRotation);
1813 mLidOpenRotation = readRotation(
1814 com.android.internal.R.integer.config_lidOpenRotation);
1815 mCarDockRotation = readRotation(
1816 com.android.internal.R.integer.config_carDockRotation);
1817 mDeskDockRotation = readRotation(
1818 com.android.internal.R.integer.config_deskDockRotation);
1819 mUndockedHdmiRotation = readRotation(
1820 com.android.internal.R.integer.config_undockedHdmiRotation);
1821 mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
1822 com.android.internal.R.bool.config_carDockEnablesAccelerometer);
1823 mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
1824 com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
1825 mLidKeyboardAccessibility = mContext.getResources().getInteger(
1826 com.android.internal.R.integer.config_lidKeyboardAccessibility);
1827 mLidNavigationAccessibility = mContext.getResources().getInteger(
1828 com.android.internal.R.integer.config_lidNavigationAccessibility);
1829 mLidControlsScreenLock = mContext.getResources().getBoolean(
1830 com.android.internal.R.bool.config_lidControlsScreenLock);
1831 mLidControlsSleep = mContext.getResources().getBoolean(
1832 com.android.internal.R.bool.config_lidControlsSleep);
1833 mTranslucentDecorEnabled = mContext.getResources().getBoolean(
1834 com.android.internal.R.bool.config_enableTranslucentDecor);
1836 mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
1837 com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
1838 mAllowTheaterModeWakeFromPowerKey = mAllowTheaterModeWakeFromKey
1839 || mContext.getResources().getBoolean(
1840 com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey);
1841 mAllowTheaterModeWakeFromMotion = mContext.getResources().getBoolean(
1842 com.android.internal.R.bool.config_allowTheaterModeWakeFromMotion);
1843 mAllowTheaterModeWakeFromMotionWhenNotDreaming = mContext.getResources().getBoolean(
1844 com.android.internal.R.bool.config_allowTheaterModeWakeFromMotionWhenNotDreaming);
1845 mAllowTheaterModeWakeFromCameraLens = mContext.getResources().getBoolean(
1846 com.android.internal.R.bool.config_allowTheaterModeWakeFromCameraLens);
1847 mAllowTheaterModeWakeFromLidSwitch = mContext.getResources().getBoolean(
1848 com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch);
1849 mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean(
1850 com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture);
1852 mGoToSleepOnButtonPressTheaterMode = mContext.getResources().getBoolean(
1853 com.android.internal.R.bool.config_goToSleepOnButtonPressTheaterMode);
1855 mSupportLongPressPowerWhenNonInteractive = mContext.getResources().getBoolean(
1856 com.android.internal.R.bool.config_supportLongPressPowerWhenNonInteractive);
1858 mLongPressOnBackBehavior = mContext.getResources().getInteger(
1859 com.android.internal.R.integer.config_longPressOnBackBehavior);
1861 mShortPressOnPowerBehavior = mContext.getResources().getInteger(
1862 com.android.internal.R.integer.config_shortPressOnPowerBehavior);
1863 mLongPressOnPowerBehavior = mContext.getResources().getInteger(
1864 com.android.internal.R.integer.config_longPressOnPowerBehavior);
1865 mDoublePressOnPowerBehavior = mContext.getResources().getInteger(
1866 com.android.internal.R.integer.config_doublePressOnPowerBehavior);
1867 mTriplePressOnPowerBehavior = mContext.getResources().getInteger(
1868 com.android.internal.R.integer.config_triplePressOnPowerBehavior);
1869 mShortPressOnSleepBehavior = mContext.getResources().getInteger(
1870 com.android.internal.R.integer.config_shortPressOnSleepBehavior);
1872 mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION;
1874 mDeviceHardwareKeys = mContext.getResources().getInteger(
1875 com.android.internal.R.integer.config_deviceHardwareKeys);
1876 mBackKillTimeout = mContext.getResources().getInteger(
1877 com.android.internal.R.integer.config_backKillTimeout);
1879 updateKeyAssignments();
1881 mAccessibilityManager = (AccessibilityManager) context.getSystemService(
1882 Context.ACCESSIBILITY_SERVICE);
1884 // register for dock events
1885 IntentFilter filter = new IntentFilter();
1886 filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
1887 filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
1888 filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
1889 filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
1890 filter.addAction(Intent.ACTION_DOCK_EVENT);
1891 Intent intent = context.registerReceiver(mDockReceiver, filter);
1892 if (intent != null) {
1893 // Retrieve current sticky dock event broadcast.
1894 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
1895 Intent.EXTRA_DOCK_STATE_UNDOCKED);
1898 // register for dream-related broadcasts
1899 filter = new IntentFilter();
1900 filter.addAction(Intent.ACTION_DREAMING_STARTED);
1901 filter.addAction(Intent.ACTION_DREAMING_STOPPED);
1902 context.registerReceiver(mDreamReceiver, filter);
1904 // register for multiuser-relevant broadcasts
1905 filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
1906 context.registerReceiver(mMultiuserReceiver, filter);
1908 // monitor for system gestures
1909 mSystemGestures = new SystemGesturesPointerEventListener(context,
1910 new SystemGesturesPointerEventListener.Callbacks() {
1912 public void onSwipeFromTop() {
1913 if (mStatusBar != null) {
1914 requestTransientBars(mStatusBar);
1918 public void onSwipeFromBottom() {
1919 if (mNavigationBar != null && mNavigationBarOnBottom) {
1920 requestTransientBars(mNavigationBar);
1924 public void onSwipeFromRight() {
1925 if (mNavigationBar != null && !mNavigationBarOnBottom) {
1926 requestTransientBars(mNavigationBar);
1930 public void onFling(int duration) {
1931 if (mPowerManagerInternal != null) {
1932 mPowerManagerInternal.powerHint(
1933 PowerManagerInternal.POWER_HINT_INTERACTION, duration);
1937 public void onDebug() {
1941 public void onDown() {
1942 mOrientationListener.onTouchStart();
1945 public void onUpOrCancel() {
1946 mOrientationListener.onTouchEnd();
1949 public void onMouseHoverAtTop() {
1950 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
1951 Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
1952 msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
1953 mHandler.sendMessageDelayed(msg, 500);
1956 public void onMouseHoverAtBottom() {
1957 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
1958 Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
1959 msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
1960 mHandler.sendMessageDelayed(msg, 500);
1963 public void onMouseLeaveFromEdge() {
1964 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
1967 mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext);
1968 mWindowManagerFuncs.registerPointerEventListener(mSystemGestures);
1970 mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
1972 /* Register for WIFI Display Intents */
1973 IntentFilter wifiDisplayFilter = new IntentFilter(ACTION_WIFI_DISPLAY_VIDEO);
1974 Intent wifidisplayIntent = context.registerReceiver(
1975 mWifiDisplayReceiver, wifiDisplayFilter);
1976 mLongPressVibePattern = getLongIntArray(mContext.getResources(),
1977 com.android.internal.R.array.config_longPressVibePattern);
1978 mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(),
1979 com.android.internal.R.array.config_virtualKeyVibePattern);
1980 mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(),
1981 com.android.internal.R.array.config_keyboardTapVibePattern);
1982 mClockTickVibePattern = getLongIntArray(mContext.getResources(),
1983 com.android.internal.R.array.config_clockTickVibePattern);
1984 mCalendarDateVibePattern = getLongIntArray(mContext.getResources(),
1985 com.android.internal.R.array.config_calendarDateVibePattern);
1986 mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
1987 com.android.internal.R.array.config_safeModeDisabledVibePattern);
1988 mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
1989 com.android.internal.R.array.config_safeModeEnabledVibePattern);
1990 mContextClickVibePattern = getLongIntArray(mContext.getResources(),
1991 com.android.internal.R.array.config_contextClickVibePattern);
1993 mScreenshotChordEnabled = mContext.getResources().getBoolean(
1994 com.android.internal.R.bool.config_enableScreenshotChord);
1996 mGlobalKeyManager = new GlobalKeyManager(mContext);
1998 // Controls rotation and the like.
1999 initializeHdmiState();
2001 // Match current screen state.
2002 if (!mPowerManager.isInteractive()) {
2003 startedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
2004 finishedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
2007 mWindowManagerInternal.registerAppTransitionListener(
2008 mStatusBarController.getAppTransitionListener());
2010 String deviceKeyHandlerLib = mContext.getResources().getString(
2011 com.android.internal.R.string.config_deviceKeyHandlerLib);
2013 String deviceKeyHandlerClass = mContext.getResources().getString(
2014 com.android.internal.R.string.config_deviceKeyHandlerClass);
2016 if (!deviceKeyHandlerLib.isEmpty() && !deviceKeyHandlerClass.isEmpty()) {
2017 DexClassLoader loader = new DexClassLoader(deviceKeyHandlerLib,
2018 new ContextWrapper(mContext).getCacheDir().getAbsolutePath(),
2020 ClassLoader.getSystemClassLoader());
2022 Class<?> klass = loader.loadClass(deviceKeyHandlerClass);
2023 Constructor<?> constructor = klass.getConstructor(Context.class);
2024 mDeviceKeyHandler = (DeviceKeyHandler) constructor.newInstance(
2026 if(DEBUG) Slog.d(TAG, "Device key handler loaded");
2027 } catch (Exception e) {
2028 Slog.w(TAG, "Could not instantiate device key handler "
2029 + deviceKeyHandlerClass + " from class "
2030 + deviceKeyHandlerLib, e);
2036 private void updateKeyAssignments() {
2037 final boolean hasMenu = (mDeviceHardwareKeys & KEY_MASK_MENU) != 0;
2038 final boolean hasHome = (mDeviceHardwareKeys & KEY_MASK_HOME) != 0;
2039 final boolean hasAssist = (mDeviceHardwareKeys & KEY_MASK_ASSIST) != 0;
2040 final boolean hasAppSwitch = (mDeviceHardwareKeys & KEY_MASK_APP_SWITCH) != 0;
2041 final ContentResolver resolver = mContext.getContentResolver();
2043 // Initialize all assignments to sane defaults.
2044 mPressOnMenuBehavior = KEY_ACTION_MENU;
2046 mLongPressOnMenuBehavior = mContext.getResources().getInteger(
2047 com.android.internal.R.integer.config_longPressOnMenuBehavior);
2049 if (mLongPressOnMenuBehavior == KEY_ACTION_NOTHING &&
2050 (hasMenu && !hasAssist)) {
2051 mLongPressOnMenuBehavior = KEY_ACTION_SEARCH;
2053 mPressOnAssistBehavior = KEY_ACTION_SEARCH;
2054 mLongPressOnAssistBehavior = KEY_ACTION_VOICE_SEARCH;
2055 mPressOnAppSwitchBehavior = KEY_ACTION_APP_SWITCH;
2056 mLongPressOnAppSwitchBehavior = mContext.getResources().getInteger(
2057 com.android.internal.R.integer.config_longPressOnAppSwitchBehavior);
2059 mLongPressOnHomeBehavior = mContext.getResources().getInteger(
2060 com.android.internal.R.integer.config_longPressOnHomeBehavior);
2061 if (mLongPressOnHomeBehavior < KEY_ACTION_NOTHING ||
2062 mLongPressOnHomeBehavior > KEY_ACTION_SLEEP) {
2063 mLongPressOnHomeBehavior = KEY_ACTION_NOTHING;
2066 mDoubleTapOnHomeBehavior = res.getInteger(
2067 com.android.internal.R.integer.config_doubleTapOnHomeBehavior);
2068 if (mDoubleTapOnHomeBehavior < KEY_ACTION_NOTHING ||
2069 mDoubleTapOnHomeBehavior > KEY_ACTION_SLEEP) {
2070 mDoubleTapOnHomeBehavior = KEY_ACTION_NOTHING;
2073 // Check for custom assignments and whether KEY_ACTION_MENU is assigned.
2075 mLongPressOnHomeBehavior = CMSettings.System.getIntForUser(resolver,
2076 CMSettings.System.KEY_HOME_LONG_PRESS_ACTION,
2077 mLongPressOnHomeBehavior, UserHandle.USER_CURRENT);
2078 mDoubleTapOnHomeBehavior = CMSettings.System.getIntForUser(resolver,
2079 CMSettings.System.KEY_HOME_DOUBLE_TAP_ACTION,
2080 mDoubleTapOnHomeBehavior, UserHandle.USER_CURRENT);
2083 mPressOnMenuBehavior = CMSettings.System.getIntForUser(resolver,
2084 CMSettings.System.KEY_MENU_ACTION,
2085 mPressOnMenuBehavior, UserHandle.USER_CURRENT);
2086 mLongPressOnMenuBehavior = CMSettings.System.getIntForUser(resolver,
2087 CMSettings.System.KEY_MENU_LONG_PRESS_ACTION,
2088 mLongPressOnMenuBehavior, UserHandle.USER_CURRENT);
2091 mPressOnAssistBehavior = CMSettings.System.getIntForUser(resolver,
2092 CMSettings.System.KEY_ASSIST_ACTION,
2093 mPressOnAssistBehavior, UserHandle.USER_CURRENT);
2094 mLongPressOnAssistBehavior = CMSettings.System.getIntForUser(resolver,
2095 CMSettings.System.KEY_ASSIST_LONG_PRESS_ACTION,
2096 mLongPressOnAssistBehavior, UserHandle.USER_CURRENT);
2099 mPressOnAppSwitchBehavior = CMSettings.System.getIntForUser(resolver,
2100 CMSettings.System.KEY_APP_SWITCH_ACTION,
2101 mPressOnAppSwitchBehavior, UserHandle.USER_CURRENT);
2102 mLongPressOnAppSwitchBehavior = CMSettings.System.getIntForUser(resolver,
2103 CMSettings.System.KEY_APP_SWITCH_LONG_PRESS_ACTION,
2104 mLongPressOnAppSwitchBehavior, UserHandle.USER_CURRENT);
2107 mShortPressWindowBehavior = SHORT_PRESS_WINDOW_NOTHING;
2108 if (mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
2109 mShortPressWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE;
2112 mNavBarOpacityMode = res.getInteger(
2113 com.android.internal.R.integer.config_navBarOpacityMode);
2117 public void setInitialDisplaySize(Display display, int width, int height, int density) {
2118 // This method might be called before the policy has been fully initialized
2119 // or for other displays we don't care about.
2120 if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) {
2125 final Resources res = mContext.getResources();
2126 int shortSize, longSize;
2127 if (width > height) {
2130 mLandscapeRotation = Surface.ROTATION_0;
2131 mSeascapeRotation = Surface.ROTATION_180;
2132 if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
2133 mPortraitRotation = Surface.ROTATION_90;
2134 mUpsideDownRotation = Surface.ROTATION_270;
2136 mPortraitRotation = Surface.ROTATION_270;
2137 mUpsideDownRotation = Surface.ROTATION_90;
2142 mPortraitRotation = Surface.ROTATION_0;
2143 mUpsideDownRotation = Surface.ROTATION_180;
2144 if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
2145 mLandscapeRotation = Surface.ROTATION_270;
2146 mSeascapeRotation = Surface.ROTATION_90;
2148 mLandscapeRotation = Surface.ROTATION_90;
2149 mSeascapeRotation = Surface.ROTATION_270;
2153 // SystemUI (status bar) layout policy
2154 int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
2155 int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
2157 // Allow the navigation bar to move on non-square small devices (phones).
2158 mNavigationBarCanMove = width != height && shortSizeDp < 600;
2160 mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
2162 // Allow a system property to override this. Used by the emulator.
2163 // See also hasNavigationBar().
2164 String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
2165 if ("1".equals(navBarOverride)) {
2166 mHasNavigationBar = false;
2167 } else if ("0".equals(navBarOverride)) {
2168 mHasNavigationBar = true;
2171 // For demo purposes, allow the rotation of the HDMI display to be controlled.
2172 // By default, HDMI locks rotation to landscape.
2173 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
2174 mDemoHdmiRotation = mPortraitRotation;
2176 mDemoHdmiRotation = mLandscapeRotation;
2178 mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
2180 // For demo purposes, allow the rotation of the remote display to be controlled.
2181 // By default, remote display locks rotation to landscape.
2182 if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
2183 mDemoRotation = mPortraitRotation;
2185 mDemoRotation = mLandscapeRotation;
2187 mDemoRotationLock = SystemProperties.getBoolean(
2188 "persist.demo.rotationlock", false);
2190 // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
2191 // http://developer.android.com/guide/practices/screens_support.html#range
2192 mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 &&
2193 res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
2194 // For debug purposes the next line turns this feature off with:
2195 // $ adb shell setprop config.override_forced_orient true
2196 // $ adb shell wm size reset
2197 !"true".equals(SystemProperties.get("config.override_forced_orient"));
2201 * @return whether the navigation bar can be hidden, e.g. the device has a
2202 * navigation bar and touch exploration is not enabled
2204 private boolean canHideNavigationBar() {
2205 return mHasNavigationBar;
2209 public boolean isDefaultOrientationForced() {
2210 return mForceDefaultOrientation;
2214 public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) {
2215 if (display.getDisplayId() == Display.DEFAULT_DISPLAY) {
2216 mOverscanLeft = left;
2218 mOverscanRight = right;
2219 mOverscanBottom = bottom;
2223 public void updateSettings() {
2224 ContentResolver resolver = mContext.getContentResolver();
2225 boolean updateRotation = false;
2226 int mDeviceHardwareWakeKeys = mContext.getResources().getInteger(
2227 com.android.internal.R.integer.config_deviceHardwareWakeKeys);
2228 synchronized (mLock) {
2229 mEndcallBehavior = Settings.System.getIntForUser(resolver,
2230 Settings.System.END_BUTTON_BEHAVIOR,
2231 Settings.System.END_BUTTON_BEHAVIOR_DEFAULT,
2232 UserHandle.USER_CURRENT);
2233 mIncallPowerBehavior = CMSettings.Secure.getIntForUser(resolver,
2234 CMSettings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
2235 CMSettings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT,
2236 UserHandle.USER_CURRENT);
2237 mHomeWakeScreen = (CMSettings.System.getIntForUser(resolver,
2238 CMSettings.System.HOME_WAKE_SCREEN, 1, UserHandle.USER_CURRENT) == 1) &&
2239 ((mDeviceHardwareWakeKeys & KEY_MASK_HOME) != 0);
2240 mBackWakeScreen = (CMSettings.System.getIntForUser(resolver,
2241 CMSettings.System.BACK_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1) &&
2242 ((mDeviceHardwareWakeKeys & KEY_MASK_BACK) != 0);
2243 mMenuWakeScreen = (CMSettings.System.getIntForUser(resolver,
2244 CMSettings.System.MENU_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1) &&
2245 ((mDeviceHardwareWakeKeys & KEY_MASK_MENU) != 0);
2246 mAssistWakeScreen = (CMSettings.System.getIntForUser(resolver,
2247 CMSettings.System.ASSIST_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1) &&
2248 ((mDeviceHardwareWakeKeys & KEY_MASK_ASSIST) != 0);
2249 mAppSwitchWakeScreen = (CMSettings.System.getIntForUser(resolver,
2250 CMSettings.System.APP_SWITCH_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1) &&
2251 ((mDeviceHardwareWakeKeys & KEY_MASK_APP_SWITCH) != 0);
2252 mCameraWakeScreen = (CMSettings.System.getIntForUser(resolver,
2253 CMSettings.System.CAMERA_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1) &&
2254 ((mDeviceHardwareWakeKeys & KEY_MASK_CAMERA) != 0);
2255 mCameraSleepOnRelease = (CMSettings.System.getIntForUser(resolver,
2256 CMSettings.System.CAMERA_SLEEP_ON_RELEASE, 0, UserHandle.USER_CURRENT) == 1);
2257 mCameraLaunch = (CMSettings.System.getIntForUser(resolver,
2258 CMSettings.System.CAMERA_LAUNCH, 0, UserHandle.USER_CURRENT) == 1);
2259 mVolumeWakeScreen = (CMSettings.System.getIntForUser(resolver,
2260 CMSettings.System.VOLUME_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1) &&
2261 ((mDeviceHardwareWakeKeys & KEY_MASK_VOLUME) != 0);
2262 mVolBtnMusicControls = (Settings.System.getIntForUser(resolver,
2263 Settings.System.VOLBTN_MUSIC_CONTROLS, 1, UserHandle.USER_CURRENT) == 1);
2265 // Configure wake gesture.
2266 boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver,
2267 Settings.Secure.WAKE_GESTURE_ENABLED, 0,
2268 UserHandle.USER_CURRENT) != 0;
2269 if (mWakeGestureEnabledSetting != wakeGestureEnabledSetting) {
2270 mWakeGestureEnabledSetting = wakeGestureEnabledSetting;
2271 updateWakeGestureListenerLp();
2274 updateKeyAssignments();
2276 // Configure rotation lock.
2277 int userRotation = Settings.System.getIntForUser(resolver,
2278 Settings.System.USER_ROTATION, Surface.ROTATION_0,
2279 UserHandle.USER_CURRENT);
2280 if (mUserRotation != userRotation) {
2281 mUserRotation = userRotation;
2282 updateRotation = true;
2284 int userRotationMode = Settings.System.getIntForUser(resolver,
2285 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
2286 WindowManagerPolicy.USER_ROTATION_FREE :
2287 WindowManagerPolicy.USER_ROTATION_LOCKED;
2288 if (mUserRotationMode != userRotationMode) {
2289 mUserRotationMode = userRotationMode;
2290 updateRotation = true;
2291 updateOrientationListenerLp();
2295 int pointerLocation = Settings.System.getIntForUser(resolver,
2296 Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT);
2297 if (mPointerLocationMode != pointerLocation) {
2298 mPointerLocationMode = pointerLocation;
2299 mHandler.sendEmptyMessage(pointerLocation != 0 ?
2300 MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
2303 // use screen off timeout setting as the timeout for the lockscreen
2304 mLockScreenTimeout = Settings.System.getIntForUser(resolver,
2305 Settings.System.SCREEN_OFF_TIMEOUT, 0, UserHandle.USER_CURRENT);
2306 String imId = Settings.Secure.getStringForUser(resolver,
2307 Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.USER_CURRENT);
2308 boolean hasSoftInput = imId != null && imId.length() > 0;
2309 if (mHasSoftInput != hasSoftInput) {
2310 mHasSoftInput = hasSoftInput;
2311 updateRotation = true;
2313 if (mImmersiveModeConfirmation != null) {
2314 mImmersiveModeConfirmation.loadSetting(mCurrentUserId);
2318 mVolumeWakeScreen = (Settings.System.getIntForUser(resolver,
2319 Settings.System.VOLUME_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1);
2322 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
2323 PolicyControl.reloadFromSetting(mContext);
2325 if (updateRotation) {
2326 updateRotation(true);
2330 private void updateWakeGestureListenerLp() {
2331 if (shouldEnableWakeGestureLp()) {
2332 mWakeGestureListener.requestWakeUpTrigger();
2334 mWakeGestureListener.cancelWakeUpTrigger();
2338 private boolean shouldEnableWakeGestureLp() {
2339 return mWakeGestureEnabledSetting && !mAwake
2340 && (!mLidControlsSleep || mLidState != LID_CLOSED)
2341 && mWakeGestureListener.isSupported();
2344 private void enablePointerLocation() {
2345 if (mPointerLocationView == null) {
2346 mPointerLocationView = new PointerLocationView(mContext);
2347 mPointerLocationView.setPrintCoords(false);
2348 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
2349 WindowManager.LayoutParams.MATCH_PARENT,
2350 WindowManager.LayoutParams.MATCH_PARENT);
2351 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
2352 lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
2353 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
2354 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2355 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
2356 if (ActivityManager.isHighEndGfx()) {
2357 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
2359 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
2361 lp.format = PixelFormat.TRANSLUCENT;
2362 lp.setTitle("PointerLocation");
2363 WindowManager wm = (WindowManager)
2364 mContext.getSystemService(Context.WINDOW_SERVICE);
2365 lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
2366 wm.addView(mPointerLocationView, lp);
2367 mWindowManagerFuncs.registerPointerEventListener(mPointerLocationView);
2371 private void disablePointerLocation() {
2372 if (mPointerLocationView != null) {
2373 mWindowManagerFuncs.unregisterPointerEventListener(mPointerLocationView);
2374 WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
2375 wm.removeView(mPointerLocationView);
2376 mPointerLocationView = null;
2380 private int readRotation(int resID) {
2382 int rotation = mContext.getResources().getInteger(resID);
2385 return Surface.ROTATION_0;
2387 return Surface.ROTATION_90;
2389 return Surface.ROTATION_180;
2391 return Surface.ROTATION_270;
2393 } catch (Resources.NotFoundException e) {
2399 /** {@inheritDoc} */
2401 public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) {
2402 int type = attrs.type;
2404 outAppOp[0] = AppOpsManager.OP_NONE;
2406 if (!((type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW)
2407 || (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW)
2408 || (type >= FIRST_SYSTEM_WINDOW && type <= LAST_SYSTEM_WINDOW))) {
2409 return WindowManagerGlobal.ADD_INVALID_TYPE;
2412 if (type < FIRST_SYSTEM_WINDOW || type > LAST_SYSTEM_WINDOW) {
2413 // Window manager will make sure these are okay.
2414 return WindowManagerGlobal.ADD_OKAY;
2416 String permission = null;
2419 // XXX right now the app process has complete control over
2420 // this... should introduce a token to let the system
2421 // monitor/control what they are doing.
2422 outAppOp[0] = AppOpsManager.OP_TOAST_WINDOW;
2425 case TYPE_INPUT_METHOD:
2426 case TYPE_WALLPAPER:
2427 case TYPE_PRIVATE_PRESENTATION:
2428 case TYPE_VOICE_INTERACTION:
2429 case TYPE_ACCESSIBILITY_OVERLAY:
2430 case TYPE_QS_DIALOG:
2431 // The window manager will check these.
2434 case TYPE_PRIORITY_PHONE:
2435 case TYPE_SYSTEM_ALERT:
2436 case TYPE_SYSTEM_ERROR:
2437 case TYPE_SYSTEM_OVERLAY:
2438 permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
2439 outAppOp[0] = AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
2442 permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
2444 if (permission != null) {
2445 if (android.Manifest.permission.SYSTEM_ALERT_WINDOW.equals(permission)) {
2446 final int callingUid = Binder.getCallingUid();
2447 // system processes will be automatically allowed privilege to draw
2448 if (callingUid == Process.SYSTEM_UID) {
2449 return WindowManagerGlobal.ADD_OKAY;
2452 // check if user has enabled this operation. SecurityException will be thrown if
2453 // this app has not been allowed by the user
2454 final int mode = mAppOpsManager.checkOpNoThrow(outAppOp[0], callingUid,
2457 case AppOpsManager.MODE_ALLOWED:
2458 case AppOpsManager.MODE_IGNORED:
2459 // although we return ADD_OKAY for MODE_IGNORED, the added window will
2460 // actually be hidden in WindowManagerService
2461 return WindowManagerGlobal.ADD_OKAY;
2462 case AppOpsManager.MODE_ERRORED:
2464 ApplicationInfo appInfo = mContext.getPackageManager()
2465 .getApplicationInfo(attrs.packageName,
2466 UserHandle.getUserId(callingUid));
2467 // Don't crash legacy apps
2468 if (appInfo.targetSdkVersion < Build.VERSION_CODES.M) {
2469 return WindowManagerGlobal.ADD_OKAY;
2471 } catch (PackageManager.NameNotFoundException e) {
2474 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
2476 // in the default mode, we will make a decision here based on
2477 // checkCallingPermission()
2478 if (mContext.checkCallingPermission(permission) !=
2479 PackageManager.PERMISSION_GRANTED) {
2480 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
2482 return WindowManagerGlobal.ADD_OKAY;
2487 if (mContext.checkCallingOrSelfPermission(permission)
2488 != PackageManager.PERMISSION_GRANTED) {
2489 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
2492 return WindowManagerGlobal.ADD_OKAY;
2496 public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) {
2498 // If this switch statement is modified, modify the comment in the declarations of
2499 // the type in {@link WindowManager.LayoutParams} as well.
2500 switch (attrs.type) {
2502 // These are the windows that by default are shown only to the user that created
2503 // them. If this needs to be overridden, set
2504 // {@link WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS} in
2505 // {@link WindowManager.LayoutParams}. Note that permission
2506 // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well.
2507 if ((attrs.privateFlags & PRIVATE_FLAG_SHOW_FOR_ALL_USERS) == 0) {
2512 // These are the windows that by default are shown to all users. However, to
2513 // protect against spoofing, check permissions below.
2514 case TYPE_APPLICATION_STARTING:
2515 case TYPE_BOOT_PROGRESS:
2516 case TYPE_DISPLAY_OVERLAY:
2517 case TYPE_INPUT_CONSUMER:
2518 case TYPE_KEYGUARD_SCRIM:
2519 case TYPE_KEYGUARD_DIALOG:
2520 case TYPE_MAGNIFICATION_OVERLAY:
2521 case TYPE_NAVIGATION_BAR:
2522 case TYPE_NAVIGATION_BAR_PANEL:
2525 case TYPE_PRIORITY_PHONE:
2526 case TYPE_SEARCH_BAR:
2527 case TYPE_STATUS_BAR:
2528 case TYPE_STATUS_BAR_PANEL:
2529 case TYPE_STATUS_BAR_SUB_PANEL:
2530 case TYPE_SYSTEM_DIALOG:
2531 case TYPE_VOLUME_OVERLAY:
2532 case TYPE_PRIVATE_PRESENTATION:
2533 case TYPE_DOCK_DIVIDER:
2537 // Check if third party app has set window to system window type.
2538 return mContext.checkCallingOrSelfPermission(
2539 android.Manifest.permission.INTERNAL_SYSTEM_WINDOW)
2540 != PackageManager.PERMISSION_GRANTED;
2544 public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
2545 switch (attrs.type) {
2546 case TYPE_SYSTEM_OVERLAY:
2547 case TYPE_SECURE_SYSTEM_OVERLAY:
2548 // These types of windows can't receive input events.
2549 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2550 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
2551 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
2553 case TYPE_STATUS_BAR:
2555 // If the Keyguard is in a hidden state (occluded by another window), we force to
2556 // remove the wallpaper and keyguard flag so that any change in-flight after setting
2557 // the keyguard as occluded wouldn't set these flags again.
2558 // See {@link #processKeyguardSetHiddenResultLw}.
2559 if (mKeyguardHidden) {
2560 attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
2561 attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2566 if (attrs.type != TYPE_STATUS_BAR) {
2567 // The status bar is the only window allowed to exhibit keyguard behavior.
2568 attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2571 if (ActivityManager.isHighEndGfx()) {
2572 if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
2573 attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
2575 final boolean forceWindowDrawsStatusBarBackground =
2576 (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND)
2578 if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
2579 || forceWindowDrawsStatusBarBackground
2580 && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) {
2581 attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2586 void readLidState() {
2587 mLidState = mWindowManagerFuncs.getLidState();
2590 private void readCameraLensCoverState() {
2591 mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState();
2594 private boolean isHidden(int accessibilityMode) {
2595 switch (accessibilityMode) {
2597 return mLidState == LID_CLOSED;
2599 return mLidState == LID_OPEN;
2605 private boolean isBuiltInKeyboardVisible() {
2606 return mHaveBuiltInKeyboard && !isHidden(mLidKeyboardAccessibility);
2609 /** {@inheritDoc} */
2611 public void adjustConfigurationLw(Configuration config, int keyboardPresence,
2612 int navigationPresence) {
2613 mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0;
2617 if (config.keyboard == Configuration.KEYBOARD_NOKEYS
2618 || (keyboardPresence == PRESENCE_INTERNAL
2619 && isHidden(mLidKeyboardAccessibility))) {
2620 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
2621 if (!mHasSoftInput) {
2622 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
2626 if (config.navigation == Configuration.NAVIGATION_NONAV
2627 || (navigationPresence == PRESENCE_INTERNAL
2628 && isHidden(mLidNavigationAccessibility))) {
2629 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
2634 public void onConfigurationChanged() {
2635 final Resources res = mContext.getResources();
2638 res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
2640 // Height of the navigation bar when presented horizontally at bottom
2641 mNavigationBarHeightForRotationDefault[mPortraitRotation] =
2642 mNavigationBarHeightForRotationDefault[mUpsideDownRotation] =
2643 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
2644 mNavigationBarHeightForRotationDefault[mLandscapeRotation] =
2645 mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize(
2646 com.android.internal.R.dimen.navigation_bar_height_landscape);
2648 // Width of the navigation bar when presented vertically along one side
2649 mNavigationBarWidthForRotationDefault[mPortraitRotation] =
2650 mNavigationBarWidthForRotationDefault[mUpsideDownRotation] =
2651 mNavigationBarWidthForRotationDefault[mLandscapeRotation] =
2652 mNavigationBarWidthForRotationDefault[mSeascapeRotation] =
2653 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
2655 // Height of the navigation bar when presented horizontally at bottom
2656 mNavigationBarHeightForRotationInCarMode[mPortraitRotation] =
2657 mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] =
2658 res.getDimensionPixelSize(
2659 com.android.internal.R.dimen.navigation_bar_height_car_mode);
2660 mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] =
2661 mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize(
2662 com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode);
2664 // Width of the navigation bar when presented vertically along one side
2665 mNavigationBarWidthForRotationInCarMode[mPortraitRotation] =
2666 mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] =
2667 mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] =
2668 mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] =
2669 res.getDimensionPixelSize(
2670 com.android.internal.R.dimen.navigation_bar_width_car_mode);
2673 /** {@inheritDoc} */
2675 public int windowTypeToLayerLw(int type) {
2676 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
2680 case TYPE_PRIVATE_PRESENTATION:
2682 case TYPE_WALLPAPER:
2683 // wallpaper is at the bottom, though the window manager may move it.
2685 case TYPE_DOCK_DIVIDER:
2687 case TYPE_QS_DIALOG:
2691 case TYPE_SEARCH_BAR:
2692 case TYPE_VOICE_INTERACTION_STARTING:
2694 case TYPE_VOICE_INTERACTION:
2695 // voice interaction layer is almost immediately above apps.
2697 case TYPE_INPUT_CONSUMER:
2699 case TYPE_SYSTEM_DIALOG:
2702 // toasts and the plugged-in battery thing
2704 case TYPE_PRIORITY_PHONE:
2705 // SIM errors and unlock. Not sure if this really should be in a high layer.
2708 // used for Dreams (screensavers with TYPE_DREAM windows)
2710 case TYPE_SYSTEM_ALERT:
2711 // like the ANR / app crashed dialogs
2713 case TYPE_INPUT_METHOD:
2714 // on-screen keyboards and other such input method user interfaces go here.
2716 case TYPE_INPUT_METHOD_DIALOG:
2717 // on-screen keyboards and other such input method user interfaces go here.
2719 case TYPE_KEYGUARD_SCRIM:
2720 // the safety window that shows behind keyguard while keyguard is starting
2722 case TYPE_STATUS_BAR_SUB_PANEL:
2724 case TYPE_STATUS_BAR:
2726 case TYPE_STATUS_BAR_PANEL:
2728 case TYPE_KEYGUARD_DIALOG:
2730 case TYPE_VOLUME_OVERLAY:
2731 // the on-screen volume indicator and controller shown when the user
2732 // changes the device volume
2734 case TYPE_SYSTEM_OVERLAY:
2735 // the on-screen volume indicator and controller shown when the user
2736 // changes the device volume
2738 case TYPE_NAVIGATION_BAR:
2739 // the navigation bar, if available, shows atop most things
2741 case TYPE_NAVIGATION_BAR_PANEL:
2742 // some panels (e.g. search) need to show on top of the navigation bar
2744 case TYPE_SCREENSHOT:
2745 // screenshot selection layer shouldn't go above system error, but it should cover
2746 // navigation bars at the very least.
2748 case TYPE_SYSTEM_ERROR:
2749 // system-level error dialogs
2751 case TYPE_MAGNIFICATION_OVERLAY:
2752 // used to highlight the magnified portion of a display
2754 case TYPE_DISPLAY_OVERLAY:
2755 // used to simulate secondary display devices
2758 // the drag layer: input for drag-and-drop is associated with this window,
2759 // which sits above all other focusable windows
2761 case TYPE_ACCESSIBILITY_OVERLAY:
2762 // overlay put by accessibility services to intercept user interaction
2764 case TYPE_SECURE_SYSTEM_OVERLAY:
2766 case TYPE_BOOT_PROGRESS:
2769 // the (mouse) pointer layer
2772 Log.e(TAG, "Unknown window type: " + type);
2776 /** {@inheritDoc} */
2778 public int subWindowTypeToLayerLw(int type) {
2780 case TYPE_APPLICATION_PANEL:
2781 case TYPE_APPLICATION_ATTACHED_DIALOG:
2782 return APPLICATION_PANEL_SUBLAYER;
2783 case TYPE_APPLICATION_MEDIA:
2784 return APPLICATION_MEDIA_SUBLAYER;
2785 case TYPE_APPLICATION_MEDIA_OVERLAY:
2786 return APPLICATION_MEDIA_OVERLAY_SUBLAYER;
2787 case TYPE_APPLICATION_SUB_PANEL:
2788 return APPLICATION_SUB_PANEL_SUBLAYER;
2789 case TYPE_APPLICATION_ABOVE_SUB_PANEL:
2790 return APPLICATION_ABOVE_SUB_PANEL_SUBLAYER;
2792 Log.e(TAG, "Unknown sub-window type: " + type);
2797 public int getMaxWallpaperLayer() {
2798 return windowTypeToLayerLw(TYPE_STATUS_BAR);
2801 private int getNavigationBarWidth(int rotation, int uiMode) {
2802 if ((uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2803 return mNavigationBarWidthForRotationInCarMode[rotation];
2805 return mNavigationBarWidthForRotationDefault[rotation];
2810 public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation,
2812 if (mHasNavigationBar) {
2813 // For a basic navigation bar, when we are in landscape mode we place
2814 // the navigation bar to the side.
2815 if (mNavigationBarCanMove && fullWidth > fullHeight) {
2816 return fullWidth - getNavigationBarWidth(rotation, uiMode);
2822 private int getNavigationBarHeight(int rotation, int uiMode) {
2823 if ((uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2824 return mNavigationBarHeightForRotationInCarMode[rotation];
2826 return mNavigationBarHeightForRotationDefault[rotation];
2831 public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation,
2833 if (mHasNavigationBar) {
2834 // For a basic navigation bar, when we are in portrait mode we place
2835 // the navigation bar to the bottom.
2836 if (!mNavigationBarCanMove || fullWidth < fullHeight) {
2837 return fullHeight - getNavigationBarHeight(rotation, uiMode);
2844 public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode) {
2845 return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode);
2849 public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode) {
2850 // There is a separate status bar at the top of the display. We don't count that as part
2851 // of the fixed decor, since it can hide; however, for purposes of configurations,
2852 // we do want to exclude it since applications can't generally use that part
2854 return getNonDecorDisplayHeight(
2855 fullWidth, fullHeight, rotation, uiMode) - mStatusBarHeight;
2859 public boolean isForceHiding(WindowManager.LayoutParams attrs) {
2860 return (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
2861 (isKeyguardHostWindow(attrs) &&
2862 (mKeyguardDelegate != null && mKeyguardDelegate.isShowing())) ||
2863 (attrs.type == TYPE_KEYGUARD_SCRIM);
2867 public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) {
2868 return attrs.type == TYPE_STATUS_BAR;
2872 public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
2873 switch (attrs.type) {
2874 case TYPE_STATUS_BAR:
2875 case TYPE_NAVIGATION_BAR:
2876 case TYPE_WALLPAPER:
2878 case TYPE_KEYGUARD_SCRIM:
2881 // Hide only windows below the keyguard host window.
2882 return windowTypeToLayerLw(win.getBaseType())
2883 < windowTypeToLayerLw(TYPE_STATUS_BAR);
2888 public WindowState getWinShowWhenLockedLw() {
2889 return mWinShowWhenLocked;
2892 /** {@inheritDoc} */
2894 public View addStartingWindow(IBinder appToken, String packageName, int theme,
2895 CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
2896 int icon, int logo, int windowFlags, Configuration overrideConfig) {
2897 if (!SHOW_STARTING_ANIMATIONS) {
2900 if (packageName == null) {
2904 WindowManager wm = null;
2908 Context context = mContext;
2909 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow " + packageName
2910 + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
2911 + Integer.toHexString(theme));
2912 if (theme != context.getThemeResId() || labelRes != 0) {
2914 context = context.createPackageContext(packageName, 0);
2915 context.setTheme(theme);
2916 } catch (PackageManager.NameNotFoundException e) {
2921 if (overrideConfig != null && overrideConfig != EMPTY) {
2922 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: creating context based"
2923 + " on overrideConfig" + overrideConfig + " for starting window");
2924 final Context overrideContext = context.createConfigurationContext(overrideConfig);
2925 overrideContext.setTheme(theme);
2926 final TypedArray typedArray = overrideContext.obtainStyledAttributes(
2927 com.android.internal.R.styleable.Window);
2928 final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
2929 if (resId != 0 && overrideContext.getDrawable(resId) != null) {
2930 // We want to use the windowBackground for the override context if it is
2931 // available, otherwise we use the default one to make sure a themed starting
2932 // window is displayed for the app.
2933 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: apply overrideConfig"
2934 + overrideConfig + " to starting window resId=" + resId);
2935 context = overrideContext;
2939 final PhoneWindow win = new PhoneWindow(context);
2940 win.setIsStartingWindow(true);
2942 CharSequence label = context.getResources().getText(labelRes, null);
2943 // Only change the accessibility title if the label is localized
2944 if (label != null) {
2945 win.setTitle(label, true);
2947 win.setTitle(nonLocalizedLabel, false);
2951 WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
2953 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
2954 // Assumes it's safe to show starting windows of launched apps while
2955 // the keyguard is being hidden. This is okay because starting windows never show
2956 // secret information.
2957 if (mKeyguardHidden) {
2958 windowFlags |= FLAG_SHOW_WHEN_LOCKED;
2962 // Force the window flags: this is a fake window, so it is not really
2963 // touchable or focusable by the user. We also add in the ALT_FOCUSABLE_IM
2964 // flag because we do know that the next window will take input
2965 // focus, so we want to get the IME window up on top of us right away.
2968 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2969 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2970 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
2972 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2973 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2974 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
2976 win.setDefaultIcon(icon);
2977 win.setDefaultLogo(logo);
2979 win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
2980 WindowManager.LayoutParams.MATCH_PARENT);
2982 final WindowManager.LayoutParams params = win.getAttributes();
2983 params.token = appToken;
2984 params.packageName = packageName;
2985 params.windowAnimations = win.getWindowStyle().getResourceId(
2986 com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
2987 params.privateFlags |=
2988 WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
2989 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
2991 if (!compatInfo.supportsScreen()) {
2992 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
2995 params.setTitle("Starting " + packageName);
2997 wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
2998 view = win.getDecorView();
3000 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Adding starting window for "
3001 + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null));
3003 wm.addView(view, params);
3005 // Only return the view if it was successfully added to the
3006 // window manager... which we can tell by it having a parent.
3007 return view.getParent() != null ? view : null;
3008 } catch (WindowManager.BadTokenException e) {
3010 Log.w(TAG, appToken + " already running, starting window not displayed. " +
3012 } catch (RuntimeException e) {
3013 // don't crash if something else bad happens, for example a
3014 // failure loading resources because we are loading from an app
3015 // on external storage that has been unmounted.
3016 Log.w(TAG, appToken + " failed creating starting window", e);
3018 if (view != null && view.getParent() == null) {
3019 Log.w(TAG, "view not successfully added to wm, removing view");
3020 wm.removeViewImmediate(view);
3027 /** {@inheritDoc} */
3029 public void removeStartingWindow(IBinder appToken, View window) {
3030 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Removing starting window for " + appToken + ": "
3031 + window + " Callers=" + Debug.getCallers(4));
3033 if (window != null) {
3034 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
3035 wm.removeView(window);
3040 * Preflight adding a window to the system.
3042 * Currently enforces that three window types are singletons:
3044 * <li>STATUS_BAR_TYPE</li>
3045 * <li>KEYGUARD_TYPE</li>
3048 * @param win The window to be added
3049 * @param attrs Information about the window to be added
3051 * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons,
3052 * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
3055 public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
3056 switch (attrs.type) {
3057 case TYPE_STATUS_BAR:
3058 mContext.enforceCallingOrSelfPermission(
3059 android.Manifest.permission.STATUS_BAR_SERVICE,
3060 "PhoneWindowManager");
3061 if (mStatusBar != null) {
3062 if (mStatusBar.isAlive()) {
3063 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
3067 mStatusBarController.setWindow(win);
3069 case TYPE_NAVIGATION_BAR:
3070 mContext.enforceCallingOrSelfPermission(
3071 android.Manifest.permission.STATUS_BAR_SERVICE,
3072 "PhoneWindowManager");
3073 if (mNavigationBar != null) {
3074 if (mNavigationBar.isAlive()) {
3075 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
3078 mNavigationBar = win;
3079 mNavigationBarController.setWindow(win);
3080 if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
3082 case TYPE_NAVIGATION_BAR_PANEL:
3083 case TYPE_STATUS_BAR_PANEL:
3084 case TYPE_STATUS_BAR_SUB_PANEL:
3085 case TYPE_VOICE_INTERACTION_STARTING:
3086 mContext.enforceCallingOrSelfPermission(
3087 android.Manifest.permission.STATUS_BAR_SERVICE,
3088 "PhoneWindowManager");
3090 case TYPE_KEYGUARD_SCRIM:
3091 if (mKeyguardScrim != null) {
3092 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
3094 mKeyguardScrim = win;
3097 return WindowManagerGlobal.ADD_OKAY;
3100 /** {@inheritDoc} */
3102 public void removeWindowLw(WindowState win) {
3103 if (mStatusBar == win) {
3105 mStatusBarController.setWindow(null);
3106 mKeyguardDelegate.showScrim();
3107 } else if (mKeyguardScrim == win) {
3108 Log.v(TAG, "Removing keyguard scrim");
3109 mKeyguardScrim = null;
3110 } if (mNavigationBar == win) {
3111 mNavigationBar = null;
3112 mNavigationBarController.setWindow(null);
3116 static final boolean PRINT_ANIM = false;
3118 /** {@inheritDoc} */
3120 public int selectAnimationLw(WindowState win, int transit) {
3121 if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
3122 + ": transit=" + transit);
3123 if (win == mStatusBar) {
3124 boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
3125 if (transit == TRANSIT_EXIT
3126 || transit == TRANSIT_HIDE) {
3127 return isKeyguard ? -1 : R.anim.dock_top_exit;
3128 } else if (transit == TRANSIT_ENTER
3129 || transit == TRANSIT_SHOW) {
3130 return isKeyguard ? -1 : R.anim.dock_top_enter;
3132 } else if (win == mNavigationBar) {
3133 if (win.getAttrs().windowAnimations != 0) {
3136 // This can be on either the bottom or the right.
3137 if (mNavigationBarOnBottom) {
3138 if (transit == TRANSIT_EXIT
3139 || transit == TRANSIT_HIDE) {
3140 return R.anim.dock_bottom_exit;
3141 } else if (transit == TRANSIT_ENTER
3142 || transit == TRANSIT_SHOW) {
3143 return R.anim.dock_bottom_enter;
3146 if (transit == TRANSIT_EXIT
3147 || transit == TRANSIT_HIDE) {
3148 return R.anim.dock_right_exit;
3149 } else if (transit == TRANSIT_ENTER
3150 || transit == TRANSIT_SHOW) {
3151 return R.anim.dock_right_enter;
3154 } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) {
3155 return selectDockedDividerAnimationLw(win, transit);
3158 if (transit == TRANSIT_PREVIEW_DONE) {
3159 if (win.hasAppShownWindows()) {
3160 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
3161 return com.android.internal.R.anim.app_starting_exit;
3163 } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
3164 && transit == TRANSIT_ENTER) {
3165 // Special case: we are animating in a dream, while the keyguard
3166 // is shown. We don't want an animation on the dream, because
3167 // we need it shown immediately with the keyguard animating away
3175 private int selectDockedDividerAnimationLw(WindowState win, int transit) {
3176 int insets = mWindowManagerFuncs.getDockedDividerInsetsLw();
3178 // If the divider is behind the navigation bar, don't animate.
3179 final Rect frame = win.getFrameLw();
3180 final boolean behindNavBar = mNavigationBar != null
3181 && ((mNavigationBarOnBottom
3182 && frame.top + insets >= mNavigationBar.getFrameLw().top)
3183 || (!mNavigationBarOnBottom
3184 && frame.left + insets >= mNavigationBar.getFrameLw().left));
3185 final boolean landscape = frame.height() > frame.width();
3186 final boolean offscreenLandscape = landscape && (frame.right - insets <= 0
3187 || frame.left + insets >= win.getDisplayFrameLw().right);
3188 final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0
3189 || frame.bottom + insets >= win.getDisplayFrameLw().bottom);
3190 final boolean offscreen = offscreenLandscape || offscreenPortrait;
3191 if (behindNavBar || offscreen) {
3194 if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
3195 return R.anim.fade_in;
3196 } else if (transit == TRANSIT_EXIT) {
3197 return R.anim.fade_out;
3204 public void selectRotationAnimationLw(int anim[]) {
3205 if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
3206 + mTopFullscreenOpaqueWindowState + " rotationAnimation="
3207 + (mTopFullscreenOpaqueWindowState == null ?
3208 "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation));
3209 if (mTopFullscreenOpaqueWindowState != null && mTopIsFullscreen) {
3210 switch (mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation) {
3211 case ROTATION_ANIMATION_CROSSFADE:
3212 anim[0] = R.anim.rotation_animation_xfade_exit;
3213 anim[1] = R.anim.rotation_animation_enter;
3215 case ROTATION_ANIMATION_JUMPCUT:
3216 anim[0] = R.anim.rotation_animation_jump_exit;
3217 anim[1] = R.anim.rotation_animation_enter;
3219 case ROTATION_ANIMATION_ROTATE:
3221 anim[0] = anim[1] = 0;
3225 anim[0] = anim[1] = 0;
3230 public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId,
3231 boolean forceDefault) {
3232 switch (exitAnimId) {
3233 case R.anim.rotation_animation_xfade_exit:
3234 case R.anim.rotation_animation_jump_exit:
3235 // These are the only cases that matter.
3239 int anim[] = new int[2];
3240 selectRotationAnimationLw(anim);
3241 return (exitAnimId == anim[0] && enterAnimId == anim[1]);
3248 public Animation createForceHideEnterAnimation(boolean onWallpaper,
3249 boolean goingToNotificationShade) {
3250 if (goingToNotificationShade) {
3251 return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
3254 AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ?
3255 R.anim.lock_screen_behind_enter_wallpaper :
3256 R.anim.lock_screen_behind_enter);
3258 // TODO: Use XML interpolators when we have log interpolators available in XML.
3259 final List<Animation> animations = set.getAnimations();
3260 for (int i = animations.size() - 1; i >= 0; --i) {
3261 animations.get(i).setInterpolator(mLogDecelerateInterpolator);
3269 public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade) {
3270 if (goingToNotificationShade) {
3273 return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
3277 private static void awakenDreams() {
3278 IDreamManager dreamManager = getDreamManager();
3279 if (dreamManager != null) {
3281 dreamManager.awaken();
3282 } catch (RemoteException e) {
3283 // fine, stay asleep then
3288 static IDreamManager getDreamManager() {
3289 return IDreamManager.Stub.asInterface(
3290 ServiceManager.checkService(DreamService.DREAM_SERVICE));
3293 TelecomManager getTelecommService() {
3294 return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
3297 static IAudioService getAudioService() {
3298 IAudioService audioService = IAudioService.Stub.asInterface(
3299 ServiceManager.checkService(Context.AUDIO_SERVICE));
3300 if (audioService == null) {
3301 Log.w(TAG, "Unable to find IAudioService interface.");
3303 return audioService;
3306 boolean keyguardOn() {
3307 return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode();
3310 private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
3311 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
3312 WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
3315 /** {@inheritDoc} */
3317 public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
3318 final boolean keyguardOn = keyguardOn();
3319 final int repeatCount = event.getRepeatCount();
3320 final int metaState = event.getMetaState();
3321 final int flags = event.getFlags();
3322 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
3323 final boolean canceled = event.isCanceled();
3324 final boolean longPress = (flags & KeyEvent.FLAG_LONG_PRESS) != 0;
3325 final boolean virtualKey = event.getDeviceId() == KeyCharacterMap.VIRTUAL_KEYBOARD;
3326 final int keyCode = event.getKeyCode();
3329 Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
3330 + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
3331 + " canceled=" + canceled);
3334 // If the boot mode is power off alarm, we should not dispatch the several physical keys
3335 // in power off alarm UI to avoid pausing power off alarm UI.
3336 boolean isAlarmBoot = SystemProperties.getBoolean("ro.alarm_boot", false);
3337 if (isAlarmBoot && (keyCode == KeyEvent.KEYCODE_HOME
3338 || keyCode == KeyEvent.KEYCODE_SEARCH
3339 || keyCode == KeyEvent.KEYCODE_MENU
3340 || keyCode == KeyEvent.KEYCODE_APP_SWITCH)) {
3344 // If we think we might have a volume down & power key chord on the way
3345 // but we're not sure, then tell the dispatcher to wait a little while and
3346 // try again later before dispatching.
3347 if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
3348 if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
3349 final long now = SystemClock.uptimeMillis();
3350 final long timeoutTime = mScreenshotChordVolumeDownKeyTime
3351 + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
3352 if (now < timeoutTime) {
3353 return timeoutTime - now;
3356 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3357 && mScreenshotChordVolumeDownKeyConsumed) {
3359 mScreenshotChordVolumeDownKeyConsumed = false;
3365 // Cancel any pending meta actions if we see any other keys being pressed between the down
3366 // of the meta key and its corresponding up.
3367 if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
3368 mPendingMetaAction = false;
3370 // Any key that is not Alt or Meta cancels Caps Lock combo tracking.
3371 if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) {
3372 mPendingCapsLockToggle = false;
3375 if (keyCode == KeyEvent.KEYCODE_BACK && !down) {
3376 mHandler.removeCallbacks(mBackLongPress);
3379 // First we always handle the home key here, so applications
3380 // can never break it, although if keyguard is on, we do let
3381 // it handle it, because that gives us the correct 5 second
3383 if (keyCode == KeyEvent.KEYCODE_HOME) {
3385 // If we have released the home key, and didn't do anything else
3386 // while it was pressed, then it is time to go home!
3387 if (!down && mHomePressed) {
3388 if (mDoubleTapOnHomeBehavior != KEY_ACTION_APP_SWITCH) {
3389 cancelPreloadRecentApps();
3392 mHomePressed = false;
3393 if (mHomeConsumed) {
3394 mHomeConsumed = false;
3399 Log.i(TAG, "Ignoring HOME; event canceled.");
3403 // If an incoming call is ringing, HOME is totally disabled.
3404 // (The user is already on the InCallUI at this point,
3405 // and his ONLY options are to answer or reject the call.)
3406 TelecomManager telecomManager = getTelecommService();
3407 if (telecomManager != null && telecomManager.isRinging()) {
3408 Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
3412 // Delay handling home if a double-tap is possible.
3413 if (mDoubleTapOnHomeBehavior != KEY_ACTION_NOTHING) {
3414 mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
3415 mHomeDoubleTapPending = true;
3416 mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
3417 ViewConfiguration.getDoubleTapTimeout());
3421 handleShortPressOnHome();
3425 // If a system window has focus, then it doesn't make sense
3426 // right now to interact with applications.
3427 WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
3428 if (attrs != null) {
3429 final int type = attrs.type;
3430 if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM
3431 || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
3432 || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
3433 // the "app" is keyguard, so give it the key
3436 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
3437 for (int i=0; i<typeCount; i++) {
3438 if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
3439 // don't do anything, but also don't pass it to the app
3445 // Remember that home is pressed and handle special actions.
3446 if (repeatCount == 0) {
3447 mHomePressed = true;
3448 if (mHomeDoubleTapPending) {
3449 mHomeDoubleTapPending = false;
3450 mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
3451 performKeyAction(mDoubleTapOnHomeBehavior, event);
3452 mHomeConsumed = true;
3453 } else if (mLongPressOnHomeBehavior == KEY_ACTION_APP_SWITCH
3454 || mDoubleTapOnHomeBehavior == KEY_ACTION_APP_SWITCH) {
3455 preloadRecentApps();
3457 } else if (longPress) {
3458 if (!keyguardOn && !mHomeConsumed &&
3459 mLongPressOnHomeBehavior != KEY_ACTION_NOTHING) {
3460 if (mLongPressOnHomeBehavior != KEY_ACTION_APP_SWITCH) {
3461 cancelPreloadRecentApps();
3463 mHomePressed = true;
3464 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
3465 performKeyAction(mLongPressOnHomeBehavior, event);
3466 mHomeConsumed = true;
3470 } else if (keyCode == KeyEvent.KEYCODE_MENU) {
3471 // Hijack modified menu keys for debugging features
3472 final int chordBug = KeyEvent.META_SHIFT_ON;
3473 if (virtualKey || keyguardOn) {
3474 // Let the app handle the key
3479 if (mPressOnMenuBehavior == KEY_ACTION_APP_SWITCH
3480 || mLongPressOnMenuBehavior == KEY_ACTION_APP_SWITCH) {
3481 preloadRecentApps();
3483 if (repeatCount == 0) {
3484 mMenuPressed = true;
3485 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
3486 Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
3487 mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
3488 null, null, null, 0, null, null);
3490 } else if (SHOW_PROCESSES_ON_ALT_MENU &&
3491 (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
3492 Intent service = new Intent();
3493 service.setClassName(mContext, "com.android.server.LoadAverageService");
3494 ContentResolver res = mContext.getContentResolver();
3495 boolean shown = Settings.Global.getInt(
3496 res, Settings.Global.SHOW_PROCESSES, 0) != 0;
3498 mContext.startService(service);
3500 mContext.stopService(service);
3502 Settings.Global.putInt(
3503 res, Settings.Global.SHOW_PROCESSES, shown ? 0 : 1);
3506 } else if (longPress) {
3507 if (!keyguardOn && mLongPressOnMenuBehavior != KEY_ACTION_NOTHING) {
3508 if (mLongPressOnMenuBehavior != KEY_ACTION_APP_SWITCH) {
3509 cancelPreloadRecentApps();
3511 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
3512 performKeyAction(mLongPressOnMenuBehavior, event);
3513 mMenuPressed = false;
3518 if (!down && mMenuPressed) {
3519 if (mPressOnMenuBehavior != KEY_ACTION_APP_SWITCH) {
3520 cancelPreloadRecentApps();
3522 mMenuPressed = false;
3524 performKeyAction(mPressOnMenuBehavior, event);
3528 } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
3530 if (repeatCount == 0) {
3531 mSearchKeyShortcutPending = true;
3532 mConsumeSearchKeyUp = false;
3535 mSearchKeyShortcutPending = false;
3536 if (mConsumeSearchKeyUp) {
3537 mConsumeSearchKeyUp = false;
3542 } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
3544 if (mPressOnAppSwitchBehavior == KEY_ACTION_APP_SWITCH
3545 || mLongPressOnAppSwitchBehavior == KEY_ACTION_APP_SWITCH) {
3546 preloadRecentApps();
3548 if (repeatCount == 0) {
3549 mAppSwitchLongPressed = false;
3550 } else if (longPress) {
3551 if (!keyguardOn && mLongPressOnAppSwitchBehavior != KEY_ACTION_NOTHING) {
3552 if (mLongPressOnAppSwitchBehavior != KEY_ACTION_APP_SWITCH) {
3553 cancelPreloadRecentApps();
3555 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
3556 performKeyAction(mLongPressOnAppSwitchBehavior, event);
3557 mAppSwitchLongPressed = true;
3561 if (mAppSwitchLongPressed) {
3562 mAppSwitchLongPressed = false;
3564 if (mPressOnAppSwitchBehavior != KEY_ACTION_APP_SWITCH) {
3565 cancelPreloadRecentApps();
3568 performKeyAction(mPressOnAppSwitchBehavior, event);
3573 } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) {
3575 IStatusBarService service = getStatusBarService();
3576 if (service != null) {
3578 service.expandNotificationsPanel();
3579 } catch (RemoteException e) {
3584 } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed()
3585 && event.isCtrlPressed()) {
3586 if (down && repeatCount == 0) {
3587 int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION
3588 : TAKE_SCREENSHOT_FULLSCREEN;
3589 mScreenshotRunnable.setScreenshotType(type);
3590 mHandler.post(mScreenshotRunnable);
3593 } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
3594 if (down && repeatCount == 0 && !isKeyguardLocked()) {
3595 toggleKeyboardShortcutsMenu(event.getDeviceId());
3597 } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
3599 if (mPressOnAssistBehavior == KEY_ACTION_APP_SWITCH
3600 || mLongPressOnAssistBehavior == KEY_ACTION_APP_SWITCH) {
3601 preloadRecentApps();
3603 if (repeatCount == 0) {
3604 mAssistKeyLongPressed = false;
3605 } else if (longPress) {
3606 if (!keyguardOn && mLongPressOnAssistBehavior != KEY_ACTION_NOTHING) {
3607 if (mLongPressOnAssistBehavior != KEY_ACTION_APP_SWITCH) {
3608 cancelPreloadRecentApps();
3610 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
3611 performKeyAction(mLongPressOnAssistBehavior, event);
3612 mAssistKeyLongPressed = true;
3616 if (mAssistKeyLongPressed) {
3617 mAssistKeyLongPressed = false;
3619 if (mPressOnAssistBehavior != KEY_ACTION_APP_SWITCH) {
3620 cancelPreloadRecentApps();
3623 performKeyAction(mPressOnAssistBehavior, event);
3628 } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
3632 voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
3634 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
3635 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
3638 dic.exitIdle("voice-search");
3639 } catch (RemoteException e) {
3642 voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
3643 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
3645 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
3647 } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
3648 if (down && repeatCount == 0) {
3649 mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
3650 mHandler.post(mScreenshotRunnable);
3653 } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP
3654 || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) {
3656 int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
3658 // Disable autobrightness if it's on
3659 int auto = Settings.System.getIntForUser(
3660 mContext.getContentResolver(),
3661 Settings.System.SCREEN_BRIGHTNESS_MODE,
3662 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3663 UserHandle.USER_CURRENT_OR_SELF);
3665 Settings.System.putIntForUser(mContext.getContentResolver(),
3666 Settings.System.SCREEN_BRIGHTNESS_MODE,
3667 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3668 UserHandle.USER_CURRENT_OR_SELF);
3671 int min = mPowerManager.getMinimumScreenBrightnessSetting();
3672 int max = mPowerManager.getMaximumScreenBrightnessSetting();
3673 int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction;
3674 int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
3675 Settings.System.SCREEN_BRIGHTNESS,
3676 mPowerManager.getDefaultScreenBrightnessSetting(),
3677 UserHandle.USER_CURRENT_OR_SELF);
3679 // Make sure we don't go beyond the limits.
3680 brightness = Math.min(max, brightness);
3681 brightness = Math.max(min, brightness);
3683 Settings.System.putIntForUser(mContext.getContentResolver(),
3684 Settings.System.SCREEN_BRIGHTNESS, brightness,
3685 UserHandle.USER_CURRENT_OR_SELF);
3686 startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
3687 UserHandle.CURRENT_OR_SELF);
3690 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
3691 || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3692 || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
3693 if (mUseTvRouting) {
3694 // On TVs volume keys never go to the foreground app.
3695 dispatchDirectAudioEvent(event);
3700 // Toggle Caps Lock on META-ALT.
3701 boolean actionTriggered = false;
3702 if (KeyEvent.isModifierKey(keyCode)) {
3703 if (!mPendingCapsLockToggle) {
3704 // Start tracking meta state for combo.
3705 mInitialMetaState = mMetaState;
3706 mPendingCapsLockToggle = true;
3707 } else if (event.getAction() == KeyEvent.ACTION_UP) {
3708 int altOnMask = mMetaState & KeyEvent.META_ALT_MASK;
3709 int metaOnMask = mMetaState & KeyEvent.META_META_MASK;
3711 // Check for Caps Lock toggle
3712 if ((metaOnMask != 0) && (altOnMask != 0)) {
3713 // Check if nothing else is pressed
3714 if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) {
3715 // Handle Caps Lock Toggle
3716 mInputManagerInternal.toggleCapsLock(event.getDeviceId());
3717 actionTriggered = true;
3721 // Always stop tracking when key goes up.
3722 mPendingCapsLockToggle = false;
3725 // Store current meta state to be able to evaluate it later.
3726 mMetaState = metaState;
3728 if (actionTriggered) {
3732 if (KeyEvent.isMetaKey(keyCode)) {
3734 mPendingMetaAction = true;
3735 } else if (mPendingMetaAction) {
3736 launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId());
3739 } else if (keyCode == KeyEvent.KEYCODE_BACK) {
3740 if (Settings.Secure.getInt(mContext.getContentResolver(),
3741 Settings.Secure.KILL_APP_LONGPRESS_BACK, 0) == 1) {
3742 if (down && repeatCount == 0) {
3743 mHandler.postDelayed(mBackLongPress, mBackKillTimeout);
3748 // Shortcuts are invoked through Search+key, so intercept those here
3749 // Any printing key that is chorded with Search should be consumed
3750 // even if no shortcut was invoked. This prevents text from being
3751 // inadvertently inserted when using a keyboard that has built-in macro
3752 // shortcut keys (that emit Search+x) and some of them are not registered.
3753 if (mSearchKeyShortcutPending) {
3754 final KeyCharacterMap kcm = event.getKeyCharacterMap();
3755 if (kcm.isPrintingKey(keyCode)) {
3756 mConsumeSearchKeyUp = true;
3757 mSearchKeyShortcutPending = false;
3758 if (down && repeatCount == 0 && !keyguardOn) {
3759 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
3760 if (shortcutIntent != null) {
3761 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3763 startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3764 dismissKeyboardShortcutsMenu();
3765 } catch (ActivityNotFoundException ex) {
3766 Slog.w(TAG, "Dropping shortcut key combination because "
3767 + "the activity to which it is registered was not found: "
3768 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);
3771 Slog.i(TAG, "Dropping unregistered shortcut key combination: "
3772 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));
3779 // Invoke shortcuts using Meta.
3780 if (down && repeatCount == 0 && !keyguardOn
3781 && (metaState & KeyEvent.META_META_ON) != 0) {
3782 final KeyCharacterMap kcm = event.getKeyCharacterMap();
3783 if (kcm.isPrintingKey(keyCode)) {
3784 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
3785 metaState & ~(KeyEvent.META_META_ON
3786 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
3787 if (shortcutIntent != null) {
3788 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3790 startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3791 dismissKeyboardShortcutsMenu();
3792 } catch (ActivityNotFoundException ex) {
3793 Slog.w(TAG, "Dropping shortcut key combination because "
3794 + "the activity to which it is registered was not found: "
3795 + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
3802 // Handle application launch keys.
3803 if (down && repeatCount == 0 && !keyguardOn) {
3804 String category = sApplicationLaunchKeyCategories.get(keyCode);
3805 if (category != null) {
3806 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
3807 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3809 startActivityAsUser(intent, UserHandle.CURRENT);
3810 dismissKeyboardShortcutsMenu();
3811 } catch (ActivityNotFoundException ex) {
3812 Slog.w(TAG, "Dropping application launch key because "
3813 + "the activity to which it is registered was not found: "
3814 + "keyCode=" + keyCode + ", category=" + category, ex);
3820 // Display task switcher for ALT-TAB.
3821 if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
3822 if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
3823 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
3824 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
3825 mRecentAppsHeldModifiers = shiftlessModifiers;
3826 showRecentApps(true, false);
3830 } else if (!down && mRecentAppsHeldModifiers != 0
3831 && (metaState & mRecentAppsHeldModifiers) == 0) {
3832 mRecentAppsHeldModifiers = 0;
3833 hideRecentApps(true, false);
3836 // Handle input method switching.
3837 if (down && repeatCount == 0
3838 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3839 || (keyCode == KeyEvent.KEYCODE_SPACE
3840 && (metaState & KeyEvent.META_META_MASK) != 0))) {
3841 final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0;
3842 mWindowManagerFuncs.switchInputMethod(forwardDirection);
3845 if (mLanguageSwitchKeyPressed && !down
3846 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3847 || keyCode == KeyEvent.KEYCODE_SPACE)) {
3848 mLanguageSwitchKeyPressed = false;
3852 if (isValidGlobalKey(keyCode)
3853 && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
3857 // Specific device key handling
3858 if (mDeviceKeyHandler != null) {
3860 // The device only should consume known keys.
3861 if (mDeviceKeyHandler.handleKeyEvent(event)) {
3864 } catch (Exception e) {
3865 Slog.w(TAG, "Could not dispatch event to device key handler", e);
3870 long shortcutCode = keyCode;
3871 if (event.isCtrlPressed()) {
3872 shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
3875 if (event.isAltPressed()) {
3876 shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
3879 if (event.isShiftPressed()) {
3880 shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
3883 if (event.isMetaPressed()) {
3884 shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE;
3887 IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode);
3888 if (shortcutService != null) {
3890 if (isUserSetupComplete()) {
3891 shortcutService.notifyShortcutKeyPressed(shortcutCode);
3893 } catch (RemoteException e) {
3894 mShortcutKeyServices.delete(shortcutCode);
3900 // Reserve all the META modifier combos for system behavior
3901 if ((metaState & KeyEvent.META_META_ON) != 0) {
3905 // Let the application handle the key.
3909 /** {@inheritDoc} */
3911 public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
3912 // Note: This method is only called if the initial down was unhandled.
3914 Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
3915 + ", flags=" + event.getFlags()
3916 + ", keyCode=" + event.getKeyCode()
3917 + ", scanCode=" + event.getScanCode()
3918 + ", metaState=" + event.getMetaState()
3919 + ", repeatCount=" + event.getRepeatCount()
3920 + ", policyFlags=" + policyFlags);
3923 KeyEvent fallbackEvent = null;
3924 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3925 final KeyCharacterMap kcm = event.getKeyCharacterMap();
3926 final int keyCode = event.getKeyCode();
3927 final int metaState = event.getMetaState();
3928 final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
3929 && event.getRepeatCount() == 0;
3931 // Specific device key handling
3932 if (mDeviceKeyHandler != null) {
3934 // The device only should consume known keys.
3935 if (mDeviceKeyHandler.handleKeyEvent(event)) {
3938 } catch (Exception e) {
3939 Slog.w(TAG, "Could not dispatch event to device key handler", e);
3943 // Check for fallback actions specified by the key character map.
3944 final FallbackAction fallbackAction;
3946 fallbackAction = kcm.getFallbackAction(keyCode, metaState);
3948 fallbackAction = mFallbackActions.get(keyCode);
3951 if (fallbackAction != null) {
3953 Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode
3954 + " metaState=" + Integer.toHexString(fallbackAction.metaState));
3957 final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
3958 fallbackEvent = KeyEvent.obtain(
3959 event.getDownTime(), event.getEventTime(),
3960 event.getAction(), fallbackAction.keyCode,
3961 event.getRepeatCount(), fallbackAction.metaState,
3962 event.getDeviceId(), event.getScanCode(),
3963 flags, event.getSource(), null);
3965 if (!interceptFallback(win, fallbackEvent, policyFlags)) {
3966 fallbackEvent.recycle();
3967 fallbackEvent = null;
3971 mFallbackActions.put(keyCode, fallbackAction);
3972 } else if (event.getAction() == KeyEvent.ACTION_UP) {
3973 mFallbackActions.remove(keyCode);
3974 fallbackAction.recycle();
3980 if (fallbackEvent == null) {
3981 Slog.d(TAG, "No fallback.");
3983 Slog.d(TAG, "Performing fallback: " + fallbackEvent);
3986 return fallbackEvent;
3989 private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
3990 int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
3991 if ((actions & ACTION_PASS_TO_USER) != 0) {
3992 long delayMillis = interceptKeyBeforeDispatching(
3993 win, fallbackEvent, policyFlags);
3994 if (delayMillis == 0) {
4002 public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
4003 throws RemoteException {
4004 synchronized (mLock) {
4005 IShortcutService service = mShortcutKeyServices.get(shortcutCode);
4006 if (service != null && service.asBinder().pingBinder()) {
4007 throw new RemoteException("Key already exists.");
4010 mShortcutKeyServices.put(shortcutCode, shortcutService);
4014 private void launchAssistLongPressAction() {
4015 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
4016 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
4018 // launch the search activity
4019 Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
4020 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
4022 // TODO: This only stops the factory-installed search manager.
4023 // Need to formalize an API to handle others
4024 SearchManager searchManager = getSearchManager();
4025 if (searchManager != null) {
4026 searchManager.stopSearch();
4028 startActivityAsUser(intent, UserHandle.CURRENT);
4029 } catch (ActivityNotFoundException e) {
4030 Slog.w(TAG, "No activity to handle assist long press action.", e);
4034 private void launchAssistAction(String hint, int deviceId) {
4035 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
4036 if (!isUserSetupComplete()) {
4037 // Disable opening assist window during setup
4041 if (deviceId > Integer.MIN_VALUE) {
4042 args = new Bundle();
4043 args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
4045 if ((mContext.getResources().getConfiguration().uiMode
4046 & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
4047 // On TV, use legacy handling until assistants are implemented in the proper way.
4048 ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
4049 .launchLegacyAssist(hint, UserHandle.myUserId(), args);
4053 args = new Bundle();
4055 args.putBoolean(hint, true);
4057 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4058 if (statusbar != null) {
4059 statusbar.startAssist(args);
4064 private void startActivityAsUser(Intent intent, UserHandle handle) {
4065 if (isUserSetupComplete()) {
4066 mContext.startActivityAsUser(intent, handle);
4068 Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent);
4072 private SearchManager getSearchManager() {
4073 if (mSearchManager == null) {
4074 mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
4076 return mSearchManager;
4079 private void preloadRecentApps() {
4080 mPreloadedRecentApps = true;
4081 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4082 if (statusbar != null) {
4083 statusbar.preloadRecentApps();
4087 private void cancelPreloadRecentApps() {
4088 if (mPreloadedRecentApps) {
4089 mPreloadedRecentApps = false;
4090 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4091 if (statusbar != null) {
4092 statusbar.cancelPreloadRecentApps();
4097 private void toggleRecentApps() {
4098 mPreloadedRecentApps = false; // preloading no longer needs to be canceled
4099 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4100 if (statusbar != null) {
4101 statusbar.toggleRecentApps();
4106 public void showRecentApps(boolean fromHome) {
4107 mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
4108 mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget();
4111 private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
4112 mPreloadedRecentApps = false; // preloading no longer needs to be canceled
4113 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4114 if (statusbar != null) {
4115 statusbar.showRecentApps(triggeredFromAltTab, fromHome);
4119 private void toggleKeyboardShortcutsMenu(int deviceId) {
4120 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4121 if (statusbar != null) {
4122 statusbar.toggleKeyboardShortcutsMenu(deviceId);
4126 private void dismissKeyboardShortcutsMenu() {
4127 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4128 if (statusbar != null) {
4129 statusbar.dismissKeyboardShortcutsMenu();
4133 private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
4134 mPreloadedRecentApps = false; // preloading no longer needs to be canceled
4135 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4136 if (statusbar != null) {
4137 statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
4141 void launchHomeFromHotKey() {
4142 launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/);
4146 * A home key -> launch home action was detected. Take the appropriate action
4147 * given the situation with the keyguard.
4149 void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) {
4150 if (respectKeyguard) {
4151 if (isKeyguardShowingAndNotOccluded()) {
4152 // don't launch home if keyguard showing
4156 if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) {
4157 // when in keyguard restricted mode, must first verify unlock
4158 // before launching home
4159 mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
4161 public void onKeyguardExitResult(boolean success) {
4164 ActivityManagerNative.getDefault().stopAppSwitches();
4165 } catch (RemoteException e) {
4167 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
4168 startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
4176 // no keyguard stuff to worry about, just launch home!
4178 ActivityManagerNative.getDefault().stopAppSwitches();
4179 } catch (RemoteException e) {
4181 if (mRecentsVisible) {
4182 // Hide Recents and notify it to launch Home
4183 if (awakenFromDreams) {
4186 hideRecentApps(false, true);
4188 // Otherwise, just launch Home
4189 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
4190 startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
4194 private final Runnable mClearHideNavigationFlag = new Runnable() {
4197 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
4199 mForceClearedSystemUiFlags &=
4200 ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
4202 mWindowManagerFuncs.reevaluateStatusBarVisibility();
4207 * Input handler used while nav bar is hidden. Captures any touch on the screen,
4208 * to determine when the nav bar should be shown and prevent applications from
4209 * receiving those touches.
4211 final class HideNavInputEventReceiver extends InputEventReceiver {
4212 public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
4213 super(inputChannel, looper);
4217 public void onInputEvent(InputEvent event) {
4218 boolean handled = false;
4220 if (event instanceof MotionEvent
4221 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
4222 final MotionEvent motionEvent = (MotionEvent)event;
4223 if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
4224 // When the user taps down, we re-show the nav bar.
4225 boolean changed = false;
4226 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
4227 if (mInputConsumer == null) {
4230 // Any user activity always causes us to show the
4231 // navigation controls, if they had been hidden.
4232 // We also clear the low profile and only content
4233 // flags so that tapping on the screen will atomically
4234 // restore all currently hidden screen decorations.
4235 int newVal = mResettingSystemUiFlags |
4236 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
4237 View.SYSTEM_UI_FLAG_LOW_PROFILE |
4238 View.SYSTEM_UI_FLAG_FULLSCREEN;
4239 if (mResettingSystemUiFlags != newVal) {
4240 mResettingSystemUiFlags = newVal;
4243 // We don't allow the system's nav bar to be hidden
4244 // again for 1 second, to prevent applications from
4245 // spamming us and keeping it from being shown.
4246 newVal = mForceClearedSystemUiFlags |
4247 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
4248 if (mForceClearedSystemUiFlags != newVal) {
4249 mForceClearedSystemUiFlags = newVal;
4251 mHandler.postDelayed(mClearHideNavigationFlag, 1000);
4255 mWindowManagerFuncs.reevaluateStatusBarVisibility();
4260 finishInputEvent(event, handled);
4264 final InputEventReceiver.Factory mHideNavInputEventReceiverFactory =
4265 new InputEventReceiver.Factory() {
4267 public InputEventReceiver createInputEventReceiver(
4268 InputChannel inputChannel, Looper looper) {
4269 return new HideNavInputEventReceiver(inputChannel, looper);
4274 public int adjustSystemUiVisibilityLw(int visibility) {
4275 mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4276 mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4277 mRecentsVisible = (visibility & View.RECENT_APPS_VISIBLE) > 0;
4278 mTvPictureInPictureVisible = (visibility & View.TV_PICTURE_IN_PICTURE_VISIBLE) > 0;
4280 // Reset any bits in mForceClearingStatusBarVisibility that
4282 mResettingSystemUiFlags &= visibility;
4283 // Clear any bits in the new visibility that are currently being
4284 // force cleared, before reporting it.
4285 return visibility & ~mResettingSystemUiFlags
4286 & ~mForceClearedSystemUiFlags;
4290 public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
4291 int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets,
4292 Rect outStableInsets, Rect outOutsets) {
4293 final int fl = PolicyControl.getWindowFlags(null, attrs);
4294 final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
4295 final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
4297 final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
4299 int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
4301 if (displayRotation == Surface.ROTATION_0) {
4302 outOutsets.bottom += outset;
4303 } else if (displayRotation == Surface.ROTATION_90) {
4304 outOutsets.right += outset;
4305 } else if (displayRotation == Surface.ROTATION_180) {
4306 outOutsets.top += outset;
4307 } else if (displayRotation == Surface.ROTATION_270) {
4308 outOutsets.left += outset;
4313 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4314 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4315 int availRight, availBottom;
4316 if (canHideNavigationBar() &&
4317 (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
4318 availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4319 availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4321 availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
4322 availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4324 if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4325 if ((fl & FLAG_FULLSCREEN) != 0) {
4326 outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop,
4327 availRight - mStableFullscreenRight,
4328 availBottom - mStableFullscreenBottom);
4330 outContentInsets.set(mStableLeft, mStableTop,
4331 availRight - mStableRight, availBottom - mStableBottom);
4333 } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
4334 outContentInsets.setEmpty();
4335 } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
4336 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
4337 outContentInsets.set(mCurLeft, mCurTop,
4338 availRight - mCurRight, availBottom - mCurBottom);
4340 outContentInsets.set(mCurLeft, mCurTop,
4341 availRight - mCurRight, availBottom - mCurBottom);
4344 outStableInsets.set(mStableLeft, mStableTop,
4345 availRight - mStableRight, availBottom - mStableBottom);
4346 if (taskBounds != null) {
4347 calculateRelevantTaskInsets(taskBounds, outContentInsets,
4348 displayWidth, displayHeight);
4349 calculateRelevantTaskInsets(taskBounds, outStableInsets,
4350 displayWidth, displayHeight);
4352 return mForceShowSystemBars;
4354 outContentInsets.setEmpty();
4355 outStableInsets.setEmpty();
4356 return mForceShowSystemBars;
4360 * For any given task bounds, the insets relevant for these bounds given the insets relevant
4361 * for the entire display.
4363 private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth,
4364 int displayHeight) {
4365 mTmpRect.set(0, 0, displayWidth, displayHeight);
4366 mTmpRect.inset(inOutInsets);
4367 mTmpRect.intersect(taskBounds);
4368 int leftInset = mTmpRect.left - taskBounds.left;
4369 int topInset = mTmpRect.top - taskBounds.top;
4370 int rightInset = taskBounds.right - mTmpRect.right;
4371 int bottomInset = taskBounds.bottom - mTmpRect.bottom;
4372 inOutInsets.set(leftInset, topInset, rightInset, bottomInset);
4375 private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
4376 return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
4377 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
4380 /** {@inheritDoc} */
4382 public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
4383 int displayRotation, int uiMode) {
4384 mDisplayRotation = displayRotation;
4385 final int overscanLeft, overscanTop, overscanRight, overscanBottom;
4386 if (isDefaultDisplay) {
4387 switch (displayRotation) {
4388 case Surface.ROTATION_90:
4389 overscanLeft = mOverscanTop;
4390 overscanTop = mOverscanRight;
4391 overscanRight = mOverscanBottom;
4392 overscanBottom = mOverscanLeft;
4394 case Surface.ROTATION_180:
4395 overscanLeft = mOverscanRight;
4396 overscanTop = mOverscanBottom;
4397 overscanRight = mOverscanLeft;
4398 overscanBottom = mOverscanTop;
4400 case Surface.ROTATION_270:
4401 overscanLeft = mOverscanBottom;
4402 overscanTop = mOverscanLeft;
4403 overscanRight = mOverscanTop;
4404 overscanBottom = mOverscanRight;
4407 overscanLeft = mOverscanLeft;
4408 overscanTop = mOverscanTop;
4409 overscanRight = mOverscanRight;
4410 overscanBottom = mOverscanBottom;
4419 mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0;
4420 mOverscanScreenTop = mRestrictedOverscanScreenTop = 0;
4421 mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth;
4422 mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight;
4425 mSystemRight = displayWidth;
4426 mSystemBottom = displayHeight;
4427 mUnrestrictedScreenLeft = overscanLeft;
4428 mUnrestrictedScreenTop = overscanTop;
4429 mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight;
4430 mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom;
4431 mRestrictedScreenLeft = mUnrestrictedScreenLeft;
4432 mRestrictedScreenTop = mUnrestrictedScreenTop;
4433 mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth;
4434 mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight;
4435 mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft
4436 = mCurLeft = mUnrestrictedScreenLeft;
4437 mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop
4438 = mCurTop = mUnrestrictedScreenTop;
4439 mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight
4440 = mCurRight = displayWidth - overscanRight;
4441 mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom
4442 = mCurBottom = displayHeight - overscanBottom;
4443 mDockLayer = 0x10000000;
4444 mStatusBarLayer = -1;
4446 // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
4447 final Rect pf = mTmpParentFrame;
4448 final Rect df = mTmpDisplayFrame;
4449 final Rect of = mTmpOverscanFrame;
4450 final Rect vf = mTmpVisibleFrame;
4451 final Rect dcf = mTmpDecorFrame;
4452 pf.left = df.left = of.left = vf.left = mDockLeft;
4453 pf.top = df.top = of.top = vf.top = mDockTop;
4454 pf.right = df.right = of.right = vf.right = mDockRight;
4455 pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom;
4456 dcf.setEmpty(); // Decor frame N/A for system bars.
4458 if (isDefaultDisplay) {
4459 // For purposes of putting out fake window up to steal focus, we will
4460 // drive nav being hidden only by whether it is requested.
4461 final int sysui = mLastSystemUiFlags;
4462 boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
4463 boolean navTranslucent = (sysui
4464 & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
4465 boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
4466 boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
4467 boolean navAllowedHidden = immersive || immersiveSticky;
4468 navTranslucent &= !immersiveSticky; // transient trumps translucent
4469 boolean isKeyguardShowing = isStatusBarKeyguard() && !mHideLockScreen;
4470 if (!isKeyguardShowing) {
4471 navTranslucent &= areTranslucentBarsAllowed();
4473 boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null
4474 && mStatusBar.getAttrs().height == MATCH_PARENT
4475 && mStatusBar.getAttrs().width == MATCH_PARENT;
4477 // When the navigation bar isn't visible, we put up a fake
4478 // input window to catch all touch events. This way we can
4479 // detect when the user presses anywhere to bring back the nav
4480 // bar and ensure the application doesn't see the event.
4481 if (navVisible || navAllowedHidden) {
4482 if (mInputConsumer != null) {
4483 mHandler.sendMessage(
4484 mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
4485 mInputConsumer = null;
4487 } else if (mInputConsumer == null) {
4488 mInputConsumer = mWindowManagerFuncs.addInputConsumer(mHandler.getLooper(),
4489 mHideNavInputEventReceiverFactory);
4492 // For purposes of positioning and showing the nav bar, if we have
4493 // decided that it can't be hidden (because of the screen aspect ratio),
4494 // then take that into account.
4495 navVisible |= !canHideNavigationBar();
4497 boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight,
4498 displayRotation, uiMode, overscanRight, overscanBottom, dcf, navVisible, navTranslucent,
4499 navAllowedHidden, statusBarExpandedNotKeyguard);
4500 if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
4501 mDockLeft, mDockTop, mDockRight, mDockBottom));
4502 updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing);
4503 if (updateSysUiVisibility) {
4504 updateSystemUiVisibilityLw();
4509 private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui,
4510 boolean isKeyguardShowing) {
4511 // decide where the status bar goes ahead of time
4512 if (mStatusBar != null) {
4513 // apply any navigation bar insets
4514 pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4515 pf.top = df.top = of.top = mUnrestrictedScreenTop;
4516 pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4517 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
4518 + mUnrestrictedScreenTop;
4519 vf.left = mStableLeft;
4520 vf.top = mStableTop;
4521 vf.right = mStableRight;
4522 vf.bottom = mStableBottom;
4524 mStatusBarLayer = mStatusBar.getSurfaceLayer();
4526 // Let the status bar determine its size.
4527 mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
4528 vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
4529 dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */);
4531 // For layout, the status bar is always at the top with our fixed height.
4532 mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
4534 boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
4535 boolean statusBarTranslucent = (sysui
4536 & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
4537 if (!isKeyguardShowing) {
4538 statusBarTranslucent &= areTranslucentBarsAllowed();
4541 // If the status bar is hidden, we don't want to cause
4542 // windows behind it to scroll.
4543 if (mStatusBar.isVisibleLw() && !statusBarTransient) {
4544 // Status bar may go away, so the screen area it occupies
4545 // is available to apps but just covering them when the
4546 // status bar is visible.
4547 mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
4549 mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4550 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4551 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4552 mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4554 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " +
4556 "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
4557 mDockLeft, mDockTop, mDockRight, mDockBottom,
4558 mContentLeft, mContentTop, mContentRight, mContentBottom,
4559 mCurLeft, mCurTop, mCurRight, mCurBottom));
4561 if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
4562 && !statusBarTransient && !statusBarTranslucent
4563 && !mStatusBarController.wasRecentlyTranslucent()) {
4564 // If the opaque status bar is currently requested to be visible,
4565 // and not in the process of animating on or off, then
4566 // we can tell the app that it is covered by it.
4567 mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
4569 if (mStatusBarController.checkHiddenLw()) {
4576 private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation,
4577 int uiMode, int overscanRight, int overscanBottom, Rect dcf, boolean navVisible,
4578 boolean navTranslucent, boolean navAllowedHidden,
4579 boolean statusBarExpandedNotKeyguard) {
4580 if (mNavigationBar != null) {
4581 boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
4582 // Force the navigation bar to its appropriate place and
4583 // size. We need to do this directly, instead of relying on
4584 // it to bubble up from the nav bar, because this needs to
4585 // change atomically with screen rotations.
4586 mNavigationBarOnBottom = isNavigationBarOnBottom(displayWidth, displayHeight);
4587 if (mNavigationBarOnBottom) {
4588 // It's a system nav bar or a portrait screen; nav bar goes on bottom.
4589 int top = displayHeight - overscanBottom
4590 - getNavigationBarHeight(displayRotation, uiMode);
4591 mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
4592 mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
4593 if (transientNavBarShowing) {
4594 mNavigationBarController.setBarShowingLw(true);
4595 } else if (navVisible) {
4596 mNavigationBarController.setBarShowingLw(true);
4597 mDockBottom = mTmpNavigationFrame.top;
4598 mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
4599 mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
4601 // We currently want to hide the navigation UI - unless we expanded the status
4603 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4605 if (navVisible && !navTranslucent && !navAllowedHidden
4606 && !mNavigationBar.isAnimatingLw()
4607 && !mNavigationBarController.wasRecentlyTranslucent()) {
4608 // If the opaque nav bar is currently requested to be visible,
4609 // and not in the process of animating on or off, then
4610 // we can tell the app that it is covered by it.
4611 mSystemBottom = mTmpNavigationFrame.top;
4614 // Landscape screen; nav bar goes to the right.
4615 int left = displayWidth - overscanRight
4616 - getNavigationBarWidth(displayRotation, uiMode);
4617 mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
4618 mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
4619 if (transientNavBarShowing) {
4620 mNavigationBarController.setBarShowingLw(true);
4621 } else if (navVisible) {
4622 mNavigationBarController.setBarShowingLw(true);
4623 mDockRight = mTmpNavigationFrame.left;
4624 mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4625 mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4627 // We currently want to hide the navigation UI - unless we expanded the status
4629 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4631 if (navVisible && !navTranslucent && !navAllowedHidden
4632 && !mNavigationBar.isAnimatingLw()
4633 && !mNavigationBarController.wasRecentlyTranslucent()) {
4634 // If the nav bar is currently requested to be visible,
4635 // and not in the process of animating on or off, then
4636 // we can tell the app that it is covered by it.
4637 mSystemRight = mTmpNavigationFrame.left;
4640 // Make sure the content and current rectangles are updated to
4641 // account for the restrictions from the navigation bar.
4642 mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4643 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4644 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4645 mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4646 mStatusBarLayer = mNavigationBar.getSurfaceLayer();
4647 // And compute the final frame.
4648 mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
4649 mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
4650 mTmpNavigationFrame, mTmpNavigationFrame);
4651 if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
4652 if (mNavigationBarController.checkHiddenLw()) {
4659 private boolean isNavigationBarOnBottom(int displayWidth, int displayHeight) {
4660 return !mNavigationBarCanMove || displayWidth < displayHeight;
4663 /** {@inheritDoc} */
4665 public int getSystemDecorLayerLw() {
4666 if (mStatusBar != null && mStatusBar.isVisibleLw()) {
4667 return mStatusBar.getSurfaceLayer();
4670 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) {
4671 return mNavigationBar.getSurfaceLayer();
4678 public void getContentRectLw(Rect r) {
4679 r.set(mContentLeft, mContentTop, mContentRight, mContentBottom);
4682 void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
4683 boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
4684 if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
4685 // Here's a special case: if this attached window is a panel that is
4686 // above the dock window, and the window it is attached to is below
4687 // the dock window, then the frames we computed for the window it is
4688 // attached to can not be used because the dock is effectively part
4689 // of the underlying window and the attached window is floating on top
4690 // of the whole thing. So, we ignore the attached window and explicitly
4691 // compute the frames that would be appropriate without the dock.
4692 df.left = of.left = cf.left = vf.left = mDockLeft;
4693 df.top = of.top = cf.top = vf.top = mDockTop;
4694 df.right = of.right = cf.right = vf.right = mDockRight;
4695 df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom;
4697 // The effective display frame of the attached window depends on
4698 // whether it is taking care of insetting its content. If not,
4699 // we need to use the parent's content frame so that the entire
4700 // window is positioned within that content. Otherwise we can use
4701 // the overscan frame and let the attached window take care of
4702 // positioning its content appropriately.
4703 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4704 // Set the content frame of the attached window to the parent's decor frame
4705 // (same as content frame when IME isn't present) if specifically requested by
4706 // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
4707 // Otherwise, use the overscan frame.
4708 cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
4709 ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
4711 // If the window is resizing, then we want to base the content
4712 // frame on our attached content frame to resize... however,
4713 // things can be tricky if the attached window is NOT in resize
4714 // mode, in which case its content frame will be larger.
4715 // Ungh. So to deal with that, make sure the content frame
4716 // we end up using is not covering the IM dock.
4717 cf.set(attached.getContentFrameLw());
4718 if (attached.isVoiceInteraction()) {
4719 if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft;
4720 if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop;
4721 if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight;
4722 if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom;
4723 } else if (attached.getSurfaceLayer() < mDockLayer) {
4724 if (cf.left < mContentLeft) cf.left = mContentLeft;
4725 if (cf.top < mContentTop) cf.top = mContentTop;
4726 if (cf.right > mContentRight) cf.right = mContentRight;
4727 if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
4730 df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
4731 of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
4732 vf.set(attached.getVisibleFrameLw());
4734 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
4735 // window should be positioned relative to its parent or the entire
4737 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
4738 ? attached.getFrameLw() : df);
4741 private void applyStableConstraints(int sysui, int fl, Rect r) {
4742 if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4743 // If app is requesting a stable layout, don't let the
4744 // content insets go below the stable values.
4745 if ((fl & FLAG_FULLSCREEN) != 0) {
4746 if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft;
4747 if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop;
4748 if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight;
4749 if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom;
4751 if (r.left < mStableLeft) r.left = mStableLeft;
4752 if (r.top < mStableTop) r.top = mStableTop;
4753 if (r.right > mStableRight) r.right = mStableRight;
4754 if (r.bottom > mStableBottom) r.bottom = mStableBottom;
4759 private boolean canReceiveInput(WindowState win) {
4760 boolean notFocusable =
4761 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
4762 boolean altFocusableIm =
4763 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
4764 boolean notFocusableForIm = notFocusable ^ altFocusableIm;
4765 return !notFocusableForIm;
4768 /** {@inheritDoc} */
4770 public void layoutWindowLw(WindowState win, WindowState attached) {
4771 // We've already done the navigation bar and status bar. If the status bar can receive
4772 // input, we need to layout it again to accomodate for the IME window.
4773 if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) {
4776 final WindowManager.LayoutParams attrs = win.getAttrs();
4777 final boolean isDefaultDisplay = win.isDefaultDisplay();
4778 final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
4779 (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
4780 if (needsToOffsetInputMethodTarget) {
4781 if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
4782 offsetInputMethodWindowLw(mLastInputMethodWindow);
4785 final int fl = PolicyControl.getWindowFlags(win, attrs);
4786 final int pfl = attrs.privateFlags;
4787 final int sim = attrs.softInputMode;
4788 final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
4790 final Rect pf = mTmpParentFrame;
4791 final Rect df = mTmpDisplayFrame;
4792 final Rect of = mTmpOverscanFrame;
4793 final Rect cf = mTmpContentFrame;
4794 final Rect vf = mTmpVisibleFrame;
4795 final Rect dcf = mTmpDecorFrame;
4796 final Rect sf = mTmpStableFrame;
4800 final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
4801 && mNavigationBar != null && mNavigationBar.isVisibleLw());
4803 final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
4805 if (isDefaultDisplay) {
4806 sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom);
4808 sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom);
4811 if (!isDefaultDisplay) {
4812 if (attached != null) {
4813 // If this window is attached to another, our display
4814 // frame is the same as the one we are attached to.
4815 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4817 // Give the window full screen.
4818 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4819 pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4820 pf.right = df.right = of.right = cf.right
4821 = mOverscanScreenLeft + mOverscanScreenWidth;
4822 pf.bottom = df.bottom = of.bottom = cf.bottom
4823 = mOverscanScreenTop + mOverscanScreenHeight;
4825 } else if (attrs.type == TYPE_INPUT_METHOD) {
4826 pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
4827 pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
4828 pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
4829 // IM dock windows layout below the nav bar...
4830 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4831 // ...with content insets above the nav bar
4832 cf.bottom = vf.bottom = mStableBottom;
4833 if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
4834 // The status bar forces the navigation bar while it's visible. Make sure the IME
4835 // avoids the navigation bar in that case.
4836 pf.right = df.right = of.right = cf.right = vf.right = mStableRight;
4838 // IM dock windows always go to the bottom of the screen.
4839 attrs.gravity = Gravity.BOTTOM;
4840 mDockLayer = win.getSurfaceLayer();
4841 } else if (attrs.type == TYPE_VOICE_INTERACTION) {
4842 pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4843 pf.top = df.top = of.top = mUnrestrictedScreenTop;
4844 pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4845 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4846 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4847 cf.left = mDockLeft;
4849 cf.right = mDockRight;
4850 cf.bottom = mDockBottom;
4852 cf.left = mContentLeft;
4853 cf.top = mContentTop;
4854 cf.right = mContentRight;
4855 cf.bottom = mContentBottom;
4857 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4860 vf.right = mCurRight;
4861 vf.bottom = mCurBottom;
4865 } else if (win == mStatusBar) {
4866 pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4867 pf.top = df.top = of.top = mUnrestrictedScreenTop;
4868 pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4869 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop;
4870 cf.left = vf.left = mStableLeft;
4871 cf.top = vf.top = mStableTop;
4872 cf.right = vf.right = mStableRight;
4873 vf.bottom = mStableBottom;
4875 if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
4876 cf.bottom = mContentBottom;
4878 cf.bottom = mDockBottom;
4879 vf.bottom = mContentBottom;
4883 // Default policy decor for the default display
4884 dcf.left = mSystemLeft;
4885 dcf.top = mSystemTop;
4886 dcf.right = mSystemRight;
4887 dcf.bottom = mSystemBottom;
4888 final boolean inheritTranslucentDecor = (attrs.privateFlags
4889 & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0;
4890 final boolean isAppWindow =
4891 attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW &&
4892 attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
4893 final boolean topAtRest =
4894 win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
4895 if (isAppWindow && !inheritTranslucentDecor && !topAtRest) {
4896 if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
4897 && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0
4898 && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
4899 && (fl & WindowManager.LayoutParams.
4900 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
4901 && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) {
4902 // Ensure policy decor includes status bar
4903 dcf.top = mStableTop;
4905 if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0
4906 && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
4907 && (fl & WindowManager.LayoutParams.
4908 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
4909 // Ensure policy decor includes navigation bar
4910 dcf.bottom = mStableBottom;
4911 dcf.right = mStableRight;
4915 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4916 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4917 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
4918 + "): IN_SCREEN, INSET_DECOR");
4919 // This is the case for a normal activity window: we want it
4920 // to cover all of the screen space, and it can take care of
4921 // moving its contents to account for screen decorations that
4922 // intrude into that space.
4923 if (attached != null) {
4924 // If this window is attached to another, our display
4925 // frame is the same as the one we are attached to.
4926 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4928 if (attrs.type == TYPE_STATUS_BAR_PANEL
4929 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
4930 // Status bar panels are the only windows who can go on top of
4931 // the status bar. They are protected by the STATUS_BAR_SERVICE
4932 // permission, so they have the same privileges as the status
4935 // However, they should still dodge the navigation bar if it exists.
4937 pf.left = df.left = of.left = hasNavBar
4938 ? mDockLeft : mUnrestrictedScreenLeft;
4939 pf.top = df.top = of.top = mUnrestrictedScreenTop;
4940 pf.right = df.right = of.right = hasNavBar
4941 ? mRestrictedScreenLeft+mRestrictedScreenWidth
4942 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4943 pf.bottom = df.bottom = of.bottom = hasNavBar
4944 ? mRestrictedScreenTop+mRestrictedScreenHeight
4945 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4947 if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4948 "Laying out status bar window: (%d,%d - %d,%d)",
4949 pf.left, pf.top, pf.right, pf.bottom));
4950 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4951 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4952 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4953 // Asking to layout into the overscan region, so give it that pure
4954 // unrestricted area.
4955 pf.left = df.left = of.left = mOverscanScreenLeft;
4956 pf.top = df.top = of.top = mOverscanScreenTop;
4957 pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth;
4958 pf.bottom = df.bottom = of.bottom = mOverscanScreenTop
4959 + mOverscanScreenHeight;
4960 } else if (canHideNavigationBar()
4961 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4962 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4963 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4964 // Asking for layout as if the nav bar is hidden, lets the
4965 // application extend into the unrestricted overscan screen area. We
4966 // only do this for application windows to ensure no window that
4967 // can be above the nav bar can do this.
4968 pf.left = df.left = mOverscanScreenLeft;
4969 pf.top = df.top = mOverscanScreenTop;
4970 pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
4971 pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
4972 // We need to tell the app about where the frame inside the overscan
4973 // is, so it can inset its content by that amount -- it didn't ask
4974 // to actually extend itself into the overscan region.
4975 of.left = mUnrestrictedScreenLeft;
4976 of.top = mUnrestrictedScreenTop;
4977 of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4978 of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4980 pf.left = df.left = mRestrictedOverscanScreenLeft;
4981 pf.top = df.top = mRestrictedOverscanScreenTop;
4982 pf.right = df.right = mRestrictedOverscanScreenLeft
4983 + mRestrictedOverscanScreenWidth;
4984 pf.bottom = df.bottom = mRestrictedOverscanScreenTop
4985 + mRestrictedOverscanScreenHeight;
4986 // We need to tell the app about where the frame inside the overscan
4987 // is, so it can inset its content by that amount -- it didn't ask
4988 // to actually extend itself into the overscan region.
4989 of.left = mUnrestrictedScreenLeft;
4990 of.top = mUnrestrictedScreenTop;
4991 of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4992 of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4995 if ((fl & FLAG_FULLSCREEN) == 0) {
4996 if (win.isVoiceInteraction()) {
4997 cf.left = mVoiceContentLeft;
4998 cf.top = mVoiceContentTop;
4999 cf.right = mVoiceContentRight;
5000 cf.bottom = mVoiceContentBottom;
5002 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5003 cf.left = mDockLeft;
5005 cf.right = mDockRight;
5006 cf.bottom = mDockBottom;
5008 cf.left = mContentLeft;
5009 cf.top = mContentTop;
5010 cf.right = mContentRight;
5011 cf.bottom = mContentBottom;
5015 // Full screen windows are always given a layout that is as if the
5016 // status bar and other transient decors are gone. This is to avoid
5017 // bad states when moving from a window that is not hding the
5018 // status bar to one that is.
5019 cf.left = mRestrictedScreenLeft;
5020 cf.top = mRestrictedScreenTop;
5021 cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
5022 cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight;
5024 applyStableConstraints(sysUiFl, fl, cf);
5025 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5028 vf.right = mCurRight;
5029 vf.bottom = mCurBottom;
5034 } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
5035 & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
5036 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
5037 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5039 // A window that has requested to fill the entire screen just
5040 // gets everything, period.
5041 if (attrs.type == TYPE_STATUS_BAR_PANEL
5042 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL
5043 || attrs.type == TYPE_VOLUME_OVERLAY) {
5044 pf.left = df.left = of.left = cf.left = hasNavBar
5045 ? mDockLeft : mUnrestrictedScreenLeft;
5046 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
5047 pf.right = df.right = of.right = cf.right = hasNavBar
5048 ? mRestrictedScreenLeft+mRestrictedScreenWidth
5049 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5050 pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar
5051 ? mRestrictedScreenTop+mRestrictedScreenHeight
5052 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5053 if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
5054 "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
5055 pf.left, pf.top, pf.right, pf.bottom));
5056 } else if (attrs.type == TYPE_NAVIGATION_BAR
5057 || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
5058 // The navigation bar has Real Ultimate Power.
5059 pf.left = df.left = of.left = mUnrestrictedScreenLeft;
5060 pf.top = df.top = of.top = mUnrestrictedScreenTop;
5061 pf.right = df.right = of.right = mUnrestrictedScreenLeft
5062 + mUnrestrictedScreenWidth;
5063 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop
5064 + mUnrestrictedScreenHeight;
5065 if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
5066 "Laying out navigation bar window: (%d,%d - %d,%d)",
5067 pf.left, pf.top, pf.right, pf.bottom));
5068 } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
5069 || attrs.type == TYPE_BOOT_PROGRESS
5070 || attrs.type == TYPE_SCREENSHOT)
5071 && ((fl & FLAG_FULLSCREEN) != 0)) {
5072 // Fullscreen secure system overlays get what they ask for. Screenshot region
5073 // selection overlay should also expand to full screen.
5074 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
5075 pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
5076 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
5077 + mOverscanScreenWidth;
5078 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
5079 + mOverscanScreenHeight;
5080 } else if (attrs.type == TYPE_BOOT_PROGRESS) {
5081 // Boot progress screen always covers entire display.
5082 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
5083 pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
5084 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
5085 + mOverscanScreenWidth;
5086 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
5087 + mOverscanScreenHeight;
5088 } else if (attrs.type == TYPE_WALLPAPER) {
5089 // The wallpaper also has Real Ultimate Power, but we want to tell
5090 // it about the overscan area.
5091 pf.left = df.left = mOverscanScreenLeft;
5092 pf.top = df.top = mOverscanScreenTop;
5093 pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
5094 pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
5095 of.left = cf.left = mUnrestrictedScreenLeft;
5096 of.top = cf.top = mUnrestrictedScreenTop;
5097 of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5098 of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5099 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
5100 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
5101 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
5102 // Asking to layout into the overscan region, so give it that pure
5103 // unrestricted area.
5104 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
5105 pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
5106 pf.right = df.right = of.right = cf.right
5107 = mOverscanScreenLeft + mOverscanScreenWidth;
5108 pf.bottom = df.bottom = of.bottom = cf.bottom
5109 = mOverscanScreenTop + mOverscanScreenHeight;
5110 } else if (canHideNavigationBar()
5111 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
5112 && (attrs.type == TYPE_STATUS_BAR
5113 || attrs.type == TYPE_TOAST
5114 || attrs.type == TYPE_DOCK_DIVIDER
5115 || attrs.type == TYPE_VOICE_INTERACTION_STARTING
5116 || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
5117 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
5118 // Asking for layout as if the nav bar is hidden, lets the
5119 // application extend into the unrestricted screen area. We
5120 // only do this for application windows (or toasts) to ensure no window that
5121 // can be above the nav bar can do this.
5122 // XXX This assumes that an app asking for this will also
5123 // ask for layout in only content. We can't currently figure out
5124 // what the screen would be if only laying out to hide the nav bar.
5125 pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
5126 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
5127 pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft
5128 + mUnrestrictedScreenWidth;
5129 pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
5130 + mUnrestrictedScreenHeight;
5131 } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
5132 pf.left = df.left = of.left = mRestrictedScreenLeft;
5133 pf.top = df.top = of.top = mRestrictedScreenTop;
5134 pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
5135 pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop
5136 + mRestrictedScreenHeight;
5137 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5138 cf.left = mDockLeft;
5140 cf.right = mDockRight;
5141 cf.bottom = mDockBottom;
5143 cf.left = mContentLeft;
5144 cf.top = mContentTop;
5145 cf.right = mContentRight;
5146 cf.bottom = mContentBottom;
5149 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
5150 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
5151 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
5152 + mRestrictedScreenWidth;
5153 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
5154 + mRestrictedScreenHeight;
5157 applyStableConstraints(sysUiFl, fl, cf);
5159 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5162 vf.right = mCurRight;
5163 vf.bottom = mCurBottom;
5167 } else if (attached != null) {
5168 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5169 "): attached to " + attached);
5170 // A child window should be placed inside of the same visible
5171 // frame that its parent had.
5172 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf);
5174 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5175 "): normal window");
5176 // Otherwise, a normal window must be placed inside the content
5177 // of all screen decorations.
5178 if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) {
5179 // Status bar panels and the volume dialog are the only windows who can go on
5180 // top of the status bar. They are protected by the STATUS_BAR_SERVICE
5181 // permission, so they have the same privileges as the status
5183 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
5184 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
5185 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
5186 + mRestrictedScreenWidth;
5187 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
5188 + mRestrictedScreenHeight;
5189 } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) {
5190 // These dialogs are stable to interim decor changes.
5191 pf.left = df.left = of.left = cf.left = mStableLeft;
5192 pf.top = df.top = of.top = cf.top = mStableTop;
5193 pf.right = df.right = of.right = cf.right = mStableRight;
5194 pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom;
5196 pf.left = mContentLeft;
5197 pf.top = mContentTop;
5198 pf.right = mContentRight;
5199 pf.bottom = mContentBottom;
5200 if (win.isVoiceInteraction()) {
5201 df.left = of.left = cf.left = mVoiceContentLeft;
5202 df.top = of.top = cf.top = mVoiceContentTop;
5203 df.right = of.right = cf.right = mVoiceContentRight;
5204 df.bottom = of.bottom = cf.bottom = mVoiceContentBottom;
5205 } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5206 df.left = of.left = cf.left = mDockLeft;
5207 df.top = of.top = cf.top = mDockTop;
5208 df.right = of.right = cf.right = mDockRight;
5209 df.bottom = of.bottom = cf.bottom = mDockBottom;
5211 df.left = of.left = cf.left = mContentLeft;
5212 df.top = of.top = cf.top = mContentTop;
5213 df.right = of.right = cf.right = mContentRight;
5214 df.bottom = of.bottom = cf.bottom = mContentBottom;
5216 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5219 vf.right = mCurRight;
5220 vf.bottom = mCurBottom;
5228 // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
5229 // Also, we don't allow windows in multi-window mode to extend out of the screen.
5230 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR
5231 && !win.isInMultiWindowMode()) {
5232 df.left = df.top = -10000;
5233 df.right = df.bottom = 10000;
5234 if (attrs.type != TYPE_WALLPAPER) {
5235 of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
5236 of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
5240 // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we
5241 // need to provide information to the clients that want to pretend that you can draw there.
5242 // We only want to apply outsets to certain types of windows. For example, we never want to
5243 // apply the outsets to floating dialogs, because they wouldn't make sense there.
5244 final boolean useOutsets = shouldUseOutsets(attrs, fl);
5245 if (isDefaultDisplay && useOutsets) {
5246 osf = mTmpOutsetFrame;
5247 osf.set(cf.left, cf.top, cf.right, cf.bottom);
5248 int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
5250 int rotation = mDisplayRotation;
5251 if (rotation == Surface.ROTATION_0) {
5252 osf.bottom += outset;
5253 } else if (rotation == Surface.ROTATION_90) {
5254 osf.right += outset;
5255 } else if (rotation == Surface.ROTATION_180) {
5257 } else if (rotation == Surface.ROTATION_270) {
5260 if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset
5261 + " with rotation " + rotation + ", result: " + osf);
5265 if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
5266 + ": sim=#" + Integer.toHexString(sim)
5267 + " attach=" + attached + " type=" + attrs.type
5268 + String.format(" flags=0x%08x", fl)
5269 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
5270 + " of=" + of.toShortString()
5271 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
5272 + " dcf=" + dcf.toShortString()
5273 + " sf=" + sf.toShortString()
5274 + " osf=" + (osf == null ? "null" : osf.toShortString()));
5276 win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf);
5278 // Dock windows carve out the bottom of the screen, so normal windows
5279 // can't appear underneath them.
5280 if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleOrBehindKeyguardLw()
5281 && win.isDisplayedLw() && !win.getGivenInsetsPendingLw()) {
5282 setLastInputMethodWindowLw(null, null);
5283 offsetInputMethodWindowLw(win);
5285 if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleOrBehindKeyguardLw()
5286 && !win.getGivenInsetsPendingLw()) {
5287 offsetVoiceInputWindowLw(win);
5291 private void offsetInputMethodWindowLw(WindowState win) {
5292 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5293 top += win.getGivenContentInsetsLw().top;
5294 if (mContentBottom > top) {
5295 mContentBottom = top;
5297 if (mVoiceContentBottom > top) {
5298 mVoiceContentBottom = top;
5300 top = win.getVisibleFrameLw().top;
5301 top += win.getGivenVisibleInsetsLw().top;
5302 if (mCurBottom > top) {
5305 if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
5306 + mDockBottom + " mContentBottom="
5307 + mContentBottom + " mCurBottom=" + mCurBottom);
5310 private void offsetVoiceInputWindowLw(WindowState win) {
5311 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5312 top += win.getGivenContentInsetsLw().top;
5313 if (mVoiceContentBottom > top) {
5314 mVoiceContentBottom = top;
5318 /** {@inheritDoc} */
5320 public void finishLayoutLw() {
5324 /** {@inheritDoc} */
5326 public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
5327 mTopFullscreenOpaqueWindowState = null;
5328 mTopFullscreenOpaqueOrDimmingWindowState = null;
5329 mTopDockedOpaqueWindowState = null;
5330 mTopDockedOpaqueOrDimmingWindowState = null;
5331 mAppsToBeHidden.clear();
5332 mAppsThatDismissKeyguard.clear();
5333 mForceStatusBar = false;
5334 mForceStatusBarFromKeyguard = false;
5335 mForceStatusBarTransparent = false;
5336 mForcingShowNavBar = false;
5337 mForcingShowNavBarLayer = -1;
5339 mHideLockScreen = false;
5340 mAllowLockscreenWhenOn = false;
5341 mDismissKeyguard = DISMISS_KEYGUARD_NONE;
5342 mShowingLockscreen = false;
5343 mShowingDream = false;
5344 mWinShowWhenLocked = null;
5345 mKeyguardSecure = isKeyguardSecure(mCurrentUserId);
5346 mKeyguardSecureIncludingHidden = mKeyguardSecure
5347 && (mKeyguardDelegate != null && mKeyguardDelegate.isShowing());
5350 /** {@inheritDoc} */
5352 public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
5353 WindowState attached) {
5354 if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
5355 + win.isVisibleOrBehindKeyguardLw());
5356 final int fl = PolicyControl.getWindowFlags(win, attrs);
5357 if (mTopFullscreenOpaqueWindowState == null
5358 && win.isVisibleLw() && attrs.type == TYPE_INPUT_METHOD) {
5359 mForcingShowNavBar = true;
5360 mForcingShowNavBarLayer = win.getSurfaceLayer();
5362 if (attrs.type == TYPE_STATUS_BAR) {
5363 if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
5364 mForceStatusBarFromKeyguard = true;
5365 mShowingLockscreen = true;
5367 if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
5368 mForceStatusBarTransparent = true;
5372 boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
5373 && attrs.type < FIRST_SYSTEM_WINDOW;
5374 final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0;
5375 final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0;
5376 final int stackId = win.getStackId();
5377 if (mTopFullscreenOpaqueWindowState == null &&
5378 win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
5379 if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
5380 if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
5381 mForceStatusBarFromKeyguard = true;
5383 mForceStatusBar = true;
5386 if (attrs.type == TYPE_DREAM) {
5387 // If the lockscreen was showing when the dream started then wait
5388 // for the dream to draw before hiding the lockscreen.
5389 if (!mDreamingLockscreen
5390 || (win.isVisibleLw() && win.hasDrawnLw())) {
5391 mShowingDream = true;
5396 final IApplicationToken appToken = win.getAppToken();
5398 // For app windows that are not attached, we decide if all windows in the app they
5399 // represent should be hidden or if we should hide the lockscreen. For attached app
5400 // windows we defer the decision to the window it is attached to.
5401 if (appWindow && attached == null) {
5402 if (showWhenLocked) {
5403 // Remove any previous windows with the same appToken.
5404 mAppsToBeHidden.remove(appToken);
5405 mAppsThatDismissKeyguard.remove(appToken);
5406 if (mAppsToBeHidden.isEmpty()) {
5407 if (dismissKeyguard && !mKeyguardSecure) {
5408 mAppsThatDismissKeyguard.add(appToken);
5409 } else if (win.isDrawnLw() || win.hasAppShownWindows()) {
5410 mWinShowWhenLocked = win;
5411 mHideLockScreen = true;
5412 mForceStatusBarFromKeyguard = false;
5415 } else if (dismissKeyguard) {
5416 if (mKeyguardSecure) {
5417 mAppsToBeHidden.add(appToken);
5419 mAppsToBeHidden.remove(appToken);
5421 mAppsThatDismissKeyguard.add(appToken);
5423 mAppsToBeHidden.add(appToken);
5425 if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
5426 if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
5427 mTopFullscreenOpaqueWindowState = win;
5428 if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5429 mTopFullscreenOpaqueOrDimmingWindowState = win;
5431 if (!mAppsThatDismissKeyguard.isEmpty() &&
5432 mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
5433 if (DEBUG_LAYOUT) Slog.v(TAG,
5434 "Setting mDismissKeyguard true by win " + win);
5435 mDismissKeyguard = (mWinDismissingKeyguard == win
5436 && mSecureDismissingKeyguard == mKeyguardSecure)
5437 ? DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
5438 mWinDismissingKeyguard = win;
5439 mSecureDismissingKeyguard = mKeyguardSecure;
5440 mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure;
5441 } else if (mAppsToBeHidden.isEmpty() && showWhenLocked
5442 && (win.isDrawnLw() || win.hasAppShownWindows())) {
5443 if (DEBUG_LAYOUT) Slog.v(TAG,
5444 "Setting mHideLockScreen to true by win " + win);
5445 mHideLockScreen = true;
5446 mForceStatusBarFromKeyguard = false;
5448 if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
5449 mAllowLockscreenWhenOn = true;
5453 if (!mKeyguardHidden && mWinShowWhenLocked != null &&
5454 mWinShowWhenLocked.getAppToken() != win.getAppToken() &&
5455 (attrs.flags & FLAG_SHOW_WHEN_LOCKED) == 0) {
5459 } else if (mTopFullscreenOpaqueWindowState == null && mWinShowWhenLocked == null) {
5460 // No TopFullscreenOpaqueWindow is showing, but we found a SHOW_WHEN_LOCKED window
5461 // that is being hidden in an animation - keep the
5462 // keyguard hidden until the new window shows up and
5463 // we know whether to show the keyguard or not.
5464 if (win.isAnimatingLw() && appWindow && showWhenLocked && mKeyguardHidden) {
5465 mHideLockScreen = true;
5466 mWinShowWhenLocked = win;
5470 // Keep track of the window if it's dimming but not necessarily fullscreen.
5471 final boolean reallyVisible = win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw();
5472 if (mTopFullscreenOpaqueOrDimmingWindowState == null && reallyVisible
5473 && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
5474 mTopFullscreenOpaqueOrDimmingWindowState = win;
5477 // We need to keep track of the top "fullscreen" opaque window for the docked stack
5478 // separately, because both the "real fullscreen" opaque window and the one for the docked
5479 // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
5480 if (mTopDockedOpaqueWindowState == null && reallyVisible && appWindow && attached == null
5481 && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
5482 mTopDockedOpaqueWindowState = win;
5483 if (mTopDockedOpaqueOrDimmingWindowState == null) {
5484 mTopDockedOpaqueOrDimmingWindowState = win;
5488 // Also keep track of any windows that are dimming but not necessarily fullscreen in the
5490 if (mTopDockedOpaqueOrDimmingWindowState == null && reallyVisible && win.isDimming()
5491 && stackId == DOCKED_STACK_ID) {
5492 mTopDockedOpaqueOrDimmingWindowState = win;
5496 private boolean isFullscreen(WindowManager.LayoutParams attrs) {
5497 return attrs.x == 0 && attrs.y == 0
5498 && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
5499 && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
5502 /** {@inheritDoc} */
5504 public int finishPostLayoutPolicyLw() {
5505 if (mWinShowWhenLocked != null && mTopFullscreenOpaqueWindowState != null &&
5506 mWinShowWhenLocked.getAppToken() != mTopFullscreenOpaqueWindowState.getAppToken()
5507 && isKeyguardLocked()) {
5508 // A dialog is dismissing the keyguard. Put the wallpaper behind it and hide the
5509 // fullscreen window.
5510 // TODO: Make sure FLAG_SHOW_WALLPAPER is restored when dialog is dismissed. Or not.
5511 mWinShowWhenLocked.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5512 mTopFullscreenOpaqueWindowState.hideLw(false);
5513 mTopFullscreenOpaqueWindowState = mWinShowWhenLocked;
5517 boolean topIsFullscreen = false;
5519 final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
5520 ? mTopFullscreenOpaqueWindowState.getAttrs()
5523 // If we are not currently showing a dream then remember the current
5524 // lockscreen state. We will use this to determine whether the dream
5525 // started while the lockscreen was showing and remember this state
5526 // while the dream is showing.
5527 if (!mShowingDream) {
5528 mDreamingLockscreen = mShowingLockscreen;
5529 if (mDreamingSleepTokenNeeded) {
5530 mDreamingSleepTokenNeeded = false;
5531 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
5534 if (!mDreamingSleepTokenNeeded) {
5535 mDreamingSleepTokenNeeded = true;
5536 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget();
5540 if (mStatusBar != null) {
5541 if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
5542 + " forcefkg=" + mForceStatusBarFromKeyguard
5543 + " top=" + mTopFullscreenOpaqueWindowState);
5544 boolean shouldBeTransparent = mForceStatusBarTransparent
5546 && !mForceStatusBarFromKeyguard;
5547 if (!shouldBeTransparent) {
5548 mStatusBarController.setShowTransparent(false /* transparent */);
5549 } else if (!mStatusBar.isVisibleLw()) {
5550 mStatusBarController.setShowTransparent(true /* transparent */);
5553 WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs();
5554 boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT
5555 && statusBarAttrs.width == MATCH_PARENT;
5556 if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
5557 || statusBarExpanded) {
5558 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
5559 if (mStatusBarController.setBarShowingLw(true)) {
5560 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5562 // Maintain fullscreen layout until incoming animation is complete.
5563 topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
5564 // Transient status bar on the lockscreen is not allowed
5565 if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) {
5566 mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
5567 mLastSystemUiFlags, mLastSystemUiFlags);
5569 if (statusBarExpanded && mNavigationBar != null) {
5570 if (mNavigationBarController.setBarShowingLw(true)) {
5571 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5574 } else if (mTopFullscreenOpaqueWindowState != null) {
5575 final int fl = PolicyControl.getWindowFlags(null, lp);
5577 Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
5578 + " shown position: "
5579 + mTopFullscreenOpaqueWindowState.getShownPositionLw());
5580 Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
5581 + " lp.flags=0x" + Integer.toHexString(fl));
5583 topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
5584 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
5585 // The subtle difference between the window for mTopFullscreenOpaqueWindowState
5586 // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
5587 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the
5589 if (mStatusBarController.isTransientShowing()) {
5590 if (mStatusBarController.setBarShowingLw(true)) {
5591 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5593 } else if (topIsFullscreen
5594 && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)
5595 && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) {
5596 if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
5597 if (mStatusBarController.setBarShowingLw(false)) {
5598 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5600 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
5603 if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
5604 if (mStatusBarController.setBarShowingLw(true)) {
5605 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5611 if (mTopIsFullscreen != topIsFullscreen) {
5612 if (!topIsFullscreen) {
5613 // Force another layout when status bar becomes fully shown.
5614 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5616 mTopIsFullscreen = topIsFullscreen;
5619 // Hide the key guard if a visible window explicitly specifies that it wants to be
5620 // displayed when the screen is locked.
5621 if (mKeyguardDelegate != null && mStatusBar != null) {
5622 if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
5624 if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardSecure) {
5625 mKeyguardHidden = true;
5626 if (setKeyguardOccludedLw(true)) {
5627 changes |= FINISH_LAYOUT_REDO_LAYOUT
5628 | FINISH_LAYOUT_REDO_CONFIG
5629 | FINISH_LAYOUT_REDO_WALLPAPER;
5631 if (mKeyguardDelegate.isShowing()) {
5632 mHandler.post(new Runnable() {
5635 mKeyguardDelegate.keyguardDone(false, false);
5639 } else if (mHideLockScreen) {
5640 mKeyguardHidden = true;
5641 mWinDismissingKeyguard = null;
5642 if (setKeyguardOccludedLw(true)) {
5643 changes |= FINISH_LAYOUT_REDO_LAYOUT
5644 | FINISH_LAYOUT_REDO_CONFIG
5645 | FINISH_LAYOUT_REDO_WALLPAPER;
5647 } else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) {
5648 mKeyguardHidden = false;
5649 if (setKeyguardOccludedLw(false)) {
5650 changes |= FINISH_LAYOUT_REDO_LAYOUT
5651 | FINISH_LAYOUT_REDO_CONFIG
5652 | FINISH_LAYOUT_REDO_WALLPAPER;
5654 if (mDismissKeyguard == DISMISS_KEYGUARD_START) {
5655 // Only launch the next keyguard unlock window once per window.
5656 mHandler.post(new Runnable() {
5659 mKeyguardDelegate.dismiss();
5664 mWinDismissingKeyguard = null;
5665 mSecureDismissingKeyguard = false;
5666 mKeyguardHidden = false;
5667 if (setKeyguardOccludedLw(false)) {
5668 changes |= FINISH_LAYOUT_REDO_LAYOUT
5669 | FINISH_LAYOUT_REDO_CONFIG
5670 | FINISH_LAYOUT_REDO_WALLPAPER;
5675 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5676 // If the navigation bar has been hidden or shown, we need to do another
5677 // layout pass to update that window.
5678 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5681 // update since mAllowLockscreenWhenOn might have changed
5682 updateLockScreenTimeout();
5687 * Updates the occluded state of the Keyguard.
5689 * @return Whether the flags have changed and we have to redo the layout.
5691 private boolean setKeyguardOccludedLw(boolean isOccluded) {
5692 boolean wasOccluded = mKeyguardOccluded;
5693 boolean showing = mKeyguardDelegate.isShowing();
5694 if (wasOccluded && !isOccluded && showing) {
5695 mKeyguardOccluded = false;
5696 mKeyguardDelegate.setOccluded(false);
5697 mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
5699 } else if (!wasOccluded && isOccluded && showing) {
5700 mKeyguardOccluded = true;
5701 mKeyguardDelegate.setOccluded(true);
5702 mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
5703 mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
5710 private boolean isStatusBarKeyguard() {
5711 return mStatusBar != null
5712 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
5716 public boolean allowAppAnimationsLw() {
5717 if (isStatusBarKeyguard() || mShowingDream) {
5718 // If keyguard or dreams is currently visible, no reason to animate behind it.
5725 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
5726 mFocusedWindow = newFocus;
5727 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5728 // If the navigation bar has been hidden or shown, we need to do another
5729 // layout pass to update that window.
5730 return FINISH_LAYOUT_REDO_LAYOUT;
5735 /** {@inheritDoc} */
5737 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
5738 // lid changed state
5739 final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
5740 if (newLidState == mLidState) {
5744 mLidState = newLidState;
5745 applyLidSwitchState();
5746 updateRotation(true);
5749 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
5750 "android.policy:LID");
5751 } else if (!mLidControlsSleep) {
5752 mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
5757 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
5758 int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
5759 if (mCameraLensCoverState == lensCoverState) {
5762 if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
5763 lensCoverState == CAMERA_LENS_UNCOVERED) {
5765 final boolean keyguardActive = mKeyguardDelegate == null ? false :
5766 mKeyguardDelegate.isShowing();
5767 if (keyguardActive) {
5768 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
5770 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
5772 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
5773 "android.policy:CAMERA_COVER");
5774 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
5776 mCameraLensCoverState = lensCoverState;
5779 void setHdmiPlugged(boolean plugged) {
5780 if (mHdmiPlugged != plugged) {
5781 mHdmiPlugged = plugged;
5782 updateRotation(true, true);
5783 Intent intent = new Intent(ACTION_HDMI_PLUGGED);
5784 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
5785 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
5786 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
5790 void initializeHdmiState() {
5791 boolean plugged = false;
5792 // watch for HDMI plug messages if the hdmi switch exists
5793 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
5794 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
5796 final String filename = "/sys/class/switch/hdmi/state";
5797 FileReader reader = null;
5799 reader = new FileReader(filename);
5800 char[] buf = new char[15];
5801 int n = reader.read(buf);
5803 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
5805 } catch (IOException ex) {
5806 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5807 } catch (NumberFormatException ex) {
5808 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5810 if (reader != null) {
5813 } catch (IOException ex) {
5818 // This dance forces the code in setHdmiPlugged to run.
5819 // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
5820 mHdmiPlugged = !plugged;
5821 setHdmiPlugged(!mHdmiPlugged);
5825 * @return Whether music is being played right now "locally" (e.g. on the device's speakers
5826 * or wired headphones) or "remotely" (e.g. on a device using the Cast protocol and
5827 * controlled by this device, or through remote submix).
5829 private boolean isMusicActive() {
5830 final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
5832 Log.w(TAG, "isMusicActive: couldn't get AudioManager reference");
5835 return am.isMusicActive();
5838 final Object mScreenshotLock = new Object();
5839 ServiceConnection mScreenshotConnection = null;
5841 final Runnable mScreenshotTimeout = new Runnable() {
5842 @Override public void run() {
5843 synchronized (mScreenshotLock) {
5844 if (mScreenshotConnection != null) {
5845 mContext.unbindService(mScreenshotConnection);
5846 mScreenshotConnection = null;
5847 notifyScreenshotError();
5853 // Assume this is called from the Handler thread.
5854 private void takeScreenshot(final int screenshotType) {
5855 synchronized (mScreenshotLock) {
5856 if (mScreenshotConnection != null) {
5859 final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
5860 SYSUI_SCREENSHOT_SERVICE);
5861 final Intent serviceIntent = new Intent();
5862 serviceIntent.setComponent(serviceComponent);
5863 ServiceConnection conn = new ServiceConnection() {
5865 public void onServiceConnected(ComponentName name, IBinder service) {
5866 synchronized (mScreenshotLock) {
5867 if (mScreenshotConnection != this) {
5870 Messenger messenger = new Messenger(service);
5871 Message msg = Message.obtain(null, screenshotType);
5872 final ServiceConnection myConn = this;
5873 Handler h = new Handler(mHandler.getLooper()) {
5875 public void handleMessage(Message msg) {
5876 synchronized (mScreenshotLock) {
5877 if (mScreenshotConnection == myConn) {
5878 mContext.unbindService(mScreenshotConnection);
5879 mScreenshotConnection = null;
5880 mHandler.removeCallbacks(mScreenshotTimeout);
5885 msg.replyTo = new Messenger(h);
5886 msg.arg1 = msg.arg2 = 0;
5887 if (mStatusBar != null && mStatusBar.isVisibleLw())
5889 if (mNavigationBar != null && mNavigationBar.isVisibleLw())
5892 messenger.send(msg);
5893 } catch (RemoteException e) {
5899 public void onServiceDisconnected(ComponentName name) {
5900 notifyScreenshotError();
5903 if (mContext.bindServiceAsUser(serviceIntent, conn,
5904 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
5905 UserHandle.CURRENT)) {
5906 mScreenshotConnection = conn;
5907 mHandler.postDelayed(mScreenshotTimeout, 10000);
5913 * Notifies the screenshot service to show an error.
5915 private void notifyScreenshotError() {
5916 // If the service process is killed, then ask it to clean up after itself
5917 final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
5918 SYSUI_SCREENSHOT_ERROR_RECEIVER);
5919 Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
5920 errorIntent.setComponent(errorComponent);
5921 errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
5922 Intent.FLAG_RECEIVER_FOREGROUND);
5923 mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT);
5926 /** {@inheritDoc} */
5928 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
5929 if (!mSystemBooted) {
5930 // If we have not yet booted, don't let key events do anything.
5934 final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
5935 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
5936 final boolean canceled = event.isCanceled();
5937 final int keyCode = event.getKeyCode();
5939 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
5941 // If screen is off then we treat the case where the keyguard is open but hidden
5942 // the same as if it were open and in front.
5943 // This will prevent any keys other than the power button from waking the screen
5944 // when the keyguard is hidden by another activity.
5945 final boolean keyguardActive = (mKeyguardDelegate == null ? false :
5947 isKeyguardShowingAndNotOccluded() :
5948 mKeyguardDelegate.isShowing()));
5951 Log.d(TAG, "interceptKeyTq keycode=" + keyCode
5952 + " interactive=" + interactive + " keyguardActive=" + keyguardActive
5953 + " policyFlags=" + Integer.toHexString(policyFlags));
5956 // Basic policy based on interactive state.
5958 boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
5959 || event.isWakeKey();
5960 if (interactive || (isInjected && !isWakeKey)) {
5961 // When the device is interactive or the key is injected pass the
5962 // key to the application.
5963 result = ACTION_PASS_TO_USER;
5965 } else if (!interactive && shouldDispatchInputWhenNonInteractive()) {
5966 // If we're currently dozing with the screen on and the keyguard showing, pass the key
5967 // to the application but preserve its wake key status to make sure we still move
5968 // from dozing to fully interactive if we would normally go from off to fully
5969 // interactive, unless the user has explicitly disabled this wake key.
5970 result = ACTION_PASS_TO_USER;
5971 isWakeKey = isWakeKey && isWakeKeyEnabled(keyCode);
5973 // When the screen is off and the key is not injected, determine whether
5974 // to wake the device but don't pass the key to the application.
5976 if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
5981 // If the key would be handled globally, just return the result, don't worry about special
5983 if (isValidGlobalKey(keyCode)
5984 && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
5986 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5991 boolean useHapticFeedback = down
5992 && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
5993 && event.getRepeatCount() == 0;
5995 // Handle special keys.
5997 case KeyEvent.KEYCODE_BACK: {
5999 mBackKeyHandled = false;
6000 if (hasLongPressOnBackBehavior()) {
6001 Message msg = mHandler.obtainMessage(MSG_BACK_LONG_PRESS);
6002 msg.setAsynchronous(true);
6003 mHandler.sendMessageDelayed(msg,
6004 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
6007 boolean handled = mBackKeyHandled;
6009 // Reset back key state
6010 cancelPendingBackKeyAction();
6012 // Don't pass back press to app if we've already handled it
6014 result &= ~ACTION_PASS_TO_USER;
6020 case KeyEvent.KEYCODE_VOLUME_DOWN:
6021 case KeyEvent.KEYCODE_VOLUME_UP:
6022 case KeyEvent.KEYCODE_VOLUME_MUTE: {
6023 // Eat all down & up keys when using volume wake.
6024 // This disables volume control, music control, and "beep" on key up.
6025 if (isWakeKey && mVolumeWakeScreen) {
6026 mVolumeWakeTriggered = true;
6028 } else if (mVolumeWakeTriggered && !down) {
6029 result &= ~ACTION_PASS_TO_USER;
6030 mVolumeWakeTriggered = false;
6034 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
6036 if (interactive && !mScreenshotChordVolumeDownKeyTriggered
6037 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
6038 mScreenshotChordVolumeDownKeyTriggered = true;
6039 mScreenshotChordVolumeDownKeyTime = event.getDownTime();
6040 mScreenshotChordVolumeDownKeyConsumed = false;
6041 cancelPendingPowerKeyAction();
6042 interceptScreenshotChord();
6045 mScreenshotChordVolumeDownKeyTriggered = false;
6046 cancelPendingScreenshotChordAction();
6048 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
6050 if (interactive && !mScreenshotChordVolumeUpKeyTriggered
6051 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
6052 mScreenshotChordVolumeUpKeyTriggered = true;
6053 cancelPendingPowerKeyAction();
6054 cancelPendingScreenshotChordAction();
6057 mScreenshotChordVolumeUpKeyTriggered = false;
6058 cancelPendingScreenshotChordAction();
6062 TelecomManager telecomManager = getTelecommService();
6063 if (telecomManager != null) {
6064 if (telecomManager.isRinging()) {
6065 // If an incoming call is ringing, either VOLUME key means
6066 // "silence ringer". We handle these keys here, rather than
6067 // in the InCallScreen, to make sure we'll respond to them
6068 // even if the InCallScreen hasn't come to the foreground yet.
6069 // Look for the DOWN event here, to agree with the "fallback"
6070 // behavior in the InCallScreen.
6071 Log.i(TAG, "interceptKeyBeforeQueueing:"
6072 + " VOLUME key-down while ringing: Silence ringer!");
6074 // Silence the ringer. (It's safe to call this
6075 // even if the ringer has already been silenced.)
6076 telecomManager.silenceRinger();
6078 // And *don't* pass this key thru to the current activity
6079 // (which is probably the InCallScreen.)
6080 result &= ~ACTION_PASS_TO_USER;
6083 if (telecomManager.isInCall()
6084 && (result & ACTION_PASS_TO_USER) == 0) {
6085 // If we are in call but we decided not to pass the key to
6086 // the application, just pass it to the session service.
6088 MediaSessionLegacyHelper.getHelper(mContext)
6089 .sendVolumeKeyEvent(event, false);
6094 if (mUseTvRouting) {
6095 // On TVs, defer special key handlings to
6096 // {@link interceptKeyBeforeDispatching()}.
6097 result |= ACTION_PASS_TO_USER;
6098 } else if ((result & ACTION_PASS_TO_USER) == 0) {
6099 // If we aren't passing to the user and no one else
6100 // handled it send it to the session manager to
6102 MediaSessionLegacyHelper.getHelper(mContext)
6103 .sendVolumeKeyEvent(event, true);
6106 // Disable music and volume control when used as wake key
6107 if ((result & ACTION_PASS_TO_USER) == 0 && !mVolumeWakeScreen) {
6108 boolean mayChangeVolume = false;
6110 if (isMusicActive()) {
6111 if (mVolBtnMusicControls && (keyCode != KeyEvent.KEYCODE_VOLUME_MUTE)) {
6112 // Detect long key presses.
6114 mIsLongPress = false;
6115 // TODO: Long press of MUTE could be mapped to KEYCODE_MEDIA_PLAY_PAUSE
6116 int newKeyCode = event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP ?
6117 KeyEvent.KEYCODE_MEDIA_NEXT : KeyEvent.KEYCODE_MEDIA_PREVIOUS;
6118 scheduleLongPressKeyEvent(event, newKeyCode);
6119 // Consume key down events of all presses.
6122 mHandler.removeMessages(MSG_DISPATCH_VOLKEY_WITH_WAKE_LOCK);
6123 // Consume key up events of long presses only.
6127 // Change volume only on key up events of short presses.
6128 mayChangeVolume = true;
6131 // Long key press detection not applicable, change volume only
6132 // on key down events
6133 mayChangeVolume = down;
6137 if (mayChangeVolume) {
6138 if (mUseTvRouting) {
6139 dispatchDirectAudioEvent(event);
6141 // If we aren't passing to the user and no one else
6142 // handled it send it to the session manager to figure
6145 // Rewrite the event to use key-down as sendVolumeKeyEvent will
6146 // only change the volume on key down.
6147 KeyEvent newEvent = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
6148 MediaSessionLegacyHelper.getHelper(mContext)
6149 .sendVolumeKeyEvent(newEvent, true);
6157 case KeyEvent.KEYCODE_HOME:
6158 if (down && !interactive && mHomeWakeScreen) {
6163 case KeyEvent.KEYCODE_FOCUS:
6164 if (down && !interactive && mCameraSleepOnRelease) {
6165 mIsFocusPressed = true;
6166 } else if ((event.getAction() == KeyEvent.ACTION_UP)
6167 && mScreenOnFully && mIsFocusPressed) {
6168 // Check if screen is fully on before letting the device go to sleep
6169 mPowerManager.goToSleep(SystemClock.uptimeMillis());
6170 mIsFocusPressed = false;
6174 case KeyEvent.KEYCODE_CAMERA:
6175 if (down && mIsFocusPressed) {
6176 mIsFocusPressed = false;
6179 mIsLongPress = false;
6180 scheduleLongPressKeyEvent(event, KeyEvent.KEYCODE_CAMERA);
6181 // Consume key down events of all presses.
6184 mHandler.removeMessages(MSG_CAMERA_LONG_PRESS);
6185 // Consume key up events of long presses only.
6186 if (mIsLongPress && mCameraLaunch) {
6188 if (keyguardActive) {
6189 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
6191 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
6194 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
6199 case KeyEvent.KEYCODE_ENDCALL: {
6200 result &= ~ACTION_PASS_TO_USER;
6202 TelecomManager telecomManager = getTelecommService();
6203 boolean hungUp = false;
6204 if (telecomManager != null) {
6205 hungUp = telecomManager.endCall();
6207 if (interactive && !hungUp) {
6208 mEndCallKeyHandled = false;
6209 mHandler.postDelayed(mEndCallLongPress,
6210 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
6212 mEndCallKeyHandled = true;
6215 if (!mEndCallKeyHandled) {
6216 mHandler.removeCallbacks(mEndCallLongPress);
6218 if ((mEndcallBehavior
6219 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
6224 if ((mEndcallBehavior
6225 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
6226 mPowerManager.goToSleep(event.getEventTime(),
6227 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
6236 case KeyEvent.KEYCODE_POWER: {
6237 result &= ~ACTION_PASS_TO_USER;
6238 isWakeKey = false; // wake-up will be handled separately
6240 interceptPowerKeyDown(event, interactive);
6242 interceptPowerKeyUp(event, interactive, canceled);
6247 case KeyEvent.KEYCODE_SLEEP: {
6248 result &= ~ACTION_PASS_TO_USER;
6250 if (!mPowerManager.isInteractive()) {
6251 useHapticFeedback = false; // suppress feedback if already non-interactive
6254 sleepPress(event.getEventTime());
6256 sleepRelease(event.getEventTime());
6261 case KeyEvent.KEYCODE_SOFT_SLEEP: {
6262 result &= ~ACTION_PASS_TO_USER;
6265 mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
6270 case KeyEvent.KEYCODE_WAKEUP: {
6271 result &= ~ACTION_PASS_TO_USER;
6276 case KeyEvent.KEYCODE_MEDIA_PLAY:
6277 case KeyEvent.KEYCODE_MEDIA_PAUSE:
6278 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6279 case KeyEvent.KEYCODE_HEADSETHOOK:
6280 case KeyEvent.KEYCODE_MUTE:
6281 case KeyEvent.KEYCODE_MEDIA_STOP:
6282 case KeyEvent.KEYCODE_MEDIA_NEXT:
6283 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6284 case KeyEvent.KEYCODE_MEDIA_REWIND:
6285 case KeyEvent.KEYCODE_MEDIA_RECORD:
6286 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6287 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
6288 if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
6289 // If the global session is active pass all media keys to it
6290 // instead of the active window.
6291 result &= ~ACTION_PASS_TO_USER;
6293 if ((result & ACTION_PASS_TO_USER) == 0) {
6294 // Only do this if we would otherwise not pass it to the user. In that
6295 // case, the PhoneWindow class will do the same thing, except it will
6296 // only do it if the showing app doesn't process the key on its own.
6297 // Note that we need to make a copy of the key event here because the
6298 // original key event will be recycled when we return.
6299 mBroadcastWakeLock.acquire();
6300 Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
6301 new KeyEvent(event));
6302 msg.setAsynchronous(true);
6308 case KeyEvent.KEYCODE_CALL: {
6310 TelecomManager telecomManager = getTelecommService();
6311 if (telecomManager != null) {
6312 if (telecomManager.isRinging()) {
6313 Log.i(TAG, "interceptKeyBeforeQueueing:"
6314 + " CALL key-down while ringing: Answer the call!");
6315 telecomManager.acceptRingingCall();
6317 // And *don't* pass this key thru to the current activity
6318 // (which is presumably the InCallScreen.)
6319 result &= ~ACTION_PASS_TO_USER;
6325 case KeyEvent.KEYCODE_VOICE_ASSIST: {
6326 // Only do this if we would otherwise not pass it to the user. In that case,
6327 // interceptKeyBeforeDispatching would apply a similar but different policy in
6328 // order to invoke voice assist actions. Note that we need to make a copy of the
6329 // key event here because the original key event will be recycled when we return.
6330 if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
6331 mBroadcastWakeLock.acquire();
6332 Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
6333 keyguardActive ? 1 : 0, 0);
6334 msg.setAsynchronous(true);
6339 case KeyEvent.KEYCODE_WINDOW: {
6340 if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
6341 if (mTvPictureInPictureVisible) {
6342 // Consumes the key only if picture-in-picture is visible
6343 // to show picture-in-picture control menu.
6344 // This gives a chance to the foreground activity
6345 // to customize PIP key behavior.
6347 showTvPictureInPictureMenu(event);
6349 result &= ~ACTION_PASS_TO_USER;
6356 if (useHapticFeedback) {
6357 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
6361 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
6367 private void scheduleLongPressKeyEvent(KeyEvent origEvent, int keyCode) {
6368 KeyEvent event = new KeyEvent(origEvent.getDownTime(), origEvent.getEventTime(),
6369 origEvent.getAction(), keyCode, 0);
6371 if (keyCode == KeyEvent.KEYCODE_CAMERA) {
6372 msg = mHandler.obtainMessage(MSG_CAMERA_LONG_PRESS, event);
6374 msg = mHandler.obtainMessage(MSG_DISPATCH_VOLKEY_WITH_WAKE_LOCK, event);
6376 msg.setAsynchronous(true);
6377 mHandler.sendMessageDelayed(msg, ViewConfiguration.getLongPressTimeout());
6381 * Returns true if the key can have global actions attached to it.
6382 * We reserve all power management keys for the system since they require
6383 * very careful handling.
6385 private static boolean isValidGlobalKey(int keyCode) {
6387 case KeyEvent.KEYCODE_POWER:
6388 case KeyEvent.KEYCODE_WAKEUP:
6389 case KeyEvent.KEYCODE_SLEEP:
6397 * Check if the given keyCode represents a key that is considered a wake key
6398 * and is currently enabled by the user in Settings or for another reason.
6400 private boolean isWakeKeyEnabled(int keyCode) {
6402 case KeyEvent.KEYCODE_VOLUME_UP:
6403 case KeyEvent.KEYCODE_VOLUME_DOWN:
6404 case KeyEvent.KEYCODE_VOLUME_MUTE:
6405 // Volume keys are still wake keys if the device is docked.
6406 return mVolumeWakeScreen || mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
6407 case KeyEvent.KEYCODE_BACK:
6408 return mBackWakeScreen;
6409 case KeyEvent.KEYCODE_MENU:
6410 return mMenuWakeScreen;
6411 case KeyEvent.KEYCODE_ASSIST:
6412 return mAssistWakeScreen;
6413 case KeyEvent.KEYCODE_APP_SWITCH:
6414 return mAppSwitchWakeScreen;
6415 case KeyEvent.KEYCODE_CAMERA:
6416 case KeyEvent.KEYCODE_FOCUS:
6417 return mCameraWakeScreen;
6423 * When the screen is off we ignore some keys that might otherwise typically
6424 * be considered wake keys. We filter them out here.
6426 * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
6427 * is always considered a wake key.
6429 private boolean isWakeKeyWhenScreenOff(int keyCode) {
6431 // ignore volume keys unless docked
6432 case KeyEvent.KEYCODE_VOLUME_UP:
6433 case KeyEvent.KEYCODE_VOLUME_DOWN:
6434 case KeyEvent.KEYCODE_VOLUME_MUTE:
6435 return mVolumeWakeScreen || mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
6437 // ignore media keys
6438 case KeyEvent.KEYCODE_MUTE:
6439 case KeyEvent.KEYCODE_HEADSETHOOK:
6440 case KeyEvent.KEYCODE_MEDIA_PLAY:
6441 case KeyEvent.KEYCODE_MEDIA_PAUSE:
6442 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6443 case KeyEvent.KEYCODE_MEDIA_STOP:
6444 case KeyEvent.KEYCODE_MEDIA_NEXT:
6445 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6446 case KeyEvent.KEYCODE_MEDIA_REWIND:
6447 case KeyEvent.KEYCODE_MEDIA_RECORD:
6448 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6449 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
6452 case KeyEvent.KEYCODE_BACK:
6453 return mBackWakeScreen;
6454 case KeyEvent.KEYCODE_MENU:
6455 return mMenuWakeScreen;
6456 case KeyEvent.KEYCODE_ASSIST:
6457 return mAssistWakeScreen;
6458 case KeyEvent.KEYCODE_APP_SWITCH:
6459 return mAppSwitchWakeScreen;
6460 case KeyEvent.KEYCODE_CAMERA:
6461 case KeyEvent.KEYCODE_FOCUS:
6462 return mCameraWakeScreen;
6468 /** {@inheritDoc} */
6470 public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
6471 if ((policyFlags & FLAG_WAKE) != 0) {
6472 if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
6473 "android.policy:MOTION")) {
6478 if (shouldDispatchInputWhenNonInteractive()) {
6479 return ACTION_PASS_TO_USER;
6482 // If we have not passed the action up and we are in theater mode without dreaming,
6483 // there will be no dream to intercept the touch and wake into ambient. The device should
6484 // wake up in this case.
6485 if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
6486 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
6487 "android.policy:MOTION");
6493 private boolean shouldDispatchInputWhenNonInteractive() {
6494 final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
6496 if (displayOff && !mHasFeatureWatch) {
6500 // Send events to keyguard while the screen is on and it's showing.
6501 if (isKeyguardShowingAndNotOccluded() && !displayOff) {
6505 // Send events to a dozing dream even if the screen is off since the dream
6506 // is in control of the state of the screen.
6507 IDreamManager dreamManager = getDreamManager();
6510 if (dreamManager != null && dreamManager.isDreaming()) {
6513 } catch (RemoteException e) {
6514 Slog.e(TAG, "RemoteException when checking if dreaming", e);
6517 // Otherwise, consume events since the user can't see what is being
6522 private void dispatchDirectAudioEvent(KeyEvent event) {
6523 if (event.getAction() != KeyEvent.ACTION_DOWN) {
6526 int keyCode = event.getKeyCode();
6527 int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
6528 | AudioManager.FLAG_FROM_KEY;
6529 String pkgName = mContext.getOpPackageName();
6531 case KeyEvent.KEYCODE_VOLUME_UP:
6533 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
6534 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6535 } catch (RemoteException e) {
6536 Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
6539 case KeyEvent.KEYCODE_VOLUME_DOWN:
6541 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
6542 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6543 } catch (RemoteException e) {
6544 Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
6547 case KeyEvent.KEYCODE_VOLUME_MUTE:
6549 if (event.getRepeatCount() == 0) {
6550 getAudioService().adjustSuggestedStreamVolume(
6551 AudioManager.ADJUST_TOGGLE_MUTE,
6552 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6554 } catch (RemoteException e) {
6555 Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
6561 void dispatchMediaKeyWithWakeLock(KeyEvent event) {
6563 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
6566 if (mHavePendingMediaKeyRepeatWithWakeLock) {
6568 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
6571 mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
6572 mHavePendingMediaKeyRepeatWithWakeLock = false;
6573 mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
6576 dispatchMediaKeyWithWakeLockToAudioService(event);
6578 if (event.getAction() == KeyEvent.ACTION_DOWN
6579 && event.getRepeatCount() == 0) {
6580 mHavePendingMediaKeyRepeatWithWakeLock = true;
6582 Message msg = mHandler.obtainMessage(
6583 MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
6584 msg.setAsynchronous(true);
6585 mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
6587 mBroadcastWakeLock.release();
6591 void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
6592 mHavePendingMediaKeyRepeatWithWakeLock = false;
6594 KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
6595 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6597 Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
6600 dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
6601 mBroadcastWakeLock.release();
6604 void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
6605 if (ActivityManagerNative.isSystemReady()) {
6606 MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
6610 void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
6611 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
6612 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
6615 dic.exitIdle("voice-search");
6616 } catch (RemoteException e) {
6619 Intent voiceIntent =
6620 new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
6621 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
6622 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
6623 mBroadcastWakeLock.release();
6626 BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
6628 public void onReceive(Context context, Intent intent) {
6629 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
6630 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6631 Intent.EXTRA_DOCK_STATE_UNDOCKED);
6634 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
6635 ServiceManager.getService(Context.UI_MODE_SERVICE));
6636 mUiMode = uiModeService.getCurrentModeType();
6637 } catch (RemoteException e) {
6640 updateRotation(true);
6641 synchronized (mLock) {
6642 updateOrientationListenerLp();
6647 BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
6649 public void onReceive(Context context, Intent intent) {
6650 if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
6651 if (mKeyguardDelegate != null) {
6652 mKeyguardDelegate.onDreamingStarted();
6654 } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
6655 if (mKeyguardDelegate != null) {
6656 mKeyguardDelegate.onDreamingStopped();
6662 BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
6664 public void onReceive(Context context, Intent intent) {
6665 if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
6666 // tickle the settings observer: this first ensures that we're
6667 // observing the relevant settings for the newly-active user,
6668 // and then updates our own bookkeeping based on the now-
6670 mSettingsObserver.onChange(false);
6672 // force a re-application of focused window sysui visibility.
6673 // the window may never have been shown for this user
6674 // e.g. the keyguard when going through the new-user setup flow
6675 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6676 mLastSystemUiFlags = 0;
6677 updateSystemUiVisibilityLw();
6683 private final Runnable mHiddenNavPanic = new Runnable() {
6686 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6687 if (!isUserSetupComplete()) {
6688 // Swipe-up for navigation bar is disabled during setup
6691 mPendingPanicGestureUptime = SystemClock.uptimeMillis();
6692 mNavigationBarController.showTransient();
6697 private void requestTransientBars(WindowState swipeTarget) {
6698 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6699 if (!isUserSetupComplete()) {
6700 // Swipe-up for navigation bar is disabled during setup
6703 boolean sb = mStatusBarController.checkShowTransientBarLw();
6704 boolean nb = mNavigationBarController.checkShowTransientBarLw();
6706 // Don't show status bar when swiping on already visible navigation bar
6707 if (!nb && swipeTarget == mNavigationBar) {
6708 if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
6711 if (sb) mStatusBarController.showTransient();
6712 if (nb) mNavigationBarController.showTransient();
6713 mImmersiveModeConfirmation.confirmCurrentPrompt();
6714 updateSystemUiVisibilityLw();
6720 BroadcastReceiver mWifiDisplayReceiver = new BroadcastReceiver() {
6721 public void onReceive(Context context, Intent intent) {
6722 String action = intent.getAction();
6723 if (action.equals(ACTION_WIFI_DISPLAY_VIDEO)) {
6724 int state = intent.getIntExtra("state", 0);
6726 mWifiDisplayConnected = true;
6728 mWifiDisplayConnected = false;
6730 mWifiDisplayCustomRotation =
6731 intent.getIntExtra("wfd_UIBC_rot", -1);
6732 updateRotation(true);
6737 // Called on the PowerManager's Notifier thread.
6739 public void startedGoingToSleep(int why) {
6740 if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
6741 mCameraGestureTriggeredDuringGoingToSleep = false;
6742 mGoingToSleep = true;
6743 if (mKeyguardDelegate != null) {
6744 mKeyguardDelegate.onStartedGoingToSleep(why);
6748 // Called on the PowerManager's Notifier thread.
6750 public void finishedGoingToSleep(int why) {
6751 EventLog.writeEvent(70000, 0);
6752 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
6753 MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
6755 mGoingToSleep = false;
6757 // We must get this work done here because the power manager will drop
6758 // the wake lock and let the system suspend once this function returns.
6759 synchronized (mLock) {
6761 updateWakeGestureListenerLp();
6762 updateOrientationListenerLp();
6763 updateLockScreenTimeout();
6765 if (mKeyguardDelegate != null) {
6766 mKeyguardDelegate.onFinishedGoingToSleep(why,
6767 mCameraGestureTriggeredDuringGoingToSleep);
6769 mCameraGestureTriggeredDuringGoingToSleep = false;
6772 // Called on the PowerManager's Notifier thread.
6774 public void startedWakingUp() {
6775 EventLog.writeEvent(70000, 1);
6776 if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
6778 // Since goToSleep performs these functions synchronously, we must
6779 // do the same here. We cannot post this work to a handler because
6780 // that might cause it to become reordered with respect to what
6781 // may happen in a future call to goToSleep.
6782 synchronized (mLock) {
6785 updateWakeGestureListenerLp();
6786 updateOrientationListenerLp();
6787 updateLockScreenTimeout();
6790 if (mKeyguardDelegate != null) {
6791 mKeyguardDelegate.onStartedWakingUp();
6795 // Called on the PowerManager's Notifier thread.
6797 public void finishedWakingUp() {
6798 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
6801 private void wakeUpFromPowerKey(long eventTime) {
6802 wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
6805 private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
6806 final boolean theaterModeEnabled = isTheaterModeEnabled();
6807 if (!wakeInTheaterMode && theaterModeEnabled) {
6811 if (theaterModeEnabled) {
6812 Settings.Global.putInt(mContext.getContentResolver(),
6813 Settings.Global.THEATER_MODE_ON, 0);
6816 mPowerManager.wakeUp(wakeTime, reason);
6820 private void finishKeyguardDrawn() {
6821 synchronized (mLock) {
6822 if (!mScreenOnEarly || mKeyguardDrawComplete) {
6823 return; // We are not awake yet or we have already informed of this event.
6826 mKeyguardDrawComplete = true;
6827 if (mKeyguardDelegate != null) {
6828 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6830 mWindowManagerDrawComplete = false;
6833 // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
6834 // as well as enabling the orientation change logic/sensor.
6835 mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
6836 WAITING_FOR_DRAWN_TIMEOUT);
6839 // Called on the DisplayManager's DisplayPowerController thread.
6841 public void screenTurnedOff() {
6842 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
6844 updateScreenOffSleepToken(true);
6845 synchronized (mLock) {
6846 mScreenOnEarly = false;
6847 mScreenOnFully = false;
6848 mKeyguardDrawComplete = false;
6849 mWindowManagerDrawComplete = false;
6850 mScreenOnListener = null;
6851 updateOrientationListenerLp();
6853 if (mKeyguardDelegate != null) {
6854 mKeyguardDelegate.onScreenTurnedOff();
6859 // Called on the DisplayManager's DisplayPowerController thread.
6861 public void screenTurningOn(final ScreenOnListener screenOnListener) {
6862 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
6864 updateScreenOffSleepToken(false);
6865 synchronized (mLock) {
6866 mScreenOnEarly = true;
6867 mScreenOnFully = false;
6868 mKeyguardDrawComplete = false;
6869 mWindowManagerDrawComplete = false;
6870 mScreenOnListener = screenOnListener;
6872 if (mKeyguardDelegate != null) {
6873 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6874 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
6875 mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
6877 if (DEBUG_WAKEUP) Slog.d(TAG,
6878 "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
6879 finishKeyguardDrawn();
6884 // Called on the DisplayManager's DisplayPowerController thread.
6886 public void screenTurnedOn() {
6887 synchronized (mLock) {
6888 if (mKeyguardDelegate != null) {
6889 mKeyguardDelegate.onScreenTurnedOn();
6894 private void finishWindowsDrawn() {
6895 synchronized (mLock) {
6896 if (!mScreenOnEarly || mWindowManagerDrawComplete) {
6897 return; // Screen is not turned on or we did already handle this case earlier.
6900 mWindowManagerDrawComplete = true;
6903 finishScreenTurningOn();
6906 private void finishScreenTurningOn() {
6907 synchronized (mLock) {
6908 // We have just finished drawing screen content. Since the orientation listener
6909 // gets only installed when all windows are drawn, we try to install it again.
6910 updateOrientationListenerLp();
6912 final ScreenOnListener listener;
6913 final boolean enableScreen;
6914 synchronized (mLock) {
6915 if (DEBUG_WAKEUP) Slog.d(TAG,
6916 "finishScreenTurningOn: mAwake=" + mAwake
6917 + ", mScreenOnEarly=" + mScreenOnEarly
6918 + ", mScreenOnFully=" + mScreenOnFully
6919 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
6920 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
6922 if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
6923 || (mAwake && !mKeyguardDrawComplete)) {
6924 return; // spurious or not ready yet
6927 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
6928 listener = mScreenOnListener;
6929 mScreenOnListener = null;
6930 mScreenOnFully = true;
6932 // Remember the first time we draw the keyguard so we know when we're done with
6933 // the main part of booting and can enable the screen and hide boot messages.
6934 if (!mKeyguardDrawnOnce && mAwake) {
6935 mKeyguardDrawnOnce = true;
6936 enableScreen = true;
6937 if (mBootMessageNeedsHiding) {
6938 mBootMessageNeedsHiding = false;
6942 enableScreen = false;
6946 if (listener != null) {
6947 listener.onScreenOn();
6952 mWindowManager.enableScreenIfNeeded();
6953 } catch (RemoteException unhandled) {
6958 private void handleHideBootMessage() {
6959 synchronized (mLock) {
6960 if (!mKeyguardDrawnOnce) {
6961 mBootMessageNeedsHiding = true;
6962 return; // keyguard hasn't drawn the first time yet, not done booting
6966 if (mBootMsgDialog != null) {
6967 if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
6968 mBootMsgDialog.dismiss();
6969 mBootMsgDialog = null;
6974 public boolean isScreenOn() {
6975 return mScreenOnFully;
6978 /** {@inheritDoc} */
6980 public void enableKeyguard(boolean enabled) {
6981 if (mKeyguardDelegate != null) {
6982 mKeyguardDelegate.setKeyguardEnabled(enabled);
6986 /** {@inheritDoc} */
6988 public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
6989 if (mKeyguardDelegate != null) {
6990 mKeyguardDelegate.verifyUnlock(callback);
6994 private boolean isKeyguardShowingAndNotOccluded() {
6995 if (mKeyguardDelegate == null) return false;
6996 return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
6999 /** {@inheritDoc} */
7001 public boolean isKeyguardLocked() {
7002 return keyguardOn();
7005 /** {@inheritDoc} */
7007 public boolean isKeyguardSecure(int userId) {
7008 if (mKeyguardDelegate == null) return false;
7009 return mKeyguardDelegate.isSecure(userId);
7012 /** {@inheritDoc} */
7014 public boolean isKeyguardShowingOrOccluded() {
7015 return mKeyguardDelegate == null ? false : mKeyguardDelegate.isShowing();
7018 /** {@inheritDoc} */
7020 public boolean inKeyguardRestrictedKeyInputMode() {
7021 if (mKeyguardDelegate == null) return false;
7022 return mKeyguardDelegate.isInputRestricted();
7026 public void dismissKeyguardLw() {
7027 if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
7028 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
7029 mHandler.post(new Runnable() {
7032 // ask the keyguard to prompt the user to authenticate if necessary
7033 mKeyguardDelegate.dismiss();
7040 public void notifyActivityDrawnForKeyguardLw() {
7041 if (mKeyguardDelegate != null) {
7042 mHandler.post(new Runnable() {
7045 mKeyguardDelegate.onActivityDrawn();
7052 public boolean isKeyguardDrawnLw() {
7053 synchronized (mLock) {
7054 return mKeyguardDrawnOnce;
7059 public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
7060 if (mKeyguardDelegate != null) {
7061 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
7062 mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
7067 public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
7069 outInsets.setEmpty();
7071 // Navigation bar and status bar.
7072 getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
7073 if (mStatusBar != null) {
7074 outInsets.top = mStatusBarHeight;
7079 public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
7081 outInsets.setEmpty();
7083 // Only navigation bar
7084 if (mNavigationBar != null) {
7085 if (isNavigationBarOnBottom(displayWidth, displayHeight)) {
7086 outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
7088 outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
7094 public boolean isNavBarForcedShownLw(WindowState windowState) {
7095 return mForceShowSystemBars;
7099 public boolean isDockSideAllowed(int dockSide) {
7101 // We do not allow all dock sides at which the navigation bar touches the docked stack.
7102 if (!mNavigationBarCanMove) {
7103 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT;
7105 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT;
7109 void sendCloseSystemWindows() {
7110 PhoneWindow.sendCloseSystemWindows(mContext, null);
7113 void sendCloseSystemWindows(String reason) {
7114 PhoneWindow.sendCloseSystemWindows(mContext, reason);
7118 public int rotationForOrientationLw(int orientation, int lastRotation) {
7120 Slog.v(TAG, "rotationForOrientationLw(orient="
7121 + orientation + ", last=" + lastRotation
7122 + "); user=" + mUserRotation + " "
7123 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
7124 ? "USER_ROTATION_LOCKED" : "")
7128 if (mForceDefaultOrientation) {
7129 return Surface.ROTATION_0;
7132 synchronized (mLock) {
7133 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
7134 if (sensorRotation < 0) {
7135 sensorRotation = lastRotation;
7138 final int preferredRotation;
7139 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
7140 // Ignore sensor when lid switch is open and rotation is forced.
7141 preferredRotation = mLidOpenRotation;
7142 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
7143 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
7144 // Ignore sensor when in car dock unless explicitly enabled.
7145 // This case can override the behavior of NOSENSOR, and can also
7146 // enable 180 degree rotation while docked.
7147 preferredRotation = mCarDockEnablesAccelerometer
7148 ? sensorRotation : mCarDockRotation;
7149 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7150 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
7151 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
7152 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
7153 // Ignore sensor when in desk dock unless explicitly enabled.
7154 // This case can override the behavior of NOSENSOR, and can also
7155 // enable 180 degree rotation while docked.
7156 preferredRotation = mDeskDockEnablesAccelerometer
7157 ? sensorRotation : mDeskDockRotation;
7158 } else if ((mHdmiPlugged || mWifiDisplayConnected) && mDemoHdmiRotationLock) {
7159 // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
7160 // Note that the dock orientation overrides the HDMI orientation.
7161 preferredRotation = mDemoHdmiRotation;
7162 } else if (mWifiDisplayConnected && (mWifiDisplayCustomRotation > -1)) {
7163 // Ignore sensor when WFD is active and UIBC rotation is enabled
7164 preferredRotation = mWifiDisplayCustomRotation;
7165 } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
7166 && mUndockedHdmiRotation >= 0) {
7167 // Ignore sensor when plugged into HDMI and an undocked orientation has
7168 // been specified in the configuration (only for legacy devices without
7169 // full multi-display support).
7170 // Note that the dock orientation overrides the HDMI orientation.
7171 preferredRotation = mUndockedHdmiRotation;
7172 } else if (mDemoRotationLock) {
7173 // Ignore sensor when demo rotation lock is enabled.
7174 // Note that the dock orientation and HDMI rotation lock override this.
7175 preferredRotation = mDemoRotation;
7176 } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
7177 // Application just wants to remain locked in the last rotation.
7178 preferredRotation = lastRotation;
7179 } else if (!mSupportAutoRotation) {
7180 // If we don't support auto-rotation then bail out here and ignore
7181 // the sensor and any rotation lock settings.
7182 preferredRotation = -1;
7183 } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
7184 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
7185 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
7186 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
7187 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
7188 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
7189 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
7190 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
7191 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
7192 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
7193 // Otherwise, use sensor only if requested by the application or enabled
7194 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR.
7195 if (mAllowAllRotations < 0) {
7196 // Can't read this during init() because the context doesn't
7197 // have display metrics at that time so we cannot determine
7198 // tablet vs. phone then.
7199 mAllowAllRotations = mContext.getResources().getBoolean(
7200 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
7202 if (sensorRotation != Surface.ROTATION_180
7203 || mAllowAllRotations == 1
7204 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
7205 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
7206 preferredRotation = sensorRotation;
7208 preferredRotation = lastRotation;
7210 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
7211 && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
7212 // Apply rotation lock. Does not apply to NOSENSOR.
7213 // The idea is that the user rotation expresses a weak preference for the direction
7214 // of gravity and as NOSENSOR is never affected by gravity, then neither should
7215 // NOSENSOR be affected by rotation lock (although it will be affected by docks).
7216 preferredRotation = mUserRotation;
7218 // No overriding preference.
7219 // We will do exactly what the application asked us to do.
7220 preferredRotation = -1;
7223 switch (orientation) {
7224 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
7225 // Return portrait unless overridden.
7226 if (isAnyPortrait(preferredRotation)) {
7227 return preferredRotation;
7229 return mPortraitRotation;
7231 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
7232 // Return landscape unless overridden.
7233 if (isLandscapeOrSeascape(preferredRotation)) {
7234 return preferredRotation;
7236 return mLandscapeRotation;
7238 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
7239 // Return reverse portrait unless overridden.
7240 if (isAnyPortrait(preferredRotation)) {
7241 return preferredRotation;
7243 return mUpsideDownRotation;
7245 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
7246 // Return seascape unless overridden.
7247 if (isLandscapeOrSeascape(preferredRotation)) {
7248 return preferredRotation;
7250 return mSeascapeRotation;
7252 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
7253 case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
7254 // Return either landscape rotation.
7255 if (isLandscapeOrSeascape(preferredRotation)) {
7256 return preferredRotation;
7258 if (isLandscapeOrSeascape(lastRotation)) {
7259 return lastRotation;
7261 return mLandscapeRotation;
7263 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
7264 case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
7265 // Return either portrait rotation.
7266 if (isAnyPortrait(preferredRotation)) {
7267 return preferredRotation;
7269 if (isAnyPortrait(lastRotation)) {
7270 return lastRotation;
7272 return mPortraitRotation;
7275 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
7276 // just return the preferred orientation we already calculated.
7277 if (preferredRotation >= 0) {
7278 return preferredRotation;
7280 return Surface.ROTATION_0;
7286 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
7287 switch (orientation) {
7288 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
7289 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
7290 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
7291 return isAnyPortrait(rotation);
7293 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
7294 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
7295 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
7296 return isLandscapeOrSeascape(rotation);
7304 public void setRotationLw(int rotation) {
7305 mOrientationListener.setCurrentRotation(rotation);
7308 private boolean isLandscapeOrSeascape(int rotation) {
7309 return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
7312 private boolean isAnyPortrait(int rotation) {
7313 return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
7317 public int getUserRotationMode() {
7318 return Settings.System.getIntForUser(mContext.getContentResolver(),
7319 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
7320 WindowManagerPolicy.USER_ROTATION_FREE :
7321 WindowManagerPolicy.USER_ROTATION_LOCKED;
7324 // User rotation: to be used when all else fails in assigning an orientation to the device
7326 public void setUserRotationMode(int mode, int rot) {
7327 ContentResolver res = mContext.getContentResolver();
7329 // mUserRotationMode and mUserRotation will be assigned by the content observer
7330 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
7331 Settings.System.putIntForUser(res,
7332 Settings.System.USER_ROTATION,
7334 UserHandle.USER_CURRENT);
7335 Settings.System.putIntForUser(res,
7336 Settings.System.ACCELEROMETER_ROTATION,
7338 UserHandle.USER_CURRENT);
7340 Settings.System.putIntForUser(res,
7341 Settings.System.ACCELEROMETER_ROTATION,
7343 UserHandle.USER_CURRENT);
7348 public void setSafeMode(boolean safeMode) {
7349 mSafeMode = safeMode;
7350 performHapticFeedbackLw(null, safeMode
7351 ? HapticFeedbackConstants.SAFE_MODE_ENABLED
7352 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
7355 static long[] getLongIntArray(Resources r, int resid) {
7356 int[] ar = r.getIntArray(resid);
7360 long[] out = new long[ar.length];
7361 for (int i=0; i<ar.length; i++) {
7367 /** {@inheritDoc} */
7369 public void systemReady() {
7370 mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
7371 mKeyguardDelegate.onSystemReady();
7373 readCameraLensCoverState();
7375 boolean bindKeyguardNow;
7376 synchronized (mLock) {
7377 updateOrientationListenerLp();
7378 mSystemReady = true;
7379 mHandler.post(new Runnable() {
7386 bindKeyguardNow = mDeferBindKeyguard;
7387 if (bindKeyguardNow) {
7388 // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now.
7389 mDeferBindKeyguard = false;
7393 if (bindKeyguardNow) {
7394 mKeyguardDelegate.bindService(mContext);
7395 mKeyguardDelegate.onBootCompleted();
7397 mSystemGestures.systemReady();
7398 mImmersiveModeConfirmation.systemReady();
7401 /** {@inheritDoc} */
7403 public void systemBooted() {
7404 boolean bindKeyguardNow = false;
7405 synchronized (mLock) {
7406 // Time to bind Keyguard; take care to only bind it once, either here if ready or
7407 // in systemReady if not.
7408 if (mKeyguardDelegate != null) {
7409 bindKeyguardNow = true;
7411 // Because mKeyguardDelegate is null, we know that the synchronized block in
7412 // systemReady didn't run yet and setting this will actually have an effect.
7413 mDeferBindKeyguard = true;
7416 if (bindKeyguardNow) {
7417 mKeyguardDelegate.bindService(mContext);
7418 mKeyguardDelegate.onBootCompleted();
7420 synchronized (mLock) {
7421 mSystemBooted = true;
7424 screenTurningOn(null);
7428 ProgressDialog mBootMsgDialog = null;
7430 /** {@inheritDoc} */
7432 public void showBootMessage(final CharSequence msg, final boolean always) {
7433 mHandler.post(new Runnable() {
7434 @Override public void run() {
7435 if (mBootMsgDialog == null) {
7437 if (mHasFeatureWatch) {
7438 theme = com.android.internal.R.style.Theme_Micro_Dialog_Alert;
7439 } else if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) {
7440 theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
7445 mBootMsgDialog = new ProgressDialog(mContext, theme) {
7446 // This dialog will consume all events coming in to
7447 // it, to avoid it trying to do things too early in boot.
7448 @Override public boolean dispatchKeyEvent(KeyEvent event) {
7451 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7454 @Override public boolean dispatchTouchEvent(MotionEvent ev) {
7457 @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
7460 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
7463 @Override public boolean dispatchPopulateAccessibilityEvent(
7464 AccessibilityEvent event) {
7468 if (mContext.getPackageManager().isUpgrade()) {
7469 mBootMsgDialog.setTitle(R.string.android_upgrading_title);
7471 mBootMsgDialog.setTitle(R.string.android_start_title);
7473 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
7474 mBootMsgDialog.setIndeterminate(true);
7475 mBootMsgDialog.getWindow().setType(
7476 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
7477 mBootMsgDialog.getWindow().addFlags(
7478 WindowManager.LayoutParams.FLAG_DIM_BEHIND
7479 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
7480 mBootMsgDialog.getWindow().setDimAmount(1);
7481 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
7482 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
7483 mBootMsgDialog.getWindow().setAttributes(lp);
7484 mBootMsgDialog.setCancelable(false);
7485 mBootMsgDialog.show();
7487 mBootMsgDialog.setMessage(msg);
7492 /** {@inheritDoc} */
7494 public void hideBootMessages() {
7495 mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
7498 /** {@inheritDoc} */
7500 public void userActivity() {
7501 // ***************************************
7502 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
7503 // ***************************************
7504 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
7505 // WITH ITS LOCKS HELD.
7507 // This code must be VERY careful about the locks
7509 // In fact, the current code acquires way too many,
7510 // and probably has lurking deadlocks.
7512 synchronized (mScreenLockTimeout) {
7513 if (mLockScreenTimerActive) {
7515 mHandler.removeCallbacks(mScreenLockTimeout);
7516 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7521 class ScreenLockTimeout implements Runnable {
7526 synchronized (this) {
7527 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
7528 if (mKeyguardDelegate != null) {
7529 mKeyguardDelegate.doKeyguardTimeout(options);
7531 mLockScreenTimerActive = false;
7536 public void setLockOptions(Bundle options) {
7537 this.options = options;
7541 ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
7544 public void lockNow(Bundle options) {
7545 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
7546 mHandler.removeCallbacks(mScreenLockTimeout);
7547 if (options != null) {
7548 // In case multiple calls are made to lockNow, we don't wipe out the options
7549 // until the runnable actually executes.
7550 mScreenLockTimeout.setLockOptions(options);
7552 mHandler.post(mScreenLockTimeout);
7555 private void updateLockScreenTimeout() {
7556 synchronized (mScreenLockTimeout) {
7557 boolean enable = (mAllowLockscreenWhenOn && mAwake &&
7558 mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
7559 if (mLockScreenTimerActive != enable) {
7561 if (localLOGV) Log.v(TAG, "setting lockscreen timer");
7562 mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
7563 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7565 if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
7566 mHandler.removeCallbacks(mScreenLockTimeout);
7568 mLockScreenTimerActive = enable;
7573 private void updateDreamingSleepToken(boolean acquire) {
7575 if (mDreamingSleepToken == null) {
7576 mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream");
7579 if (mDreamingSleepToken != null) {
7580 mDreamingSleepToken.release();
7581 mDreamingSleepToken = null;
7586 private void updateScreenOffSleepToken(boolean acquire) {
7588 if (mScreenOffSleepToken == null) {
7589 mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff");
7592 if (mScreenOffSleepToken != null) {
7593 mScreenOffSleepToken.release();
7594 mScreenOffSleepToken = null;
7599 /** {@inheritDoc} */
7601 public void enableScreenAfterBoot() {
7603 applyLidSwitchState();
7604 updateRotation(true);
7607 private void applyLidSwitchState() {
7608 mPowerManager.setKeyboardVisibility(isBuiltInKeyboardVisible());
7610 if (mLidState == LID_CLOSED && mLidControlsSleep) {
7611 mPowerManager.goToSleep(SystemClock.uptimeMillis(),
7612 PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
7613 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
7614 } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
7615 mWindowManagerFuncs.lockDeviceNow();
7618 synchronized (mLock) {
7619 updateWakeGestureListenerLp();
7623 void updateUiMode() {
7624 if (mUiModeManager == null) {
7625 mUiModeManager = IUiModeManager.Stub.asInterface(
7626 ServiceManager.getService(Context.UI_MODE_SERVICE));
7629 mUiMode = mUiModeManager.getCurrentModeType();
7630 } catch (RemoteException e) {
7634 void updateRotation(boolean alwaysSendConfiguration) {
7636 //set orientation on WindowManager
7637 mWindowManager.updateRotation(alwaysSendConfiguration, false);
7638 } catch (RemoteException e) {
7643 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
7645 //set orientation on WindowManager
7646 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
7647 } catch (RemoteException e) {
7653 * Return an Intent to launch the currently active dock app as home. Returns
7654 * null if the standard home should be launched, which is the case if any of the following is
7657 * <li>The device is not in either car mode or desk mode
7658 * <li>The device is in car mode but mEnableCarDockHomeCapture is false
7659 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
7660 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
7661 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
7663 * @return A dock intent.
7665 Intent createHomeDockIntent() {
7666 Intent intent = null;
7668 // What home does is based on the mode, not the dock state. That
7669 // is, when in car mode you should be taken to car home regardless
7670 // of whether we are actually in a car dock.
7671 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
7672 if (mEnableCarDockHomeCapture) {
7673 intent = mCarDockIntent;
7675 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
7676 if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
7677 intent = mDeskDockIntent;
7679 } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
7680 && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7681 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
7682 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
7683 // Always launch dock home from home when watch is docked, if it exists.
7684 intent = mDeskDockIntent;
7687 if (intent == null) {
7691 ActivityInfo ai = null;
7692 ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
7694 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
7697 ai = info.activityInfo;
7700 && ai.metaData != null
7701 && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
7702 intent = new Intent(intent);
7703 intent.setClassName(ai.packageName, ai.name);
7710 void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
7711 if (awakenFromDreams) {
7715 Intent dock = createHomeDockIntent();
7719 dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7721 startActivityAsUser(dock, UserHandle.CURRENT);
7723 } catch (ActivityNotFoundException e) {
7730 intent = new Intent(mHomeIntent);
7731 intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7733 intent = mHomeIntent;
7736 startActivityAsUser(intent, UserHandle.CURRENT);
7740 * goes to the home screen
7741 * @return whether it did anything
7744 if (!isUserSetupComplete()) {
7745 Slog.i(TAG, "Not going home because user setup is in progress.");
7749 // This code always brings home to the front.
7751 ActivityManagerNative.getDefault().stopAppSwitches();
7752 } catch (RemoteException e) {
7754 sendCloseSystemWindows();
7755 startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
7757 // This code brings home to the front or, if it is already
7758 // at the front, puts the device to sleep.
7760 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
7761 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
7762 Log.d(TAG, "UTS-TEST-MODE");
7764 ActivityManagerNative.getDefault().stopAppSwitches();
7765 sendCloseSystemWindows();
7766 Intent dock = createHomeDockIntent();
7768 int result = ActivityManagerNative.getDefault()
7769 .startActivityAsUser(null, null, dock,
7770 dock.resolveTypeIfNeeded(mContext.getContentResolver()),
7772 ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7773 null, null, UserHandle.USER_CURRENT);
7774 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7779 int result = ActivityManagerNative.getDefault()
7780 .startActivityAsUser(null, null, mHomeIntent,
7781 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
7783 ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7784 null, null, UserHandle.USER_CURRENT);
7785 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7788 } catch (RemoteException ex) {
7789 // bummer, the activity manager, which is in this process, is dead
7796 public void setCurrentOrientationLw(int newOrientation) {
7797 synchronized (mLock) {
7798 if (newOrientation != mCurrentAppOrientation) {
7799 mCurrentAppOrientation = newOrientation;
7800 updateOrientationListenerLp();
7805 private void performAuditoryFeedbackForAccessibilityIfNeed() {
7806 if (!isGlobalAccessibilityGestureEnabled()) {
7809 AudioManager audioManager = (AudioManager) mContext.getSystemService(
7810 Context.AUDIO_SERVICE);
7811 if (audioManager.isSilentMode()) {
7814 Ringtone ringTone = RingtoneManager.getRingtone(mContext,
7815 Settings.System.DEFAULT_NOTIFICATION_URI);
7816 ringTone.setStreamType(AudioManager.STREAM_MUSIC);
7820 private boolean isTheaterModeEnabled() {
7821 return Settings.Global.getInt(mContext.getContentResolver(),
7822 Settings.Global.THEATER_MODE_ON, 0) == 1;
7825 private boolean isGlobalAccessibilityGestureEnabled() {
7826 return Settings.Global.getInt(mContext.getContentResolver(),
7827 Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1;
7831 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
7832 if (!mVibrator.hasVibrator()) {
7835 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
7836 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
7837 if (hapticsDisabled && !always) {
7840 long[] pattern = null;
7842 case HapticFeedbackConstants.LONG_PRESS:
7843 pattern = mLongPressVibePattern;
7845 case HapticFeedbackConstants.VIRTUAL_KEY:
7846 pattern = mVirtualKeyVibePattern;
7848 case HapticFeedbackConstants.KEYBOARD_TAP:
7849 pattern = mKeyboardTapVibePattern;
7851 case HapticFeedbackConstants.CLOCK_TICK:
7852 pattern = mClockTickVibePattern;
7854 case HapticFeedbackConstants.CALENDAR_DATE:
7855 pattern = mCalendarDateVibePattern;
7857 case HapticFeedbackConstants.SAFE_MODE_DISABLED:
7858 pattern = mSafeModeDisabledVibePattern;
7860 case HapticFeedbackConstants.SAFE_MODE_ENABLED:
7861 pattern = mSafeModeEnabledVibePattern;
7863 case HapticFeedbackConstants.CONTEXT_CLICK:
7864 pattern = mContextClickVibePattern;
7870 String owningPackage;
7872 owningUid = win.getOwningUid();
7873 owningPackage = win.getOwningPackage();
7875 owningUid = android.os.Process.myUid();
7876 owningPackage = mContext.getOpPackageName();
7878 if (pattern.length == 1) {
7879 // One-shot vibration
7880 mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES);
7882 // Pattern vibration
7883 mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES);
7889 public void keepScreenOnStartedLw() {
7893 public void keepScreenOnStoppedLw() {
7894 if (isKeyguardShowingAndNotOccluded()) {
7895 mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
7899 private int updateSystemUiVisibilityLw() {
7900 // If there is no window focused, there will be nobody to handle the events
7901 // anyway, so just hang on in whatever state we're in until things settle down.
7902 final WindowState win = mFocusedWindow != null ? mFocusedWindow
7903 : mTopFullscreenOpaqueWindowState;
7907 if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) {
7908 // We are updating at a point where the keyguard has gotten
7909 // focus, but we were last in a state where the top window is
7910 // hiding it. This is probably because the keyguard as been
7911 // shown while the top window was displayed, so we want to ignore
7912 // it here because this is just a very transient change and it
7913 // will quickly lose focus once it correctly gets hidden.
7917 int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
7918 & ~mResettingSystemUiFlags
7919 & ~mForceClearedSystemUiFlags;
7920 if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
7921 tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
7924 final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
7925 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
7926 final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
7927 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
7928 mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);
7929 mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);
7930 final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
7931 final int diff = visibility ^ mLastSystemUiFlags;
7932 final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
7933 final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
7934 final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
7935 if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
7936 && mFocusedApp == win.getAppToken()
7937 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
7938 && mLastDockedStackBounds.equals(mDockedStackBounds)) {
7941 mLastSystemUiFlags = visibility;
7942 mLastFullscreenStackSysUiFlags = fullscreenVisibility;
7943 mLastDockedStackSysUiFlags = dockedVisibility;
7944 mLastFocusNeedsMenu = needsMenu;
7945 mFocusedApp = win.getAppToken();
7946 final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
7947 final Rect dockedStackBounds = new Rect(mDockedStackBounds);
7948 mHandler.post(new Runnable() {
7951 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
7952 if (statusbar != null) {
7953 statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
7954 dockedVisibility, 0xffffffff, fullscreenStackBounds,
7955 dockedStackBounds, win.toString());
7956 statusbar.topAppWindowChanged(needsMenu);
7963 private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
7964 WindowState statusColorWin = isStatusBarKeyguard() && !mHideLockScreen
7968 if (statusColorWin != null) {
7969 if (statusColorWin == opaque) {
7970 // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7972 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7973 vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
7974 & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7975 } else if (statusColorWin != null && statusColorWin.isDimming()) {
7976 // Otherwise if it's dimming, clear the light flag.
7977 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7983 private boolean drawsSystemBarBackground(WindowState win) {
7984 return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
7987 private boolean forcesDrawStatusBarBackground(WindowState win) {
7988 return win == null || (win.getAttrs().privateFlags
7989 & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
7992 private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
7993 final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
7994 final boolean freeformStackVisible =
7995 mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
7996 final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
7998 // We need to force system bars when the docked stack is visible, when the freeform stack
7999 // is visible but also when we are resizing for the transitions when docked stack
8000 // visibility changes.
8001 mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
8002 final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
8004 // apply translucent bar vis flags
8005 WindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen
8007 : mTopFullscreenOpaqueWindowState;
8008 vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
8009 vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
8010 final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
8011 mTopDockedOpaqueWindowState, 0, 0);
8013 final boolean fullscreenDrawsStatusBarBackground =
8014 (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
8015 && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
8016 || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
8017 final boolean dockedDrawsStatusBarBackground =
8018 (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
8019 && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
8020 || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
8022 // prevent status bar interaction from clearing certain flags
8023 int type = win.getAttrs().type;
8024 boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
8025 if (statusBarHasFocus && !isStatusBarKeyguard()) {
8026 int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
8027 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
8028 | View.SYSTEM_UI_FLAG_IMMERSIVE
8029 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
8030 | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
8031 if (mHideLockScreen) {
8032 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
8034 vis = (vis & ~flags) | (oldVis & flags);
8037 if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
8038 vis |= View.STATUS_BAR_TRANSPARENT;
8039 vis &= ~View.STATUS_BAR_TRANSLUCENT;
8040 } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
8041 || forceOpaqueStatusBar) {
8042 vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
8045 vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
8047 // update status bar
8048 boolean immersiveSticky =
8049 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
8050 final boolean hideStatusBarWM =
8051 mTopFullscreenOpaqueWindowState != null
8052 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
8053 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
8054 final boolean hideStatusBarSysui =
8055 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
8056 final boolean hideNavBarSysui =
8057 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
8059 final boolean transientStatusBarAllowed = mStatusBar != null
8060 && (statusBarHasFocus || (!mForceShowSystemBars
8061 && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
8063 final boolean transientNavBarAllowed = mNavigationBar != null
8064 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
8066 final long now = SystemClock.uptimeMillis();
8067 final boolean pendingPanic = mPendingPanicGestureUptime != 0
8068 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
8069 if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
8070 // The user performed the panic gesture recently, we're about to hide the bars,
8071 // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
8072 mPendingPanicGestureUptime = 0;
8073 mStatusBarController.showTransient();
8074 mNavigationBarController.showTransient();
8077 final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
8078 && !transientStatusBarAllowed && hideStatusBarSysui;
8079 final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
8080 && !transientNavBarAllowed;
8081 if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
8082 // clear the clearable flags instead
8083 clearClearableFlagsLw();
8084 vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
8087 final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
8088 immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
8089 final boolean navAllowedHidden = immersive || immersiveSticky;
8091 if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType())
8092 > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) {
8093 // We can't hide the navbar from this window otherwise the input consumer would not get
8094 // the input events.
8095 vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
8098 vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
8100 // update navigation bar
8101 boolean oldImmersiveMode = isImmersiveMode(oldVis);
8102 boolean newImmersiveMode = isImmersiveMode(vis);
8103 if (win != null && oldImmersiveMode != newImmersiveMode) {
8104 final String pkg = win.getOwningPackage();
8105 mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
8106 isUserSetupComplete());
8109 vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
8115 * @return the current visibility flags with the nav-bar opacity related flags toggled based
8116 * on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
8118 private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
8119 boolean freeformStackVisible, boolean isDockedDividerResizing) {
8120 if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
8121 if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
8122 visibility = setNavBarOpaqueFlag(visibility);
8124 } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
8125 if (isDockedDividerResizing) {
8126 visibility = setNavBarOpaqueFlag(visibility);
8127 } else if (freeformStackVisible) {
8128 visibility = setNavBarTranslucentFlag(visibility);
8130 visibility = setNavBarOpaqueFlag(visibility);
8134 if (!areTranslucentBarsAllowed()) {
8135 visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
8140 private int setNavBarOpaqueFlag(int visibility) {
8141 return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
8144 private int setNavBarTranslucentFlag(int visibility) {
8145 visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
8146 return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
8149 private void clearClearableFlagsLw() {
8150 int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
8151 if (newVal != mResettingSystemUiFlags) {
8152 mResettingSystemUiFlags = newVal;
8153 mWindowManagerFuncs.reevaluateStatusBarVisibility();
8157 private boolean isImmersiveMode(int vis) {
8158 final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
8159 return mNavigationBar != null
8160 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
8161 && (vis & flags) != 0
8162 && canHideNavigationBar();
8166 * @return whether the navigation or status bar can be made translucent
8168 * This should return true unless touch exploration is not enabled or
8169 * R.boolean.config_enableTranslucentDecor is false.
8171 private boolean areTranslucentBarsAllowed() {
8172 return mTranslucentDecorEnabled;
8175 // Use this instead of checking config_showNavigationBar so that it can be consistently
8176 // overridden by qemu.hw.mainkeys in the emulator.
8178 public boolean hasNavigationBar() {
8179 return mHasNavigationBar;
8183 public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
8184 mLastInputMethodWindow = ime;
8185 mLastInputMethodTargetWindow = target;
8189 public int getInputMethodWindowVisibleHeightLw() {
8190 return mDockBottom - mCurBottom;
8194 public void setCurrentUserLw(int newUserId) {
8195 mCurrentUserId = newUserId;
8196 if (mKeyguardDelegate != null) {
8197 mKeyguardDelegate.setCurrentUser(newUserId);
8199 StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
8200 if (statusBar != null) {
8201 statusBar.setCurrentUser(newUserId);
8203 setLastInputMethodWindowLw(null, null);
8207 public boolean canMagnifyWindow(int windowType) {
8208 switch (windowType) {
8209 case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
8210 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
8211 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
8212 case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
8220 public boolean isTopLevelWindow(int windowType) {
8221 if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
8222 && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
8223 return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
8229 public void dump(String prefix, PrintWriter pw, String[] args) {
8230 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
8231 pw.print(" mSystemReady="); pw.print(mSystemReady);
8232 pw.print(" mSystemBooted="); pw.println(mSystemBooted);
8233 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
8234 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
8235 pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
8236 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
8237 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
8238 || mForceClearedSystemUiFlags != 0) {
8239 pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
8240 pw.print(Integer.toHexString(mLastSystemUiFlags));
8241 pw.print(" mResettingSystemUiFlags=0x");
8242 pw.print(Integer.toHexString(mResettingSystemUiFlags));
8243 pw.print(" mForceClearedSystemUiFlags=0x");
8244 pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
8246 if (mLastFocusNeedsMenu) {
8247 pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
8248 pw.println(mLastFocusNeedsMenu);
8250 pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
8251 pw.println(mWakeGestureEnabledSetting);
8253 pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
8254 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
8255 pw.print(" mDockMode="); pw.print(mDockMode);
8256 pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
8257 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
8258 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
8259 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
8260 pw.print(" mUserRotation="); pw.print(mUserRotation);
8261 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
8262 pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
8263 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
8264 pw.print(mCarDockEnablesAccelerometer);
8265 pw.print(" mDeskDockEnablesAccelerometer=");
8266 pw.println(mDeskDockEnablesAccelerometer);
8267 pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
8268 pw.print(mLidKeyboardAccessibility);
8269 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
8270 pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
8271 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
8273 pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
8275 pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
8276 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
8278 pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
8279 pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
8280 pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
8281 pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
8282 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
8283 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
8284 pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
8285 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
8286 pw.print(prefix); pw.print("mOrientationSensorEnabled=");
8287 pw.println(mOrientationSensorEnabled);
8288 pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
8289 pw.print(","); pw.print(mOverscanScreenTop);
8290 pw.print(") "); pw.print(mOverscanScreenWidth);
8291 pw.print("x"); pw.println(mOverscanScreenHeight);
8292 if (mOverscanLeft != 0 || mOverscanTop != 0
8293 || mOverscanRight != 0 || mOverscanBottom != 0) {
8294 pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
8295 pw.print(" top="); pw.print(mOverscanTop);
8296 pw.print(" right="); pw.print(mOverscanRight);
8297 pw.print(" bottom="); pw.println(mOverscanBottom);
8299 pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
8300 pw.print(mRestrictedOverscanScreenLeft);
8301 pw.print(","); pw.print(mRestrictedOverscanScreenTop);
8302 pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
8303 pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
8304 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
8305 pw.print(","); pw.print(mUnrestrictedScreenTop);
8306 pw.print(") "); pw.print(mUnrestrictedScreenWidth);
8307 pw.print("x"); pw.println(mUnrestrictedScreenHeight);
8308 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
8309 pw.print(","); pw.print(mRestrictedScreenTop);
8310 pw.print(") "); pw.print(mRestrictedScreenWidth);
8311 pw.print("x"); pw.println(mRestrictedScreenHeight);
8312 pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
8313 pw.print(","); pw.print(mStableFullscreenTop);
8314 pw.print(")-("); pw.print(mStableFullscreenRight);
8315 pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
8316 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
8317 pw.print(","); pw.print(mStableTop);
8318 pw.print(")-("); pw.print(mStableRight);
8319 pw.print(","); pw.print(mStableBottom); pw.println(")");
8320 pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
8321 pw.print(","); pw.print(mSystemTop);
8322 pw.print(")-("); pw.print(mSystemRight);
8323 pw.print(","); pw.print(mSystemBottom); pw.println(")");
8324 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
8325 pw.print(","); pw.print(mCurTop);
8326 pw.print(")-("); pw.print(mCurRight);
8327 pw.print(","); pw.print(mCurBottom); pw.println(")");
8328 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
8329 pw.print(","); pw.print(mContentTop);
8330 pw.print(")-("); pw.print(mContentRight);
8331 pw.print(","); pw.print(mContentBottom); pw.println(")");
8332 pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft);
8333 pw.print(","); pw.print(mVoiceContentTop);
8334 pw.print(")-("); pw.print(mVoiceContentRight);
8335 pw.print(","); pw.print(mVoiceContentBottom); pw.println(")");
8336 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
8337 pw.print(","); pw.print(mDockTop);
8338 pw.print(")-("); pw.print(mDockRight);
8339 pw.print(","); pw.print(mDockBottom); pw.println(")");
8340 pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
8341 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
8342 pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen);
8343 pw.print(" mShowingDream="); pw.print(mShowingDream);
8344 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
8345 pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
8346 if (mLastInputMethodWindow != null) {
8347 pw.print(prefix); pw.print("mLastInputMethodWindow=");
8348 pw.println(mLastInputMethodWindow);
8350 if (mLastInputMethodTargetWindow != null) {
8351 pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
8352 pw.println(mLastInputMethodTargetWindow);
8354 if (mStatusBar != null) {
8355 pw.print(prefix); pw.print("mStatusBar=");
8356 pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
8357 pw.println(isStatusBarKeyguard());
8359 if (mNavigationBar != null) {
8360 pw.print(prefix); pw.print("mNavigationBar=");
8361 pw.println(mNavigationBar);
8363 if (mFocusedWindow != null) {
8364 pw.print(prefix); pw.print("mFocusedWindow=");
8365 pw.println(mFocusedWindow);
8367 if (mFocusedApp != null) {
8368 pw.print(prefix); pw.print("mFocusedApp=");
8369 pw.println(mFocusedApp);
8371 if (mWinDismissingKeyguard != null) {
8372 pw.print(prefix); pw.print("mWinDismissingKeyguard=");
8373 pw.println(mWinDismissingKeyguard);
8375 if (mTopFullscreenOpaqueWindowState != null) {
8376 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
8377 pw.println(mTopFullscreenOpaqueWindowState);
8379 if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
8380 pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
8381 pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
8383 if (mForcingShowNavBar) {
8384 pw.print(prefix); pw.print("mForcingShowNavBar=");
8385 pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
8386 pw.println(mForcingShowNavBarLayer);
8388 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
8389 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
8390 pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
8391 pw.print(" mForceStatusBarFromKeyguard=");
8392 pw.println(mForceStatusBarFromKeyguard);
8393 pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
8394 pw.print(" mWinDismissingKeyguard="); pw.print(mWinDismissingKeyguard);
8395 pw.print(" mHomePressed="); pw.println(mHomePressed);
8396 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
8397 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
8398 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
8399 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
8400 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
8401 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
8402 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
8403 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
8404 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
8405 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
8406 pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
8407 pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
8408 pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
8410 mGlobalKeyManager.dump(prefix, pw);
8411 mStatusBarController.dump(pw, prefix);
8412 mNavigationBarController.dump(pw, prefix);
8413 PolicyControl.dump(prefix, pw);
8415 if (mWakeGestureListener != null) {
8416 mWakeGestureListener.dump(pw, prefix);
8418 if (mOrientationListener != null) {
8419 mOrientationListener.dump(pw, prefix);
8421 if (mBurnInProtectionHelper != null) {
8422 mBurnInProtectionHelper.dump(prefix, pw);
8424 if (mKeyguardDelegate != null) {
8425 mKeyguardDelegate.dump(prefix, pw);