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.ActivityManagerNative;
46 import android.app.AppOpsManager;
47 import android.app.IUiModeManager;
48 import android.app.ProgressDialog;
49 import android.app.SearchManager;
50 import android.app.StatusBarManager;
51 import android.app.UiModeManager;
52 import android.content.ActivityNotFoundException;
53 import android.content.BroadcastReceiver;
54 import android.content.ComponentName;
55 import android.content.ContentResolver;
56 import android.content.Context;
57 import android.content.Intent;
58 import android.content.IntentFilter;
59 import android.content.ServiceConnection;
60 import android.content.pm.ActivityInfo;
61 import android.content.pm.ApplicationInfo;
62 import android.content.pm.PackageManager;
63 import android.content.pm.ResolveInfo;
64 import android.content.res.CompatibilityInfo;
65 import android.content.res.Configuration;
66 import android.content.res.Resources;
67 import android.content.res.TypedArray;
68 import android.database.ContentObserver;
69 import android.graphics.PixelFormat;
70 import android.graphics.Rect;
71 import android.hardware.hdmi.HdmiControlManager;
72 import android.hardware.hdmi.HdmiPlaybackClient;
73 import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback;
74 import android.hardware.input.InputManagerInternal;
75 import android.media.AudioAttributes;
76 import android.media.AudioManager;
77 import android.media.AudioSystem;
78 import android.media.IAudioService;
79 import android.media.Ringtone;
80 import android.media.RingtoneManager;
81 import android.media.session.MediaSessionLegacyHelper;
82 import android.os.Binder;
83 import android.os.Build;
84 import android.os.Bundle;
85 import android.os.Debug;
86 import android.os.FactoryTest;
87 import android.os.Handler;
88 import android.os.IBinder;
89 import android.os.IDeviceIdleController;
90 import android.os.Looper;
91 import android.os.Message;
92 import android.os.Messenger;
93 import android.os.PowerManager;
94 import android.os.PowerManagerInternal;
95 import android.os.Process;
96 import android.os.RemoteException;
97 import android.os.ServiceManager;
98 import android.os.SystemClock;
99 import android.os.SystemProperties;
100 import android.os.UEventObserver;
101 import android.os.UserHandle;
102 import android.os.Vibrator;
103 import android.provider.MediaStore;
104 import android.provider.Settings;
105 import android.service.dreams.DreamManagerInternal;
106 import android.service.dreams.DreamService;
107 import android.service.dreams.IDreamManager;
108 import android.speech.RecognizerIntent;
109 import android.telecom.TelecomManager;
110 import android.util.DisplayMetrics;
111 import android.util.EventLog;
112 import android.util.Log;
113 import android.util.MutableBoolean;
114 import android.util.Slog;
115 import android.util.SparseArray;
116 import android.util.LongSparseArray;
117 import android.view.Display;
118 import android.view.Gravity;
119 import android.view.HapticFeedbackConstants;
120 import android.view.IApplicationToken;
121 import android.view.IWindowManager;
122 import android.view.InputChannel;
123 import android.view.InputDevice;
124 import android.view.InputEvent;
125 import android.view.InputEventReceiver;
126 import android.view.KeyCharacterMap;
127 import android.view.KeyCharacterMap.FallbackAction;
128 import android.view.KeyEvent;
129 import android.view.MotionEvent;
130 import android.view.Surface;
131 import android.view.View;
132 import android.view.ViewConfiguration;
133 import android.view.WindowManager;
134 import android.view.WindowManagerGlobal;
135 import android.view.WindowManagerInternal;
136 import android.view.WindowManagerPolicy;
137 import android.view.accessibility.AccessibilityEvent;
138 import android.view.accessibility.AccessibilityManager;
139 import android.view.animation.Animation;
140 import android.view.animation.AnimationSet;
141 import android.view.animation.AnimationUtils;
142 import com.android.internal.R;
143 import com.android.internal.logging.MetricsLogger;
144 import com.android.internal.policy.PhoneWindow;
145 import com.android.internal.policy.IShortcutService;
146 import com.android.internal.statusbar.IStatusBarService;
147 import com.android.internal.util.ScreenShapeHelper;
148 import com.android.internal.widget.PointerLocationView;
149 import com.android.server.GestureLauncherService;
150 import com.android.server.LocalServices;
151 import com.android.server.policy.keyguard.KeyguardServiceDelegate;
152 import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener;
153 import com.android.server.statusbar.StatusBarManagerInternal;
156 import java.io.FileReader;
157 import java.io.IOException;
158 import java.io.PrintWriter;
159 import java.util.HashSet;
160 import java.util.List;
163 * WindowManagerPolicy implementation for the Android phone UI. This
164 * introduces a new method suffix, Lp, for an internal lock of the
165 * PhoneWindowManager. This is used to protect some internal state, and
166 * can be acquired with either the Lw and Li lock held, so has the restrictions
167 * of both of those when held.
169 public class PhoneWindowManager implements WindowManagerPolicy {
170 static final String TAG = "WindowManager";
171 static final boolean DEBUG = false;
172 static final boolean localLOGV = false;
173 static final boolean DEBUG_INPUT = false;
174 static final boolean DEBUG_KEYGUARD = false;
175 static final boolean DEBUG_LAYOUT = false;
176 static final boolean DEBUG_STARTING_WINDOW = false;
177 static final boolean DEBUG_WAKEUP = false;
178 static final boolean SHOW_STARTING_ANIMATIONS = true;
179 static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
181 // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
182 // No longer recommended for desk docks;
183 static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
185 static final int SHORT_PRESS_POWER_NOTHING = 0;
186 static final int SHORT_PRESS_POWER_GO_TO_SLEEP = 1;
187 static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2;
188 static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3;
189 static final int SHORT_PRESS_POWER_GO_HOME = 4;
191 static final int LONG_PRESS_POWER_NOTHING = 0;
192 static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
193 static final int LONG_PRESS_POWER_SHUT_OFF = 2;
194 static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
196 static final int LONG_PRESS_BACK_NOTHING = 0;
197 static final int LONG_PRESS_BACK_GO_TO_VOICE_ASSIST = 1;
199 static final int MULTI_PRESS_POWER_NOTHING = 0;
200 static final int MULTI_PRESS_POWER_THEATER_MODE = 1;
201 static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2;
203 // These need to match the documentation/constant in
204 // core/res/res/values/config.xml
205 static final int LONG_PRESS_HOME_NOTHING = 0;
206 static final int LONG_PRESS_HOME_RECENT_SYSTEM_UI = 1;
207 static final int LONG_PRESS_HOME_ASSIST = 2;
208 static final int LAST_LONG_PRESS_HOME_BEHAVIOR = LONG_PRESS_HOME_ASSIST;
210 static final int DOUBLE_TAP_HOME_NOTHING = 0;
211 static final int DOUBLE_TAP_HOME_RECENT_SYSTEM_UI = 1;
213 static final int SHORT_PRESS_WINDOW_NOTHING = 0;
214 static final int SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE = 1;
216 static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP = 0;
217 static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME = 1;
219 static final int PENDING_KEY_NULL = -1;
221 // Controls navigation bar opacity depending on which workspace stacks are currently
223 // Nav bar is always opaque when either the freeform stack or docked stack is visible.
224 static final int NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED = 0;
225 // Nav bar is always translucent when the freeform stack is visible, otherwise always opaque.
226 static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1;
228 static final int APPLICATION_MEDIA_SUBLAYER = -2;
229 static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
230 static final int APPLICATION_PANEL_SUBLAYER = 1;
231 static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
232 static final int APPLICATION_ABOVE_SUB_PANEL_SUBLAYER = 3;
234 static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
235 static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
236 static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
237 static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
238 static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";
241 * These are the system UI flags that, when changing, can cause the layout
242 * of the screen to change.
244 static final int SYSTEM_UI_CHANGING_LAYOUT =
245 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
246 | View.SYSTEM_UI_FLAG_FULLSCREEN
247 | View.STATUS_BAR_TRANSLUCENT
248 | View.NAVIGATION_BAR_TRANSLUCENT
249 | View.STATUS_BAR_TRANSPARENT
250 | View.NAVIGATION_BAR_TRANSPARENT;
252 private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
253 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
254 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
257 // The panic gesture may become active only after the keyguard is dismissed and the immersive
258 // app shows again. If that doesn't happen for 30s we drop the gesture.
259 private static final long PANIC_GESTURE_EXPIRATION = 30000;
261 private static final String SYSUI_PACKAGE = "com.android.systemui";
262 private static final String SYSUI_SCREENSHOT_SERVICE =
263 "com.android.systemui.screenshot.TakeScreenshotService";
264 private static final String SYSUI_SCREENSHOT_ERROR_RECEIVER =
265 "com.android.systemui.screenshot.ScreenshotServiceErrorReceiver";
267 private static final int NAV_BAR_BOTTOM = 0;
268 private static final int NAV_BAR_RIGHT = 1;
269 private static final int NAV_BAR_LEFT = 2;
274 private WindowState mKeyguardScrim;
275 private boolean mKeyguardHidden;
276 private boolean mKeyguardDrawnOnce;
278 /* Table of Application Launch keys. Maps from key codes to intent categories.
280 * These are special keys that are used to launch particular kinds of applications,
281 * such as a web browser. HID defines nearly a hundred of them in the Consumer (0x0C)
282 * usage page. We don't support quite that many yet...
284 static SparseArray<String> sApplicationLaunchKeyCategories;
286 sApplicationLaunchKeyCategories = new SparseArray<String>();
287 sApplicationLaunchKeyCategories.append(
288 KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER);
289 sApplicationLaunchKeyCategories.append(
290 KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL);
291 sApplicationLaunchKeyCategories.append(
292 KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS);
293 sApplicationLaunchKeyCategories.append(
294 KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR);
295 sApplicationLaunchKeyCategories.append(
296 KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC);
297 sApplicationLaunchKeyCategories.append(
298 KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
301 /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
302 static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;
305 * Lock protecting internal state. Must not call out into window
306 * manager with lock held. (This lock will be acquired in places
307 * where the window manager is calling in with its own lock held.)
309 private final Object mLock = new Object();
312 IWindowManager mWindowManager;
313 WindowManagerFuncs mWindowManagerFuncs;
314 WindowManagerInternal mWindowManagerInternal;
315 PowerManager mPowerManager;
316 ActivityManagerInternal mActivityManagerInternal;
317 InputManagerInternal mInputManagerInternal;
318 DreamManagerInternal mDreamManagerInternal;
319 PowerManagerInternal mPowerManagerInternal;
320 IStatusBarService mStatusBarService;
321 StatusBarManagerInternal mStatusBarManagerInternal;
322 boolean mPreloadedRecentApps;
323 final Object mServiceAquireLock = new Object();
324 Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
325 SearchManager mSearchManager;
326 AccessibilityManager mAccessibilityManager;
327 BurnInProtectionHelper mBurnInProtectionHelper;
328 AppOpsManager mAppOpsManager;
329 private boolean mHasFeatureWatch;
331 // Vibrator pattern for haptic feedback of a long press.
332 long[] mLongPressVibePattern;
334 // Vibrator pattern for haptic feedback of virtual key press.
335 long[] mVirtualKeyVibePattern;
337 // Vibrator pattern for a short vibration.
338 long[] mKeyboardTapVibePattern;
340 // Vibrator pattern for a short vibration when tapping on an hour/minute tick of a Clock.
341 long[] mClockTickVibePattern;
343 // Vibrator pattern for a short vibration when tapping on a day/month/year date of a Calendar.
344 long[] mCalendarDateVibePattern;
346 // Vibrator pattern for haptic feedback during boot when safe mode is disabled.
347 long[] mSafeModeDisabledVibePattern;
349 // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
350 long[] mSafeModeEnabledVibePattern;
352 // Vibrator pattern for haptic feedback of a context click.
353 long[] mContextClickVibePattern;
355 /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
356 boolean mEnableShiftMenuBugReports = false;
359 WindowState mStatusBar = null;
360 int mStatusBarHeight;
361 WindowState mNavigationBar = null;
362 boolean mHasNavigationBar = false;
363 boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?
364 int mNavigationBarPosition = NAV_BAR_BOTTOM;
365 int[] mNavigationBarHeightForRotationDefault = new int[4];
366 int[] mNavigationBarWidthForRotationDefault = new int[4];
367 int[] mNavigationBarHeightForRotationInCarMode = new int[4];
368 int[] mNavigationBarWidthForRotationInCarMode = new int[4];
370 private LongSparseArray<IShortcutService> mShortcutKeyServices = new LongSparseArray<>();
372 // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
373 // This is for car dock and this is updated from resource.
374 private boolean mEnableCarDockHomeCapture = true;
376 boolean mBootMessageNeedsHiding;
377 KeyguardServiceDelegate mKeyguardDelegate;
378 final Runnable mWindowManagerDrawCallback = new Runnable() {
381 if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!");
382 mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);
385 final DrawnListener mKeyguardDrawnCallback = new DrawnListener() {
387 public void onDrawn() {
388 if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn.");
389 mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
393 GlobalActions mGlobalActions;
395 WindowState mLastInputMethodWindow = null;
396 WindowState mLastInputMethodTargetWindow = null;
398 // FIXME This state is shared between the input reader and handler thread.
399 // Technically it's broken and buggy but it has been like this for many years
400 // and we have not yet seen any problems. Someday we'll rewrite this logic
401 // so that only one thread is involved in handling input policy. Unfortunately
402 // it's on a critical path for power management so we can't just post the work to the
403 // handler thread. We'll need to resolve this someday by teaching the input dispatcher
404 // to hold wakelocks during dispatch and eliminating the critical path.
405 volatile boolean mPowerKeyHandled;
406 volatile boolean mBackKeyHandled;
407 volatile boolean mBeganFromNonInteractive;
408 volatile int mPowerKeyPressCounter;
409 volatile boolean mEndCallKeyHandled;
410 volatile boolean mCameraGestureTriggeredDuringGoingToSleep;
411 volatile boolean mGoingToSleep;
412 volatile boolean mRecentsVisible;
413 volatile boolean mTvPictureInPictureVisible;
415 // Used to hold the last user key used to wake the device. This helps us prevent up events
416 // from being passed to the foregrounded app without a corresponding down event
417 volatile int mPendingWakeKey = PENDING_KEY_NULL;
419 int mRecentAppsHeldModifiers;
420 boolean mLanguageSwitchKeyPressed;
422 int mLidState = LID_ABSENT;
423 int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT;
424 boolean mHaveBuiltInKeyboard;
426 boolean mSystemReady;
427 boolean mSystemBooted;
428 private boolean mDeferBindKeyguard;
429 boolean mHdmiPlugged;
430 HdmiControl mHdmiControl;
431 IUiModeManager mUiModeManager;
433 int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
434 int mLidOpenRotation;
435 int mCarDockRotation;
436 int mDeskDockRotation;
437 int mUndockedHdmiRotation;
438 int mDemoHdmiRotation;
439 boolean mDemoHdmiRotationLock;
441 boolean mDemoRotationLock;
443 boolean mWakeGestureEnabledSetting;
444 MyWakeGestureListener mWakeGestureListener;
446 // Default display does not rotate, apps that require non-default orientation will have to
447 // have the orientation emulated.
448 private boolean mForceDefaultOrientation = false;
450 int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
451 int mUserRotation = Surface.ROTATION_0;
452 boolean mAccelerometerDefault;
454 boolean mSupportAutoRotation;
455 int mAllowAllRotations = -1;
456 boolean mCarDockEnablesAccelerometer;
457 boolean mDeskDockEnablesAccelerometer;
458 int mLidKeyboardAccessibility;
459 int mLidNavigationAccessibility;
460 boolean mLidControlsScreenLock;
461 boolean mLidControlsSleep;
462 int mShortPressOnPowerBehavior;
463 int mLongPressOnPowerBehavior;
464 int mDoublePressOnPowerBehavior;
465 int mTriplePressOnPowerBehavior;
466 int mLongPressOnBackBehavior;
467 int mShortPressOnSleepBehavior;
468 int mShortPressWindowBehavior;
470 boolean mScreenOnEarly;
471 boolean mScreenOnFully;
472 ScreenOnListener mScreenOnListener;
473 boolean mKeyguardDrawComplete;
474 boolean mWindowManagerDrawComplete;
475 boolean mOrientationSensorEnabled = false;
476 int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
477 boolean mHasSoftInput = false;
478 boolean mTranslucentDecorEnabled = true;
479 boolean mUseTvRouting;
481 int mPointerLocationMode = 0; // guarded by mLock
483 // The last window we were told about in focusChanged.
484 WindowState mFocusedWindow;
485 IApplicationToken mFocusedApp;
487 PointerLocationView mPointerLocationView;
489 // The current size of the screen; really; extends into the overscan area of
490 // the screen and doesn't account for any system elements like the status bar.
491 int mOverscanScreenLeft, mOverscanScreenTop;
492 int mOverscanScreenWidth, mOverscanScreenHeight;
493 // The current visible size of the screen; really; (ir)regardless of whether the status
494 // bar can be hidden but not extending into the overscan area.
495 int mUnrestrictedScreenLeft, mUnrestrictedScreenTop;
496 int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight;
497 // Like mOverscanScreen*, but allowed to move into the overscan region where appropriate.
498 int mRestrictedOverscanScreenLeft, mRestrictedOverscanScreenTop;
499 int mRestrictedOverscanScreenWidth, mRestrictedOverscanScreenHeight;
500 // The current size of the screen; these may be different than (0,0)-(dw,dh)
501 // if the status bar can't be hidden; in that case it effectively carves out
502 // that area of the display from all other windows.
503 int mRestrictedScreenLeft, mRestrictedScreenTop;
504 int mRestrictedScreenWidth, mRestrictedScreenHeight;
505 // During layout, the current screen borders accounting for any currently
506 // visible system UI elements.
507 int mSystemLeft, mSystemTop, mSystemRight, mSystemBottom;
508 // For applications requesting stable content insets, these are them.
509 int mStableLeft, mStableTop, mStableRight, mStableBottom;
510 // For applications requesting stable content insets but have also set the
511 // fullscreen window flag, these are the stable dimensions without the status bar.
512 int mStableFullscreenLeft, mStableFullscreenTop;
513 int mStableFullscreenRight, mStableFullscreenBottom;
514 // During layout, the current screen borders with all outer decoration
515 // (status bar, input method dock) accounted for.
516 int mCurLeft, mCurTop, mCurRight, mCurBottom;
517 // During layout, the frame in which content should be displayed
518 // to the user, accounting for all screen decoration except for any
519 // space they deem as available for other content. This is usually
520 // the same as mCur*, but may be larger if the screen decor has supplied
522 int mContentLeft, mContentTop, mContentRight, mContentBottom;
523 // During layout, the frame in which voice content should be displayed
524 // to the user, accounting for all screen decoration except for any
525 // space they deem as available for other content.
526 int mVoiceContentLeft, mVoiceContentTop, mVoiceContentRight, mVoiceContentBottom;
527 // During layout, the current screen borders along which input method
528 // windows are placed.
529 int mDockLeft, mDockTop, mDockRight, mDockBottom;
530 // During layout, the layer at which the doc window is placed.
532 // During layout, this is the layer of the status bar.
534 int mLastSystemUiFlags;
535 // Bits that we are in the process of clearing, so we want to prevent
536 // them from being set by applications until everything has been updated
537 // to have them clear.
538 int mResettingSystemUiFlags = 0;
539 // Bits that we are currently always keeping cleared.
540 int mForceClearedSystemUiFlags = 0;
541 int mLastFullscreenStackSysUiFlags;
542 int mLastDockedStackSysUiFlags;
543 final Rect mNonDockedStackBounds = new Rect();
544 final Rect mDockedStackBounds = new Rect();
545 final Rect mLastNonDockedStackBounds = new Rect();
546 final Rect mLastDockedStackBounds = new Rect();
548 // What we last reported to system UI about whether the compatibility
549 // menu needs to be displayed.
550 boolean mLastFocusNeedsMenu = false;
551 // If nonzero, a panic gesture was performed at that time in uptime millis and is still pending.
552 private long mPendingPanicGestureUptime;
554 InputConsumer mInputConsumer = null;
556 static final Rect mTmpParentFrame = new Rect();
557 static final Rect mTmpDisplayFrame = new Rect();
558 static final Rect mTmpOverscanFrame = new Rect();
559 static final Rect mTmpContentFrame = new Rect();
560 static final Rect mTmpVisibleFrame = new Rect();
561 static final Rect mTmpDecorFrame = new Rect();
562 static final Rect mTmpStableFrame = new Rect();
563 static final Rect mTmpNavigationFrame = new Rect();
564 static final Rect mTmpOutsetFrame = new Rect();
565 private static final Rect mTmpRect = new Rect();
567 WindowState mTopFullscreenOpaqueWindowState;
568 WindowState mTopFullscreenOpaqueOrDimmingWindowState;
569 WindowState mTopDockedOpaqueWindowState;
570 WindowState mTopDockedOpaqueOrDimmingWindowState;
571 HashSet<IApplicationToken> mAppsToBeHidden = new HashSet<IApplicationToken>();
572 HashSet<IApplicationToken> mAppsThatDismissKeyguard = new HashSet<IApplicationToken>();
573 boolean mTopIsFullscreen;
574 boolean mForceStatusBar;
575 boolean mForceStatusBarFromKeyguard;
576 private boolean mForceStatusBarTransparent;
577 int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
578 boolean mHideLockScreen;
579 boolean mForcingShowNavBar;
580 int mForcingShowNavBarLayer;
582 // States of keyguard dismiss.
583 private static final int DISMISS_KEYGUARD_NONE = 0; // Keyguard not being dismissed.
584 private static final int DISMISS_KEYGUARD_START = 1; // Keyguard needs to be dismissed.
585 private static final int DISMISS_KEYGUARD_CONTINUE = 2; // Keyguard has been dismissed.
586 int mDismissKeyguard = DISMISS_KEYGUARD_NONE;
588 /** The window that is currently dismissing the keyguard. Dismissing the keyguard must only
589 * be done once per window. */
590 private WindowState mWinDismissingKeyguard;
592 /** When window is currently dismissing the keyguard, dismissing the keyguard must handle
593 * the keygaurd secure state change instantly case, e.g. the use case of inserting a PIN
594 * lock SIM card. This variable is used to record the previous keyguard secure state for
595 * monitoring secure state change on window dismissing keyguard. */
596 private boolean mSecureDismissingKeyguard;
598 /** The window that is currently showing "over" the keyguard. If there is an app window
599 * belonging to another app on top of this the keyguard shows. If there is a fullscreen
600 * app window under this, still dismiss the keyguard but don't show the app underneath. Show
602 private WindowState mWinShowWhenLocked;
604 boolean mShowingLockscreen;
605 boolean mShowingDream;
606 boolean mDreamingLockscreen;
607 boolean mDreamingSleepTokenNeeded;
608 SleepToken mDreamingSleepToken;
609 SleepToken mScreenOffSleepToken;
610 boolean mKeyguardSecure;
611 boolean mKeyguardSecureIncludingHidden;
612 volatile boolean mKeyguardOccluded;
613 boolean mHomePressed;
614 boolean mHomeConsumed;
615 boolean mHomeDoubleTapPending;
617 Intent mCarDockIntent;
618 Intent mDeskDockIntent;
619 boolean mSearchKeyShortcutPending;
620 boolean mConsumeSearchKeyUp;
621 boolean mAssistKeyLongPressed;
622 boolean mPendingMetaAction;
623 boolean mPendingCapsLockToggle;
625 int mInitialMetaState;
626 boolean mForceShowSystemBars;
628 // support for activating the lock screen while the screen is on
629 boolean mAllowLockscreenWhenOn;
630 int mLockScreenTimeout;
631 boolean mLockScreenTimerActive;
633 // Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.)
634 int mEndcallBehavior;
636 // Behavior of POWER button while in-call and screen on.
637 // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
638 int mIncallPowerBehavior;
642 private int mDisplayRotation;
644 int mLandscapeRotation = 0; // default landscape rotation
645 int mSeascapeRotation = 0; // "other" landscape rotation, 180 degrees from mLandscapeRotation
646 int mPortraitRotation = 0; // default portrait rotation
647 int mUpsideDownRotation = 0; // "other" portrait rotation
649 int mOverscanLeft = 0;
650 int mOverscanTop = 0;
651 int mOverscanRight = 0;
652 int mOverscanBottom = 0;
654 // What we do when the user long presses on home
655 private int mLongPressOnHomeBehavior;
657 // What we do when the user double-taps on home
658 private int mDoubleTapOnHomeBehavior;
660 // Allowed theater mode wake actions
661 private boolean mAllowTheaterModeWakeFromKey;
662 private boolean mAllowTheaterModeWakeFromPowerKey;
663 private boolean mAllowTheaterModeWakeFromMotion;
664 private boolean mAllowTheaterModeWakeFromMotionWhenNotDreaming;
665 private boolean mAllowTheaterModeWakeFromCameraLens;
666 private boolean mAllowTheaterModeWakeFromLidSwitch;
667 private boolean mAllowTheaterModeWakeFromWakeGesture;
669 // Whether to support long press from power button in non-interactive mode
670 private boolean mSupportLongPressPowerWhenNonInteractive;
672 // Whether to go to sleep entering theater mode from power button
673 private boolean mGoToSleepOnButtonPressTheaterMode;
675 // Screenshot trigger states
676 // Time to volume and power must be pressed within this interval of each other.
677 private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
678 // Increase the chord delay when taking a screenshot from the keyguard
679 private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f;
680 private boolean mScreenshotChordEnabled;
681 private boolean mScreenshotChordVolumeDownKeyTriggered;
682 private long mScreenshotChordVolumeDownKeyTime;
683 private boolean mScreenshotChordVolumeDownKeyConsumed;
684 private boolean mScreenshotChordVolumeUpKeyTriggered;
685 private boolean mScreenshotChordPowerKeyTriggered;
686 private long mScreenshotChordPowerKeyTime;
688 /* The number of steps between min and max brightness */
689 private static final int BRIGHTNESS_STEPS = 10;
691 SettingsObserver mSettingsObserver;
692 ShortcutManager mShortcutManager;
693 PowerManager.WakeLock mBroadcastWakeLock;
694 PowerManager.WakeLock mPowerKeyWakeLock;
695 boolean mHavePendingMediaKeyRepeatWithWakeLock;
697 private int mCurrentUserId;
699 // Maps global key codes to the components that will handle them.
700 private GlobalKeyManager mGlobalKeyManager;
702 // Fallback actions by key code.
703 private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions =
704 new SparseArray<KeyCharacterMap.FallbackAction>();
706 private final LogDecelerateInterpolator mLogDecelerateInterpolator
707 = new LogDecelerateInterpolator(100, 0);
709 private final MutableBoolean mTmpBoolean = new MutableBoolean(false);
711 private static final int MSG_ENABLE_POINTER_LOCATION = 1;
712 private static final int MSG_DISABLE_POINTER_LOCATION = 2;
713 private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
714 private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
715 private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
716 private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6;
717 private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7;
718 private static final int MSG_DISPATCH_SHOW_RECENTS = 9;
719 private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10;
720 private static final int MSG_HIDE_BOOT_MESSAGE = 11;
721 private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12;
722 private static final int MSG_POWER_DELAYED_PRESS = 13;
723 private static final int MSG_POWER_LONG_PRESS = 14;
724 private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 15;
725 private static final int MSG_REQUEST_TRANSIENT_BARS = 16;
726 private static final int MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU = 17;
727 private static final int MSG_BACK_LONG_PRESS = 18;
728 private static final int MSG_DISPOSE_INPUT_CONSUMER = 19;
730 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
731 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
733 private class PolicyHandler extends Handler {
735 public void handleMessage(Message msg) {
737 case MSG_ENABLE_POINTER_LOCATION:
738 enablePointerLocation();
740 case MSG_DISABLE_POINTER_LOCATION:
741 disablePointerLocation();
743 case MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK:
744 dispatchMediaKeyWithWakeLock((KeyEvent)msg.obj);
746 case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK:
747 dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj);
749 case MSG_DISPATCH_SHOW_RECENTS:
750 showRecentApps(false, msg.arg1 != 0);
752 case MSG_DISPATCH_SHOW_GLOBAL_ACTIONS:
753 showGlobalActionsInternal();
755 case MSG_KEYGUARD_DRAWN_COMPLETE:
756 if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete");
757 finishKeyguardDrawn();
759 case MSG_KEYGUARD_DRAWN_TIMEOUT:
760 Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete");
761 finishKeyguardDrawn();
763 case MSG_WINDOW_MANAGER_DRAWN_COMPLETE:
764 if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete");
765 finishWindowsDrawn();
767 case MSG_HIDE_BOOT_MESSAGE:
768 handleHideBootMessage();
770 case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK:
771 launchVoiceAssistWithWakeLock(msg.arg1 != 0);
773 case MSG_POWER_DELAYED_PRESS:
774 powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2);
775 finishPowerKeyPress();
777 case MSG_POWER_LONG_PRESS:
780 case MSG_UPDATE_DREAMING_SLEEP_TOKEN:
781 updateDreamingSleepToken(msg.arg1 != 0);
783 case MSG_REQUEST_TRANSIENT_BARS:
784 WindowState targetBar = (msg.arg1 == MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS) ?
785 mStatusBar : mNavigationBar;
786 if (targetBar != null) {
787 requestTransientBars(targetBar);
790 case MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU:
791 showTvPictureInPictureMenuInternal();
793 case MSG_BACK_LONG_PRESS:
796 case MSG_DISPOSE_INPUT_CONSUMER:
797 disposeInputConsumer((InputConsumer) msg.obj);
803 private UEventObserver mHDMIObserver = new UEventObserver() {
805 public void onUEvent(UEventObserver.UEvent event) {
806 setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
810 class SettingsObserver extends ContentObserver {
811 SettingsObserver(Handler handler) {
816 // Observe all users' changes
817 ContentResolver resolver = mContext.getContentResolver();
818 resolver.registerContentObserver(Settings.System.getUriFor(
819 Settings.System.END_BUTTON_BEHAVIOR), false, this,
820 UserHandle.USER_ALL);
821 resolver.registerContentObserver(Settings.Secure.getUriFor(
822 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this,
823 UserHandle.USER_ALL);
824 resolver.registerContentObserver(Settings.Secure.getUriFor(
825 Settings.Secure.WAKE_GESTURE_ENABLED), false, this,
826 UserHandle.USER_ALL);
827 resolver.registerContentObserver(Settings.System.getUriFor(
828 Settings.System.ACCELEROMETER_ROTATION), false, this,
829 UserHandle.USER_ALL);
830 resolver.registerContentObserver(Settings.System.getUriFor(
831 Settings.System.USER_ROTATION), false, this,
832 UserHandle.USER_ALL);
833 resolver.registerContentObserver(Settings.System.getUriFor(
834 Settings.System.SCREEN_OFF_TIMEOUT), false, this,
835 UserHandle.USER_ALL);
836 resolver.registerContentObserver(Settings.System.getUriFor(
837 Settings.System.POINTER_LOCATION), false, this,
838 UserHandle.USER_ALL);
839 resolver.registerContentObserver(Settings.Secure.getUriFor(
840 Settings.Secure.DEFAULT_INPUT_METHOD), false, this,
841 UserHandle.USER_ALL);
842 resolver.registerContentObserver(Settings.Secure.getUriFor(
843 Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this,
844 UserHandle.USER_ALL);
845 resolver.registerContentObserver(Settings.Global.getUriFor(
846 Settings.Global.POLICY_CONTROL), false, this,
847 UserHandle.USER_ALL);
851 @Override public void onChange(boolean selfChange) {
853 updateRotation(false);
857 class MyWakeGestureListener extends WakeGestureListener {
858 MyWakeGestureListener(Context context, Handler handler) {
859 super(context, handler);
863 public void onWakeUp() {
864 synchronized (mLock) {
865 if (shouldEnableWakeGestureLp()) {
866 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
867 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture,
868 "android.policy:GESTURE");
874 class MyOrientationListener extends WindowOrientationListener {
875 private final Runnable mUpdateRotationRunnable = new Runnable() {
878 // send interaction hint to improve redraw performance
879 mPowerManagerInternal.powerHint(PowerManagerInternal.POWER_HINT_INTERACTION, 0);
880 updateRotation(false);
884 MyOrientationListener(Context context, Handler handler) {
885 super(context, handler);
889 public void onProposedRotationChanged(int rotation) {
890 if (localLOGV) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
891 mHandler.post(mUpdateRotationRunnable);
894 MyOrientationListener mOrientationListener;
896 private final StatusBarController mStatusBarController = new StatusBarController();
898 private final BarController mNavigationBarController = new BarController("NavigationBar",
899 View.NAVIGATION_BAR_TRANSIENT,
900 View.NAVIGATION_BAR_UNHIDE,
901 View.NAVIGATION_BAR_TRANSLUCENT,
902 StatusBarManager.WINDOW_NAVIGATION_BAR,
903 WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
904 View.NAVIGATION_BAR_TRANSPARENT);
906 private ImmersiveModeConfirmation mImmersiveModeConfirmation;
908 private SystemGesturesPointerEventListener mSystemGestures;
910 IStatusBarService getStatusBarService() {
911 synchronized (mServiceAquireLock) {
912 if (mStatusBarService == null) {
913 mStatusBarService = IStatusBarService.Stub.asInterface(
914 ServiceManager.getService("statusbar"));
916 return mStatusBarService;
920 StatusBarManagerInternal getStatusBarManagerInternal() {
921 synchronized (mServiceAquireLock) {
922 if (mStatusBarManagerInternal == null) {
923 mStatusBarManagerInternal =
924 LocalServices.getService(StatusBarManagerInternal.class);
926 return mStatusBarManagerInternal;
931 * We always let the sensor be switched on by default except when
932 * the user has explicitly disabled sensor based rotation or when the
933 * screen is switched off.
935 boolean needSensorRunningLp() {
936 if (mSupportAutoRotation) {
937 if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
938 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
939 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
940 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
941 // If the application has explicitly requested to follow the
942 // orientation, then we need to turn the sensor on.
946 if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
947 (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
948 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
949 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
950 // enable accelerometer if we are docked in a dock that enables accelerometer
951 // orientation management,
954 if (mUserRotationMode == USER_ROTATION_LOCKED) {
955 // If the setting for using the sensor by default is enabled, then
956 // we will always leave it on. Note that the user could go to
957 // a window that forces an orientation that does not use the
958 // sensor and in theory we could turn it off... however, when next
959 // turning it on we won't have a good value for the current
960 // orientation for a little bit, which can cause orientation
961 // changes to lag, so we'd like to keep it always on. (It will
962 // still be turned off when the screen is off.)
965 return mSupportAutoRotation;
969 * Various use cases for invoking this function
970 * screen turning off, should always disable listeners if already enabled
971 * screen turned on and current app has sensor based orientation, enable listeners
972 * if not already enabled
973 * screen turned on and current app does not have sensor orientation, disable listeners if
975 * screen turning on and current app has sensor based orientation, enable listeners if needed
976 * screen turning on and current app has nosensor based orientation, do nothing
978 void updateOrientationListenerLp() {
979 if (!mOrientationListener.canDetectOrientation()) {
980 // If sensor is turned off or nonexistent for some reason
983 // Could have been invoked due to screen turning on or off or
984 // change of the currently visible window's orientation.
985 if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly
986 + ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation
987 + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled
988 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
989 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
990 boolean disable = true;
991 // Note: We postpone the rotating of the screen until the keyguard as well as the
992 // window manager have reported a draw complete.
993 if (mScreenOnEarly && mAwake &&
994 mKeyguardDrawComplete && mWindowManagerDrawComplete) {
995 if (needSensorRunningLp()) {
997 //enable listener if not already enabled
998 if (!mOrientationSensorEnabled) {
999 mOrientationListener.enable();
1000 if(localLOGV) Slog.v(TAG, "Enabling listeners");
1001 mOrientationSensorEnabled = true;
1005 //check if sensors need to be disabled
1006 if (disable && mOrientationSensorEnabled) {
1007 mOrientationListener.disable();
1008 if(localLOGV) Slog.v(TAG, "Disabling listeners");
1009 mOrientationSensorEnabled = false;
1013 private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
1014 // Hold a wake lock until the power key is released.
1015 if (!mPowerKeyWakeLock.isHeld()) {
1016 mPowerKeyWakeLock.acquire();
1019 // Cancel multi-press detection timeout.
1020 if (mPowerKeyPressCounter != 0) {
1021 mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);
1024 // Detect user pressing the power button in panic when an application has
1025 // taken over the whole screen.
1026 boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
1027 SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags),
1028 isNavBarEmpty(mLastSystemUiFlags));
1030 mHandler.post(mHiddenNavPanic);
1033 // Latch power key state to detect screenshot chord.
1034 if (interactive && !mScreenshotChordPowerKeyTriggered
1035 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
1036 mScreenshotChordPowerKeyTriggered = true;
1037 mScreenshotChordPowerKeyTime = event.getDownTime();
1038 interceptScreenshotChord();
1041 // Stop ringing or end call if configured to do so when power is pressed.
1042 TelecomManager telecomManager = getTelecommService();
1043 boolean hungUp = false;
1044 if (telecomManager != null) {
1045 if (telecomManager.isRinging()) {
1046 // Pressing Power while there's a ringing incoming
1047 // call should silence the ringer.
1048 telecomManager.silenceRinger();
1049 } else if ((mIncallPowerBehavior
1050 & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
1051 && telecomManager.isInCall() && interactive) {
1052 // Otherwise, if "Power button ends call" is enabled,
1053 // the Power button will hang up any current active call.
1054 hungUp = telecomManager.endCall();
1058 GestureLauncherService gestureService = LocalServices.getService(
1059 GestureLauncherService.class);
1060 boolean gesturedServiceIntercepted = false;
1061 if (gestureService != null) {
1062 gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive,
1064 if (mTmpBoolean.value && mGoingToSleep) {
1065 mCameraGestureTriggeredDuringGoingToSleep = true;
1069 // If the power key has still not yet been handled, then detect short
1070 // press, long press, or multi press and decide what to do.
1071 mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
1072 || mScreenshotChordVolumeUpKeyTriggered || gesturedServiceIntercepted;
1073 if (!mPowerKeyHandled) {
1075 // When interactive, we're already awake.
1076 // Wait for a long press or for the button to be released to decide what to do.
1077 if (hasLongPressOnPowerBehavior()) {
1078 Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
1079 msg.setAsynchronous(true);
1080 mHandler.sendMessageDelayed(msg,
1081 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1084 wakeUpFromPowerKey(event.getDownTime());
1086 if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
1087 Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
1088 msg.setAsynchronous(true);
1089 mHandler.sendMessageDelayed(msg,
1090 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1091 mBeganFromNonInteractive = true;
1093 final int maxCount = getMaxMultiPressPowerCount();
1095 if (maxCount <= 1) {
1096 mPowerKeyHandled = true;
1098 mBeganFromNonInteractive = true;
1105 private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
1106 final boolean handled = canceled || mPowerKeyHandled;
1107 mScreenshotChordPowerKeyTriggered = false;
1108 cancelPendingScreenshotChordAction();
1109 cancelPendingPowerKeyAction();
1112 // Figure out how to handle the key now that it has been released.
1113 mPowerKeyPressCounter += 1;
1115 final int maxCount = getMaxMultiPressPowerCount();
1116 final long eventTime = event.getDownTime();
1117 if (mPowerKeyPressCounter < maxCount) {
1118 // This could be a multi-press. Wait a little bit longer to confirm.
1119 // Continue holding the wake lock.
1120 Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
1121 interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
1122 msg.setAsynchronous(true);
1123 mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
1127 // No other actions. Handle it immediately.
1128 powerPress(eventTime, interactive, mPowerKeyPressCounter);
1131 // Done. Reset our state.
1132 finishPowerKeyPress();
1135 private void finishPowerKeyPress() {
1136 mBeganFromNonInteractive = false;
1137 mPowerKeyPressCounter = 0;
1138 if (mPowerKeyWakeLock.isHeld()) {
1139 mPowerKeyWakeLock.release();
1143 private void cancelPendingPowerKeyAction() {
1144 if (!mPowerKeyHandled) {
1145 mPowerKeyHandled = true;
1146 mHandler.removeMessages(MSG_POWER_LONG_PRESS);
1150 private void cancelPendingBackKeyAction() {
1151 if (!mBackKeyHandled) {
1152 mBackKeyHandled = true;
1153 mHandler.removeMessages(MSG_BACK_LONG_PRESS);
1157 private void powerPress(long eventTime, boolean interactive, int count) {
1158 if (mScreenOnEarly && !mScreenOnFully) {
1159 Slog.i(TAG, "Suppressed redundant power key press while "
1160 + "already in the process of turning the screen on.");
1165 powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
1166 } else if (count == 3) {
1167 powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
1168 } else if (interactive && !mBeganFromNonInteractive) {
1169 switch (mShortPressOnPowerBehavior) {
1170 case SHORT_PRESS_POWER_NOTHING:
1172 case SHORT_PRESS_POWER_GO_TO_SLEEP:
1173 mPowerManager.goToSleep(eventTime,
1174 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
1176 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
1177 mPowerManager.goToSleep(eventTime,
1178 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
1179 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
1181 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
1182 mPowerManager.goToSleep(eventTime,
1183 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
1184 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
1185 launchHomeFromHotKey();
1187 case SHORT_PRESS_POWER_GO_HOME:
1188 launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
1194 private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) {
1196 case MULTI_PRESS_POWER_NOTHING:
1198 case MULTI_PRESS_POWER_THEATER_MODE:
1199 if (!isUserSetupComplete()) {
1200 Slog.i(TAG, "Ignoring toggling theater mode - device not setup.");
1204 if (isTheaterModeEnabled()) {
1205 Slog.i(TAG, "Toggling theater mode off.");
1206 Settings.Global.putInt(mContext.getContentResolver(),
1207 Settings.Global.THEATER_MODE_ON, 0);
1209 wakeUpFromPowerKey(eventTime);
1212 Slog.i(TAG, "Toggling theater mode on.");
1213 Settings.Global.putInt(mContext.getContentResolver(),
1214 Settings.Global.THEATER_MODE_ON, 1);
1216 if (mGoToSleepOnButtonPressTheaterMode && interactive) {
1217 mPowerManager.goToSleep(eventTime,
1218 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
1222 case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
1223 Slog.i(TAG, "Starting brightness boost.");
1225 wakeUpFromPowerKey(eventTime);
1227 mPowerManager.boostScreenBrightness(eventTime);
1232 private int getMaxMultiPressPowerCount() {
1233 if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
1236 if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
1242 private void powerLongPress() {
1243 final int behavior = getResolvedLongPressOnPowerBehavior();
1245 case LONG_PRESS_POWER_NOTHING:
1247 case LONG_PRESS_POWER_GLOBAL_ACTIONS:
1248 mPowerKeyHandled = true;
1249 if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
1250 performAuditoryFeedbackForAccessibilityIfNeed();
1252 showGlobalActionsInternal();
1254 case LONG_PRESS_POWER_SHUT_OFF:
1255 case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
1256 mPowerKeyHandled = true;
1257 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1258 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
1259 mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
1264 private void backLongPress() {
1265 mBackKeyHandled = true;
1267 switch (mLongPressOnBackBehavior) {
1268 case LONG_PRESS_BACK_NOTHING:
1270 case LONG_PRESS_BACK_GO_TO_VOICE_ASSIST:
1271 Intent intent = new Intent(Intent.ACTION_VOICE_ASSIST);
1272 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
1277 private void disposeInputConsumer(InputConsumer inputConsumer) {
1278 if (inputConsumer != null) {
1279 inputConsumer.dismiss();
1283 private void sleepPress(long eventTime) {
1284 if (mShortPressOnSleepBehavior == SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME) {
1285 launchHomeFromHotKey(false /* awakenDreams */, true /*respectKeyguard*/);
1289 private void sleepRelease(long eventTime) {
1290 switch (mShortPressOnSleepBehavior) {
1291 case SHORT_PRESS_SLEEP_GO_TO_SLEEP:
1292 case SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME:
1293 Slog.i(TAG, "sleepRelease() calling goToSleep(GO_TO_SLEEP_REASON_SLEEP_BUTTON)");
1294 mPowerManager.goToSleep(eventTime,
1295 PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON, 0);
1300 private int getResolvedLongPressOnPowerBehavior() {
1301 if (FactoryTest.isLongPressOnPowerOffEnabled()) {
1302 return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
1304 return mLongPressOnPowerBehavior;
1307 private boolean hasLongPressOnPowerBehavior() {
1308 return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;
1311 private boolean hasLongPressOnBackBehavior() {
1312 return mLongPressOnBackBehavior != LONG_PRESS_BACK_NOTHING;
1315 private void interceptScreenshotChord() {
1316 if (mScreenshotChordEnabled
1317 && mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered
1318 && !mScreenshotChordVolumeUpKeyTriggered) {
1319 final long now = SystemClock.uptimeMillis();
1320 if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
1321 && now <= mScreenshotChordPowerKeyTime
1322 + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
1323 mScreenshotChordVolumeDownKeyConsumed = true;
1324 cancelPendingPowerKeyAction();
1325 mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
1326 mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
1331 private long getScreenshotChordLongPressDelay() {
1332 if (mKeyguardDelegate.isShowing()) {
1333 // Double the time it takes to take a screenshot from the keyguard
1334 return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER *
1335 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1337 return ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout();
1340 private void cancelPendingScreenshotChordAction() {
1341 mHandler.removeCallbacks(mScreenshotRunnable);
1344 private final Runnable mEndCallLongPress = new Runnable() {
1347 mEndCallKeyHandled = true;
1348 if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
1349 performAuditoryFeedbackForAccessibilityIfNeed();
1351 showGlobalActionsInternal();
1355 private class ScreenshotRunnable implements Runnable {
1356 private int mScreenshotType = TAKE_SCREENSHOT_FULLSCREEN;
1358 public void setScreenshotType(int screenshotType) {
1359 mScreenshotType = screenshotType;
1364 takeScreenshot(mScreenshotType);
1368 private final ScreenshotRunnable mScreenshotRunnable = new ScreenshotRunnable();
1371 public void showGlobalActions() {
1372 mHandler.removeMessages(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
1373 mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
1376 void showGlobalActionsInternal() {
1377 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
1378 if (mGlobalActions == null) {
1379 mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
1381 final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();
1382 mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
1383 if (keyguardShowing) {
1384 // since it took two seconds of long press to bring this up,
1385 // poke the wake lock so they have some time to see the dialog.
1386 mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
1390 boolean isDeviceProvisioned() {
1391 return Settings.Global.getInt(
1392 mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
1395 boolean isUserSetupComplete() {
1396 return Settings.Secure.getIntForUser(mContext.getContentResolver(),
1397 Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
1400 private void handleShortPressOnHome() {
1401 // Turn on the connected TV and switch HDMI input if we're a HDMI playback device.
1402 getHdmiControl().turnOnTv();
1404 // If there's a dream running then use home to escape the dream
1405 // but don't actually go home.
1406 if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) {
1407 mDreamManagerInternal.stopDream(false /*immediate*/);
1412 launchHomeFromHotKey();
1416 * Creates an accessor to HDMI control service that performs the operation of
1417 * turning on TV (optional) and switching input to us. If HDMI control service
1418 * is not available or we're not a HDMI playback device, the operation is no-op.
1420 private HdmiControl getHdmiControl() {
1421 if (null == mHdmiControl) {
1422 HdmiControlManager manager = (HdmiControlManager) mContext.getSystemService(
1423 Context.HDMI_CONTROL_SERVICE);
1424 HdmiPlaybackClient client = null;
1425 if (manager != null) {
1426 client = manager.getPlaybackClient();
1428 mHdmiControl = new HdmiControl(client);
1430 return mHdmiControl;
1433 private static class HdmiControl {
1434 private final HdmiPlaybackClient mClient;
1436 private HdmiControl(HdmiPlaybackClient client) {
1440 public void turnOnTv() {
1441 if (mClient == null) {
1444 mClient.oneTouchPlay(new OneTouchPlayCallback() {
1446 public void onComplete(int result) {
1447 if (result != HdmiControlManager.RESULT_SUCCESS) {
1448 Log.w(TAG, "One touch play failed: " + result);
1455 private void handleLongPressOnHome(int deviceId) {
1456 if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_NOTHING) {
1459 mHomeConsumed = true;
1460 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1462 switch (mLongPressOnHomeBehavior) {
1463 case LONG_PRESS_HOME_RECENT_SYSTEM_UI:
1466 case LONG_PRESS_HOME_ASSIST:
1467 launchAssistAction(null, deviceId);
1470 Log.w(TAG, "Undefined home long press behavior: " + mLongPressOnHomeBehavior);
1475 private void handleDoubleTapOnHome() {
1476 if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
1477 mHomeConsumed = true;
1482 private void showTvPictureInPictureMenu(KeyEvent event) {
1483 if (DEBUG_INPUT) Log.d(TAG, "showTvPictureInPictureMenu event=" + event);
1484 mHandler.removeMessages(MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU);
1485 Message msg = mHandler.obtainMessage(MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU);
1486 msg.setAsynchronous(true);
1490 private void showTvPictureInPictureMenuInternal() {
1491 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
1492 if (statusbar != null) {
1493 statusbar.showTvPictureInPictureMenu();
1497 private final Runnable mHomeDoubleTapTimeoutRunnable = new Runnable() {
1500 if (mHomeDoubleTapPending) {
1501 mHomeDoubleTapPending = false;
1502 handleShortPressOnHome();
1507 private boolean isRoundWindow() {
1508 return mContext.getResources().getConfiguration().isScreenRound();
1511 /** {@inheritDoc} */
1513 public void init(Context context, IWindowManager windowManager,
1514 WindowManagerFuncs windowManagerFuncs) {
1516 mWindowManager = windowManager;
1517 mWindowManagerFuncs = windowManagerFuncs;
1518 mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
1519 mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
1520 mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
1521 mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
1522 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
1523 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
1524 mHasFeatureWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH);
1526 // Init display burn-in protection
1527 boolean burnInProtectionEnabled = context.getResources().getBoolean(
1528 com.android.internal.R.bool.config_enableBurnInProtection);
1529 // Allow a system property to override this. Used by developer settings.
1530 boolean burnInProtectionDevMode =
1531 SystemProperties.getBoolean("persist.debug.force_burn_in", false);
1532 if (burnInProtectionEnabled || burnInProtectionDevMode) {
1533 final int minHorizontal;
1534 final int maxHorizontal;
1535 final int minVertical;
1536 final int maxVertical;
1537 final int maxRadius;
1538 if (burnInProtectionDevMode) {
1543 maxRadius = (isRoundWindow()) ? 6 : -1;
1545 Resources resources = context.getResources();
1546 minHorizontal = resources.getInteger(
1547 com.android.internal.R.integer.config_burnInProtectionMinHorizontalOffset);
1548 maxHorizontal = resources.getInteger(
1549 com.android.internal.R.integer.config_burnInProtectionMaxHorizontalOffset);
1550 minVertical = resources.getInteger(
1551 com.android.internal.R.integer.config_burnInProtectionMinVerticalOffset);
1552 maxVertical = resources.getInteger(
1553 com.android.internal.R.integer.config_burnInProtectionMaxVerticalOffset);
1554 maxRadius = resources.getInteger(
1555 com.android.internal.R.integer.config_burnInProtectionMaxRadius);
1557 mBurnInProtectionHelper = new BurnInProtectionHelper(
1558 context, minHorizontal, maxHorizontal, minVertical, maxVertical, maxRadius);
1561 mHandler = new PolicyHandler();
1562 mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
1563 mOrientationListener = new MyOrientationListener(mContext, mHandler);
1565 mOrientationListener.setCurrentRotation(windowManager.getRotation());
1566 } catch (RemoteException ex) { }
1567 mSettingsObserver = new SettingsObserver(mHandler);
1568 mSettingsObserver.observe();
1569 mShortcutManager = new ShortcutManager(context);
1570 mUiMode = context.getResources().getInteger(
1571 com.android.internal.R.integer.config_defaultUiModeType);
1572 mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
1573 mHomeIntent.addCategory(Intent.CATEGORY_HOME);
1574 mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1575 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1576 mEnableCarDockHomeCapture = context.getResources().getBoolean(
1577 com.android.internal.R.bool.config_enableCarDockHomeLaunch);
1578 mCarDockIntent = new Intent(Intent.ACTION_MAIN, null);
1579 mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
1580 mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1581 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1582 mDeskDockIntent = new Intent(Intent.ACTION_MAIN, null);
1583 mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
1584 mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1585 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1587 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1588 mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1589 "PhoneWindowManager.mBroadcastWakeLock");
1590 mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1591 "PhoneWindowManager.mPowerKeyWakeLock");
1592 mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
1593 mSupportAutoRotation = mContext.getResources().getBoolean(
1594 com.android.internal.R.bool.config_supportAutoRotation);
1595 mLidOpenRotation = readRotation(
1596 com.android.internal.R.integer.config_lidOpenRotation);
1597 mCarDockRotation = readRotation(
1598 com.android.internal.R.integer.config_carDockRotation);
1599 mDeskDockRotation = readRotation(
1600 com.android.internal.R.integer.config_deskDockRotation);
1601 mUndockedHdmiRotation = readRotation(
1602 com.android.internal.R.integer.config_undockedHdmiRotation);
1603 mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
1604 com.android.internal.R.bool.config_carDockEnablesAccelerometer);
1605 mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
1606 com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
1607 mLidKeyboardAccessibility = mContext.getResources().getInteger(
1608 com.android.internal.R.integer.config_lidKeyboardAccessibility);
1609 mLidNavigationAccessibility = mContext.getResources().getInteger(
1610 com.android.internal.R.integer.config_lidNavigationAccessibility);
1611 mLidControlsScreenLock = mContext.getResources().getBoolean(
1612 com.android.internal.R.bool.config_lidControlsScreenLock);
1613 mLidControlsSleep = mContext.getResources().getBoolean(
1614 com.android.internal.R.bool.config_lidControlsSleep);
1615 mTranslucentDecorEnabled = mContext.getResources().getBoolean(
1616 com.android.internal.R.bool.config_enableTranslucentDecor);
1618 mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
1619 com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
1620 mAllowTheaterModeWakeFromPowerKey = mAllowTheaterModeWakeFromKey
1621 || mContext.getResources().getBoolean(
1622 com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey);
1623 mAllowTheaterModeWakeFromMotion = mContext.getResources().getBoolean(
1624 com.android.internal.R.bool.config_allowTheaterModeWakeFromMotion);
1625 mAllowTheaterModeWakeFromMotionWhenNotDreaming = mContext.getResources().getBoolean(
1626 com.android.internal.R.bool.config_allowTheaterModeWakeFromMotionWhenNotDreaming);
1627 mAllowTheaterModeWakeFromCameraLens = mContext.getResources().getBoolean(
1628 com.android.internal.R.bool.config_allowTheaterModeWakeFromCameraLens);
1629 mAllowTheaterModeWakeFromLidSwitch = mContext.getResources().getBoolean(
1630 com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch);
1631 mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean(
1632 com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture);
1634 mGoToSleepOnButtonPressTheaterMode = mContext.getResources().getBoolean(
1635 com.android.internal.R.bool.config_goToSleepOnButtonPressTheaterMode);
1637 mSupportLongPressPowerWhenNonInteractive = mContext.getResources().getBoolean(
1638 com.android.internal.R.bool.config_supportLongPressPowerWhenNonInteractive);
1640 mLongPressOnBackBehavior = mContext.getResources().getInteger(
1641 com.android.internal.R.integer.config_longPressOnBackBehavior);
1643 mShortPressOnPowerBehavior = mContext.getResources().getInteger(
1644 com.android.internal.R.integer.config_shortPressOnPowerBehavior);
1645 mLongPressOnPowerBehavior = mContext.getResources().getInteger(
1646 com.android.internal.R.integer.config_longPressOnPowerBehavior);
1647 mDoublePressOnPowerBehavior = mContext.getResources().getInteger(
1648 com.android.internal.R.integer.config_doublePressOnPowerBehavior);
1649 mTriplePressOnPowerBehavior = mContext.getResources().getInteger(
1650 com.android.internal.R.integer.config_triplePressOnPowerBehavior);
1651 mShortPressOnSleepBehavior = mContext.getResources().getInteger(
1652 com.android.internal.R.integer.config_shortPressOnSleepBehavior);
1654 mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION;
1656 readConfigurationDependentBehaviors();
1658 mAccessibilityManager = (AccessibilityManager) context.getSystemService(
1659 Context.ACCESSIBILITY_SERVICE);
1661 // register for dock events
1662 IntentFilter filter = new IntentFilter();
1663 filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
1664 filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
1665 filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
1666 filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
1667 filter.addAction(Intent.ACTION_DOCK_EVENT);
1668 Intent intent = context.registerReceiver(mDockReceiver, filter);
1669 if (intent != null) {
1670 // Retrieve current sticky dock event broadcast.
1671 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
1672 Intent.EXTRA_DOCK_STATE_UNDOCKED);
1675 // register for dream-related broadcasts
1676 filter = new IntentFilter();
1677 filter.addAction(Intent.ACTION_DREAMING_STARTED);
1678 filter.addAction(Intent.ACTION_DREAMING_STOPPED);
1679 context.registerReceiver(mDreamReceiver, filter);
1681 // register for multiuser-relevant broadcasts
1682 filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
1683 context.registerReceiver(mMultiuserReceiver, filter);
1685 // monitor for system gestures
1686 mSystemGestures = new SystemGesturesPointerEventListener(context,
1687 new SystemGesturesPointerEventListener.Callbacks() {
1689 public void onSwipeFromTop() {
1690 if (mStatusBar != null) {
1691 requestTransientBars(mStatusBar);
1695 public void onSwipeFromBottom() {
1696 if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_BOTTOM) {
1697 requestTransientBars(mNavigationBar);
1701 public void onSwipeFromRight() {
1702 if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_RIGHT) {
1703 requestTransientBars(mNavigationBar);
1707 public void onSwipeFromLeft() {
1708 if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_LEFT) {
1709 requestTransientBars(mNavigationBar);
1713 public void onFling(int duration) {
1714 if (mPowerManagerInternal != null) {
1715 mPowerManagerInternal.powerHint(
1716 PowerManagerInternal.POWER_HINT_INTERACTION, duration);
1720 public void onDebug() {
1724 public void onDown() {
1725 mOrientationListener.onTouchStart();
1728 public void onUpOrCancel() {
1729 mOrientationListener.onTouchEnd();
1732 public void onMouseHoverAtTop() {
1733 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
1734 Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
1735 msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
1736 mHandler.sendMessageDelayed(msg, 500);
1739 public void onMouseHoverAtBottom() {
1740 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
1741 Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
1742 msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
1743 mHandler.sendMessageDelayed(msg, 500);
1746 public void onMouseLeaveFromEdge() {
1747 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
1750 mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext);
1751 mWindowManagerFuncs.registerPointerEventListener(mSystemGestures);
1753 mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
1754 mLongPressVibePattern = getLongIntArray(mContext.getResources(),
1755 com.android.internal.R.array.config_longPressVibePattern);
1756 mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(),
1757 com.android.internal.R.array.config_virtualKeyVibePattern);
1758 mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(),
1759 com.android.internal.R.array.config_keyboardTapVibePattern);
1760 mClockTickVibePattern = getLongIntArray(mContext.getResources(),
1761 com.android.internal.R.array.config_clockTickVibePattern);
1762 mCalendarDateVibePattern = getLongIntArray(mContext.getResources(),
1763 com.android.internal.R.array.config_calendarDateVibePattern);
1764 mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
1765 com.android.internal.R.array.config_safeModeDisabledVibePattern);
1766 mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
1767 com.android.internal.R.array.config_safeModeEnabledVibePattern);
1768 mContextClickVibePattern = getLongIntArray(mContext.getResources(),
1769 com.android.internal.R.array.config_contextClickVibePattern);
1771 mScreenshotChordEnabled = mContext.getResources().getBoolean(
1772 com.android.internal.R.bool.config_enableScreenshotChord);
1774 mGlobalKeyManager = new GlobalKeyManager(mContext);
1776 // Controls rotation and the like.
1777 initializeHdmiState();
1779 // Match current screen state.
1780 if (!mPowerManager.isInteractive()) {
1781 startedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
1782 finishedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
1785 mWindowManagerInternal.registerAppTransitionListener(
1786 mStatusBarController.getAppTransitionListener());
1790 * Read values from config.xml that may be overridden depending on
1791 * the configuration of the device.
1792 * eg. Disable long press on home goes to recents on sw600dp.
1794 private void readConfigurationDependentBehaviors() {
1795 final Resources res = mContext.getResources();
1797 mLongPressOnHomeBehavior = res.getInteger(
1798 com.android.internal.R.integer.config_longPressOnHomeBehavior);
1799 if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||
1800 mLongPressOnHomeBehavior > LAST_LONG_PRESS_HOME_BEHAVIOR) {
1801 mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
1804 mDoubleTapOnHomeBehavior = res.getInteger(
1805 com.android.internal.R.integer.config_doubleTapOnHomeBehavior);
1806 if (mDoubleTapOnHomeBehavior < DOUBLE_TAP_HOME_NOTHING ||
1807 mDoubleTapOnHomeBehavior > DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
1808 mDoubleTapOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
1811 mShortPressWindowBehavior = SHORT_PRESS_WINDOW_NOTHING;
1812 if (mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
1813 mShortPressWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE;
1816 mNavBarOpacityMode = res.getInteger(
1817 com.android.internal.R.integer.config_navBarOpacityMode);
1821 public void setInitialDisplaySize(Display display, int width, int height, int density) {
1822 // This method might be called before the policy has been fully initialized
1823 // or for other displays we don't care about.
1824 if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) {
1829 final Resources res = mContext.getResources();
1830 int shortSize, longSize;
1831 if (width > height) {
1834 mLandscapeRotation = Surface.ROTATION_0;
1835 mSeascapeRotation = Surface.ROTATION_180;
1836 if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
1837 mPortraitRotation = Surface.ROTATION_90;
1838 mUpsideDownRotation = Surface.ROTATION_270;
1840 mPortraitRotation = Surface.ROTATION_270;
1841 mUpsideDownRotation = Surface.ROTATION_90;
1846 mPortraitRotation = Surface.ROTATION_0;
1847 mUpsideDownRotation = Surface.ROTATION_180;
1848 if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
1849 mLandscapeRotation = Surface.ROTATION_270;
1850 mSeascapeRotation = Surface.ROTATION_90;
1852 mLandscapeRotation = Surface.ROTATION_90;
1853 mSeascapeRotation = Surface.ROTATION_270;
1857 // SystemUI (status bar) layout policy
1858 int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
1859 int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
1861 // Allow the navigation bar to move on non-square small devices (phones).
1862 mNavigationBarCanMove = width != height && shortSizeDp < 600;
1864 mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
1866 // Allow a system property to override this. Used by the emulator.
1867 // See also hasNavigationBar().
1868 String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
1869 if ("1".equals(navBarOverride)) {
1870 mHasNavigationBar = false;
1871 } else if ("0".equals(navBarOverride)) {
1872 mHasNavigationBar = true;
1875 // For demo purposes, allow the rotation of the HDMI display to be controlled.
1876 // By default, HDMI locks rotation to landscape.
1877 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
1878 mDemoHdmiRotation = mPortraitRotation;
1880 mDemoHdmiRotation = mLandscapeRotation;
1882 mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
1884 // For demo purposes, allow the rotation of the remote display to be controlled.
1885 // By default, remote display locks rotation to landscape.
1886 if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
1887 mDemoRotation = mPortraitRotation;
1889 mDemoRotation = mLandscapeRotation;
1891 mDemoRotationLock = SystemProperties.getBoolean(
1892 "persist.demo.rotationlock", false);
1894 // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
1895 // http://developer.android.com/guide/practices/screens_support.html#range
1896 mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 &&
1897 res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
1898 // For debug purposes the next line turns this feature off with:
1899 // $ adb shell setprop config.override_forced_orient true
1900 // $ adb shell wm size reset
1901 !"true".equals(SystemProperties.get("config.override_forced_orient"));
1905 * @return whether the navigation bar can be hidden, e.g. the device has a
1906 * navigation bar and touch exploration is not enabled
1908 private boolean canHideNavigationBar() {
1909 return mHasNavigationBar;
1913 public boolean isDefaultOrientationForced() {
1914 return mForceDefaultOrientation;
1918 public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) {
1919 if (display.getDisplayId() == Display.DEFAULT_DISPLAY) {
1920 mOverscanLeft = left;
1922 mOverscanRight = right;
1923 mOverscanBottom = bottom;
1927 public void updateSettings() {
1928 ContentResolver resolver = mContext.getContentResolver();
1929 boolean updateRotation = false;
1930 synchronized (mLock) {
1931 mEndcallBehavior = Settings.System.getIntForUser(resolver,
1932 Settings.System.END_BUTTON_BEHAVIOR,
1933 Settings.System.END_BUTTON_BEHAVIOR_DEFAULT,
1934 UserHandle.USER_CURRENT);
1935 mIncallPowerBehavior = Settings.Secure.getIntForUser(resolver,
1936 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
1937 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT,
1938 UserHandle.USER_CURRENT);
1940 // Configure wake gesture.
1941 boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver,
1942 Settings.Secure.WAKE_GESTURE_ENABLED, 0,
1943 UserHandle.USER_CURRENT) != 0;
1944 if (mWakeGestureEnabledSetting != wakeGestureEnabledSetting) {
1945 mWakeGestureEnabledSetting = wakeGestureEnabledSetting;
1946 updateWakeGestureListenerLp();
1949 // Configure rotation lock.
1950 int userRotation = Settings.System.getIntForUser(resolver,
1951 Settings.System.USER_ROTATION, Surface.ROTATION_0,
1952 UserHandle.USER_CURRENT);
1953 if (mUserRotation != userRotation) {
1954 mUserRotation = userRotation;
1955 updateRotation = true;
1957 int userRotationMode = Settings.System.getIntForUser(resolver,
1958 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
1959 WindowManagerPolicy.USER_ROTATION_FREE :
1960 WindowManagerPolicy.USER_ROTATION_LOCKED;
1961 if (mUserRotationMode != userRotationMode) {
1962 mUserRotationMode = userRotationMode;
1963 updateRotation = true;
1964 updateOrientationListenerLp();
1968 int pointerLocation = Settings.System.getIntForUser(resolver,
1969 Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT);
1970 if (mPointerLocationMode != pointerLocation) {
1971 mPointerLocationMode = pointerLocation;
1972 mHandler.sendEmptyMessage(pointerLocation != 0 ?
1973 MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
1976 // use screen off timeout setting as the timeout for the lockscreen
1977 mLockScreenTimeout = Settings.System.getIntForUser(resolver,
1978 Settings.System.SCREEN_OFF_TIMEOUT, 0, UserHandle.USER_CURRENT);
1979 String imId = Settings.Secure.getStringForUser(resolver,
1980 Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.USER_CURRENT);
1981 boolean hasSoftInput = imId != null && imId.length() > 0;
1982 if (mHasSoftInput != hasSoftInput) {
1983 mHasSoftInput = hasSoftInput;
1984 updateRotation = true;
1986 if (mImmersiveModeConfirmation != null) {
1987 mImmersiveModeConfirmation.loadSetting(mCurrentUserId);
1990 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
1991 PolicyControl.reloadFromSetting(mContext);
1993 if (updateRotation) {
1994 updateRotation(true);
1998 private void updateWakeGestureListenerLp() {
1999 if (shouldEnableWakeGestureLp()) {
2000 mWakeGestureListener.requestWakeUpTrigger();
2002 mWakeGestureListener.cancelWakeUpTrigger();
2006 private boolean shouldEnableWakeGestureLp() {
2007 return mWakeGestureEnabledSetting && !mAwake
2008 && (!mLidControlsSleep || mLidState != LID_CLOSED)
2009 && mWakeGestureListener.isSupported();
2012 private void enablePointerLocation() {
2013 if (mPointerLocationView == null) {
2014 mPointerLocationView = new PointerLocationView(mContext);
2015 mPointerLocationView.setPrintCoords(false);
2016 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
2017 WindowManager.LayoutParams.MATCH_PARENT,
2018 WindowManager.LayoutParams.MATCH_PARENT);
2019 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
2020 lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
2021 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
2022 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2023 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
2024 if (ActivityManager.isHighEndGfx()) {
2025 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
2027 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
2029 lp.format = PixelFormat.TRANSLUCENT;
2030 lp.setTitle("PointerLocation");
2031 WindowManager wm = (WindowManager)
2032 mContext.getSystemService(Context.WINDOW_SERVICE);
2033 lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
2034 wm.addView(mPointerLocationView, lp);
2035 mWindowManagerFuncs.registerPointerEventListener(mPointerLocationView);
2039 private void disablePointerLocation() {
2040 if (mPointerLocationView != null) {
2041 mWindowManagerFuncs.unregisterPointerEventListener(mPointerLocationView);
2042 WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
2043 wm.removeView(mPointerLocationView);
2044 mPointerLocationView = null;
2048 private int readRotation(int resID) {
2050 int rotation = mContext.getResources().getInteger(resID);
2053 return Surface.ROTATION_0;
2055 return Surface.ROTATION_90;
2057 return Surface.ROTATION_180;
2059 return Surface.ROTATION_270;
2061 } catch (Resources.NotFoundException e) {
2067 /** {@inheritDoc} */
2069 public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) {
2070 int type = attrs.type;
2072 outAppOp[0] = AppOpsManager.OP_NONE;
2074 if (!((type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW)
2075 || (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW)
2076 || (type >= FIRST_SYSTEM_WINDOW && type <= LAST_SYSTEM_WINDOW))) {
2077 return WindowManagerGlobal.ADD_INVALID_TYPE;
2080 if (type < FIRST_SYSTEM_WINDOW || type > LAST_SYSTEM_WINDOW) {
2081 // Window manager will make sure these are okay.
2082 return WindowManagerGlobal.ADD_OKAY;
2084 String permission = null;
2087 // XXX right now the app process has complete control over
2088 // this... should introduce a token to let the system
2089 // monitor/control what they are doing.
2090 outAppOp[0] = AppOpsManager.OP_TOAST_WINDOW;
2093 case TYPE_INPUT_METHOD:
2094 case TYPE_WALLPAPER:
2095 case TYPE_PRIVATE_PRESENTATION:
2096 case TYPE_VOICE_INTERACTION:
2097 case TYPE_ACCESSIBILITY_OVERLAY:
2098 case TYPE_QS_DIALOG:
2099 // The window manager will check these.
2102 case TYPE_PRIORITY_PHONE:
2103 case TYPE_SYSTEM_ALERT:
2104 case TYPE_SYSTEM_ERROR:
2105 case TYPE_SYSTEM_OVERLAY:
2106 permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
2107 outAppOp[0] = AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
2110 permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
2112 if (permission != null) {
2113 if (android.Manifest.permission.SYSTEM_ALERT_WINDOW.equals(permission)) {
2114 final int callingUid = Binder.getCallingUid();
2115 // system processes will be automatically allowed privilege to draw
2116 if (callingUid == Process.SYSTEM_UID) {
2117 return WindowManagerGlobal.ADD_OKAY;
2120 // check if user has enabled this operation. SecurityException will be thrown if
2121 // this app has not been allowed by the user
2122 final int mode = mAppOpsManager.checkOpNoThrow(outAppOp[0], callingUid,
2125 case AppOpsManager.MODE_ALLOWED:
2126 case AppOpsManager.MODE_IGNORED:
2127 // although we return ADD_OKAY for MODE_IGNORED, the added window will
2128 // actually be hidden in WindowManagerService
2129 return WindowManagerGlobal.ADD_OKAY;
2130 case AppOpsManager.MODE_ERRORED:
2132 ApplicationInfo appInfo = mContext.getPackageManager()
2133 .getApplicationInfo(attrs.packageName,
2134 UserHandle.getUserId(callingUid));
2135 // Don't crash legacy apps
2136 if (appInfo.targetSdkVersion < Build.VERSION_CODES.M) {
2137 return WindowManagerGlobal.ADD_OKAY;
2139 } catch (PackageManager.NameNotFoundException e) {
2142 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
2144 // in the default mode, we will make a decision here based on
2145 // checkCallingPermission()
2146 if (mContext.checkCallingPermission(permission) !=
2147 PackageManager.PERMISSION_GRANTED) {
2148 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
2150 return WindowManagerGlobal.ADD_OKAY;
2155 if (mContext.checkCallingOrSelfPermission(permission)
2156 != PackageManager.PERMISSION_GRANTED) {
2157 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
2160 return WindowManagerGlobal.ADD_OKAY;
2164 public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) {
2166 // If this switch statement is modified, modify the comment in the declarations of
2167 // the type in {@link WindowManager.LayoutParams} as well.
2168 switch (attrs.type) {
2170 // These are the windows that by default are shown only to the user that created
2171 // them. If this needs to be overridden, set
2172 // {@link WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS} in
2173 // {@link WindowManager.LayoutParams}. Note that permission
2174 // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well.
2175 if ((attrs.privateFlags & PRIVATE_FLAG_SHOW_FOR_ALL_USERS) == 0) {
2180 // These are the windows that by default are shown to all users. However, to
2181 // protect against spoofing, check permissions below.
2182 case TYPE_APPLICATION_STARTING:
2183 case TYPE_BOOT_PROGRESS:
2184 case TYPE_DISPLAY_OVERLAY:
2185 case TYPE_INPUT_CONSUMER:
2186 case TYPE_KEYGUARD_SCRIM:
2187 case TYPE_KEYGUARD_DIALOG:
2188 case TYPE_MAGNIFICATION_OVERLAY:
2189 case TYPE_NAVIGATION_BAR:
2190 case TYPE_NAVIGATION_BAR_PANEL:
2193 case TYPE_PRIORITY_PHONE:
2194 case TYPE_SEARCH_BAR:
2195 case TYPE_STATUS_BAR:
2196 case TYPE_STATUS_BAR_PANEL:
2197 case TYPE_STATUS_BAR_SUB_PANEL:
2198 case TYPE_SYSTEM_DIALOG:
2199 case TYPE_VOLUME_OVERLAY:
2200 case TYPE_PRIVATE_PRESENTATION:
2201 case TYPE_DOCK_DIVIDER:
2205 // Check if third party app has set window to system window type.
2206 return mContext.checkCallingOrSelfPermission(
2207 android.Manifest.permission.INTERNAL_SYSTEM_WINDOW)
2208 != PackageManager.PERMISSION_GRANTED;
2212 public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
2213 switch (attrs.type) {
2214 case TYPE_SYSTEM_OVERLAY:
2215 case TYPE_SECURE_SYSTEM_OVERLAY:
2216 // These types of windows can't receive input events.
2217 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2218 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
2219 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
2221 case TYPE_STATUS_BAR:
2223 // If the Keyguard is in a hidden state (occluded by another window), we force to
2224 // remove the wallpaper and keyguard flag so that any change in-flight after setting
2225 // the keyguard as occluded wouldn't set these flags again.
2226 // See {@link #processKeyguardSetHiddenResultLw}.
2227 if (mKeyguardHidden) {
2228 attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
2229 attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2232 case TYPE_SCREENSHOT:
2233 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
2237 if (attrs.type != TYPE_STATUS_BAR) {
2238 // The status bar is the only window allowed to exhibit keyguard behavior.
2239 attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2242 if (ActivityManager.isHighEndGfx()) {
2243 if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
2244 attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
2246 final boolean forceWindowDrawsStatusBarBackground =
2247 (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND)
2249 if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
2250 || forceWindowDrawsStatusBarBackground
2251 && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) {
2252 attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2257 void readLidState() {
2258 mLidState = mWindowManagerFuncs.getLidState();
2261 private void readCameraLensCoverState() {
2262 mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState();
2265 private boolean isHidden(int accessibilityMode) {
2266 switch (accessibilityMode) {
2268 return mLidState == LID_CLOSED;
2270 return mLidState == LID_OPEN;
2276 /** {@inheritDoc} */
2278 public void adjustConfigurationLw(Configuration config, int keyboardPresence,
2279 int navigationPresence) {
2280 mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0;
2282 readConfigurationDependentBehaviors();
2285 if (config.keyboard == Configuration.KEYBOARD_NOKEYS
2286 || (keyboardPresence == PRESENCE_INTERNAL
2287 && isHidden(mLidKeyboardAccessibility))) {
2288 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
2289 if (!mHasSoftInput) {
2290 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
2294 if (config.navigation == Configuration.NAVIGATION_NONAV
2295 || (navigationPresence == PRESENCE_INTERNAL
2296 && isHidden(mLidNavigationAccessibility))) {
2297 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
2302 public void onConfigurationChanged() {
2303 final Resources res = mContext.getResources();
2306 res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
2308 // Height of the navigation bar when presented horizontally at bottom
2309 mNavigationBarHeightForRotationDefault[mPortraitRotation] =
2310 mNavigationBarHeightForRotationDefault[mUpsideDownRotation] =
2311 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
2312 mNavigationBarHeightForRotationDefault[mLandscapeRotation] =
2313 mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize(
2314 com.android.internal.R.dimen.navigation_bar_height_landscape);
2316 // Width of the navigation bar when presented vertically along one side
2317 mNavigationBarWidthForRotationDefault[mPortraitRotation] =
2318 mNavigationBarWidthForRotationDefault[mUpsideDownRotation] =
2319 mNavigationBarWidthForRotationDefault[mLandscapeRotation] =
2320 mNavigationBarWidthForRotationDefault[mSeascapeRotation] =
2321 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
2323 // Height of the navigation bar when presented horizontally at bottom
2324 mNavigationBarHeightForRotationInCarMode[mPortraitRotation] =
2325 mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] =
2326 res.getDimensionPixelSize(
2327 com.android.internal.R.dimen.navigation_bar_height_car_mode);
2328 mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] =
2329 mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize(
2330 com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode);
2332 // Width of the navigation bar when presented vertically along one side
2333 mNavigationBarWidthForRotationInCarMode[mPortraitRotation] =
2334 mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] =
2335 mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] =
2336 mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] =
2337 res.getDimensionPixelSize(
2338 com.android.internal.R.dimen.navigation_bar_width_car_mode);
2341 /** {@inheritDoc} */
2343 public int windowTypeToLayerLw(int type) {
2344 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
2348 case TYPE_PRIVATE_PRESENTATION:
2350 case TYPE_WALLPAPER:
2351 // wallpaper is at the bottom, though the window manager may move it.
2353 case TYPE_DOCK_DIVIDER:
2355 case TYPE_QS_DIALOG:
2359 case TYPE_SEARCH_BAR:
2360 case TYPE_VOICE_INTERACTION_STARTING:
2362 case TYPE_VOICE_INTERACTION:
2363 // voice interaction layer is almost immediately above apps.
2365 case TYPE_INPUT_CONSUMER:
2367 case TYPE_SYSTEM_DIALOG:
2370 // toasts and the plugged-in battery thing
2372 case TYPE_PRIORITY_PHONE:
2373 // SIM errors and unlock. Not sure if this really should be in a high layer.
2376 // used for Dreams (screensavers with TYPE_DREAM windows)
2378 case TYPE_SYSTEM_ALERT:
2379 // like the ANR / app crashed dialogs
2381 case TYPE_INPUT_METHOD:
2382 // on-screen keyboards and other such input method user interfaces go here.
2384 case TYPE_INPUT_METHOD_DIALOG:
2385 // on-screen keyboards and other such input method user interfaces go here.
2387 case TYPE_KEYGUARD_SCRIM:
2388 // the safety window that shows behind keyguard while keyguard is starting
2390 case TYPE_STATUS_BAR_SUB_PANEL:
2392 case TYPE_STATUS_BAR:
2394 case TYPE_STATUS_BAR_PANEL:
2396 case TYPE_KEYGUARD_DIALOG:
2398 case TYPE_VOLUME_OVERLAY:
2399 // the on-screen volume indicator and controller shown when the user
2400 // changes the device volume
2402 case TYPE_SYSTEM_OVERLAY:
2403 // the on-screen volume indicator and controller shown when the user
2404 // changes the device volume
2406 case TYPE_NAVIGATION_BAR:
2407 // the navigation bar, if available, shows atop most things
2409 case TYPE_NAVIGATION_BAR_PANEL:
2410 // some panels (e.g. search) need to show on top of the navigation bar
2412 case TYPE_SCREENSHOT:
2413 // screenshot selection layer shouldn't go above system error, but it should cover
2414 // navigation bars at the very least.
2416 case TYPE_SYSTEM_ERROR:
2417 // system-level error dialogs
2419 case TYPE_MAGNIFICATION_OVERLAY:
2420 // used to highlight the magnified portion of a display
2422 case TYPE_DISPLAY_OVERLAY:
2423 // used to simulate secondary display devices
2426 // the drag layer: input for drag-and-drop is associated with this window,
2427 // which sits above all other focusable windows
2429 case TYPE_ACCESSIBILITY_OVERLAY:
2430 // overlay put by accessibility services to intercept user interaction
2432 case TYPE_SECURE_SYSTEM_OVERLAY:
2434 case TYPE_BOOT_PROGRESS:
2437 // the (mouse) pointer layer
2440 Log.e(TAG, "Unknown window type: " + type);
2444 /** {@inheritDoc} */
2446 public int subWindowTypeToLayerLw(int type) {
2448 case TYPE_APPLICATION_PANEL:
2449 case TYPE_APPLICATION_ATTACHED_DIALOG:
2450 return APPLICATION_PANEL_SUBLAYER;
2451 case TYPE_APPLICATION_MEDIA:
2452 return APPLICATION_MEDIA_SUBLAYER;
2453 case TYPE_APPLICATION_MEDIA_OVERLAY:
2454 return APPLICATION_MEDIA_OVERLAY_SUBLAYER;
2455 case TYPE_APPLICATION_SUB_PANEL:
2456 return APPLICATION_SUB_PANEL_SUBLAYER;
2457 case TYPE_APPLICATION_ABOVE_SUB_PANEL:
2458 return APPLICATION_ABOVE_SUB_PANEL_SUBLAYER;
2460 Log.e(TAG, "Unknown sub-window type: " + type);
2465 public int getMaxWallpaperLayer() {
2466 return windowTypeToLayerLw(TYPE_STATUS_BAR);
2469 private int getNavigationBarWidth(int rotation, int uiMode) {
2470 if ((uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2471 return mNavigationBarWidthForRotationInCarMode[rotation];
2473 return mNavigationBarWidthForRotationDefault[rotation];
2478 public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation,
2480 if (mHasNavigationBar) {
2481 // For a basic navigation bar, when we are in landscape mode we place
2482 // the navigation bar to the side.
2483 if (mNavigationBarCanMove && fullWidth > fullHeight) {
2484 return fullWidth - getNavigationBarWidth(rotation, uiMode);
2490 private int getNavigationBarHeight(int rotation, int uiMode) {
2491 if ((uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2492 return mNavigationBarHeightForRotationInCarMode[rotation];
2494 return mNavigationBarHeightForRotationDefault[rotation];
2499 public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation,
2501 if (mHasNavigationBar) {
2502 // For a basic navigation bar, when we are in portrait mode we place
2503 // the navigation bar to the bottom.
2504 if (!mNavigationBarCanMove || fullWidth < fullHeight) {
2505 return fullHeight - getNavigationBarHeight(rotation, uiMode);
2512 public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode) {
2513 return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode);
2517 public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode) {
2518 // There is a separate status bar at the top of the display. We don't count that as part
2519 // of the fixed decor, since it can hide; however, for purposes of configurations,
2520 // we do want to exclude it since applications can't generally use that part
2522 return getNonDecorDisplayHeight(
2523 fullWidth, fullHeight, rotation, uiMode) - mStatusBarHeight;
2527 public boolean isForceHiding(WindowManager.LayoutParams attrs) {
2528 return (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
2529 (isKeyguardHostWindow(attrs) &&
2530 (mKeyguardDelegate != null && mKeyguardDelegate.isShowing())) ||
2531 (attrs.type == TYPE_KEYGUARD_SCRIM);
2535 public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) {
2536 return attrs.type == TYPE_STATUS_BAR;
2540 public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
2541 switch (attrs.type) {
2542 case TYPE_STATUS_BAR:
2543 case TYPE_NAVIGATION_BAR:
2544 case TYPE_WALLPAPER:
2546 case TYPE_KEYGUARD_SCRIM:
2549 // Hide only windows below the keyguard host window.
2550 return windowTypeToLayerLw(win.getBaseType())
2551 < windowTypeToLayerLw(TYPE_STATUS_BAR);
2556 public WindowState getWinShowWhenLockedLw() {
2557 return mWinShowWhenLocked;
2560 /** {@inheritDoc} */
2562 public View addStartingWindow(IBinder appToken, String packageName, int theme,
2563 CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
2564 int icon, int logo, int windowFlags, Configuration overrideConfig) {
2565 if (!SHOW_STARTING_ANIMATIONS) {
2568 if (packageName == null) {
2572 WindowManager wm = null;
2576 Context context = mContext;
2577 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow " + packageName
2578 + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
2579 + Integer.toHexString(theme));
2580 if (theme != context.getThemeResId() || labelRes != 0) {
2582 context = context.createPackageContext(packageName, 0);
2583 context.setTheme(theme);
2584 } catch (PackageManager.NameNotFoundException e) {
2589 if (overrideConfig != null && overrideConfig != EMPTY) {
2590 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: creating context based"
2591 + " on overrideConfig" + overrideConfig + " for starting window");
2592 final Context overrideContext = context.createConfigurationContext(overrideConfig);
2593 overrideContext.setTheme(theme);
2594 final TypedArray typedArray = overrideContext.obtainStyledAttributes(
2595 com.android.internal.R.styleable.Window);
2596 final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
2597 if (resId != 0 && overrideContext.getDrawable(resId) != null) {
2598 // We want to use the windowBackground for the override context if it is
2599 // available, otherwise we use the default one to make sure a themed starting
2600 // window is displayed for the app.
2601 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: apply overrideConfig"
2602 + overrideConfig + " to starting window resId=" + resId);
2603 context = overrideContext;
2607 final PhoneWindow win = new PhoneWindow(context);
2608 win.setIsStartingWindow(true);
2610 CharSequence label = context.getResources().getText(labelRes, null);
2611 // Only change the accessibility title if the label is localized
2612 if (label != null) {
2613 win.setTitle(label, true);
2615 win.setTitle(nonLocalizedLabel, false);
2619 WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
2621 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
2622 // Assumes it's safe to show starting windows of launched apps while
2623 // the keyguard is being hidden. This is okay because starting windows never show
2624 // secret information.
2625 if (mKeyguardHidden) {
2626 windowFlags |= FLAG_SHOW_WHEN_LOCKED;
2630 // Force the window flags: this is a fake window, so it is not really
2631 // touchable or focusable by the user. We also add in the ALT_FOCUSABLE_IM
2632 // flag because we do know that the next window will take input
2633 // focus, so we want to get the IME window up on top of us right away.
2636 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2637 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2638 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
2640 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2641 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2642 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
2644 win.setDefaultIcon(icon);
2645 win.setDefaultLogo(logo);
2647 win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
2648 WindowManager.LayoutParams.MATCH_PARENT);
2650 final WindowManager.LayoutParams params = win.getAttributes();
2651 params.token = appToken;
2652 params.packageName = packageName;
2653 params.windowAnimations = win.getWindowStyle().getResourceId(
2654 com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
2655 params.privateFlags |=
2656 WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
2657 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
2659 if (!compatInfo.supportsScreen()) {
2660 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
2663 params.setTitle("Starting " + packageName);
2665 wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
2666 view = win.getDecorView();
2668 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Adding starting window for "
2669 + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null));
2671 wm.addView(view, params);
2673 // Only return the view if it was successfully added to the
2674 // window manager... which we can tell by it having a parent.
2675 return view.getParent() != null ? view : null;
2676 } catch (WindowManager.BadTokenException e) {
2678 Log.w(TAG, appToken + " already running, starting window not displayed. " +
2680 } catch (RuntimeException e) {
2681 // don't crash if something else bad happens, for example a
2682 // failure loading resources because we are loading from an app
2683 // on external storage that has been unmounted.
2684 Log.w(TAG, appToken + " failed creating starting window", e);
2686 if (view != null && view.getParent() == null) {
2687 Log.w(TAG, "view not successfully added to wm, removing view");
2688 wm.removeViewImmediate(view);
2695 /** {@inheritDoc} */
2697 public void removeStartingWindow(IBinder appToken, View window) {
2698 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Removing starting window for " + appToken + ": "
2699 + window + " Callers=" + Debug.getCallers(4));
2701 if (window != null) {
2702 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
2703 wm.removeView(window);
2708 * Preflight adding a window to the system.
2710 * Currently enforces that three window types are singletons:
2712 * <li>STATUS_BAR_TYPE</li>
2713 * <li>KEYGUARD_TYPE</li>
2716 * @param win The window to be added
2717 * @param attrs Information about the window to be added
2719 * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons,
2720 * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
2723 public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
2724 switch (attrs.type) {
2725 case TYPE_STATUS_BAR:
2726 mContext.enforceCallingOrSelfPermission(
2727 android.Manifest.permission.STATUS_BAR_SERVICE,
2728 "PhoneWindowManager");
2729 if (mStatusBar != null) {
2730 if (mStatusBar.isAlive()) {
2731 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2735 mStatusBarController.setWindow(win);
2737 case TYPE_NAVIGATION_BAR:
2738 mContext.enforceCallingOrSelfPermission(
2739 android.Manifest.permission.STATUS_BAR_SERVICE,
2740 "PhoneWindowManager");
2741 if (mNavigationBar != null) {
2742 if (mNavigationBar.isAlive()) {
2743 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2746 mNavigationBar = win;
2747 mNavigationBarController.setWindow(win);
2748 if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
2750 case TYPE_NAVIGATION_BAR_PANEL:
2751 case TYPE_STATUS_BAR_PANEL:
2752 case TYPE_STATUS_BAR_SUB_PANEL:
2753 case TYPE_VOICE_INTERACTION_STARTING:
2754 mContext.enforceCallingOrSelfPermission(
2755 android.Manifest.permission.STATUS_BAR_SERVICE,
2756 "PhoneWindowManager");
2758 case TYPE_KEYGUARD_SCRIM:
2759 if (mKeyguardScrim != null) {
2760 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2762 mKeyguardScrim = win;
2765 return WindowManagerGlobal.ADD_OKAY;
2768 /** {@inheritDoc} */
2770 public void removeWindowLw(WindowState win) {
2771 if (mStatusBar == win) {
2773 mStatusBarController.setWindow(null);
2774 mKeyguardDelegate.showScrim();
2775 } else if (mKeyguardScrim == win) {
2776 Log.v(TAG, "Removing keyguard scrim");
2777 mKeyguardScrim = null;
2778 } if (mNavigationBar == win) {
2779 mNavigationBar = null;
2780 mNavigationBarController.setWindow(null);
2784 static final boolean PRINT_ANIM = false;
2786 /** {@inheritDoc} */
2788 public int selectAnimationLw(WindowState win, int transit) {
2789 if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
2790 + ": transit=" + transit);
2791 if (win == mStatusBar) {
2792 boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
2793 if (transit == TRANSIT_EXIT
2794 || transit == TRANSIT_HIDE) {
2795 return isKeyguard ? -1 : R.anim.dock_top_exit;
2796 } else if (transit == TRANSIT_ENTER
2797 || transit == TRANSIT_SHOW) {
2798 return isKeyguard ? -1 : R.anim.dock_top_enter;
2800 } else if (win == mNavigationBar) {
2801 if (win.getAttrs().windowAnimations != 0) {
2804 // This can be on either the bottom or the right or the left.
2805 if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
2806 if (transit == TRANSIT_EXIT
2807 || transit == TRANSIT_HIDE) {
2808 return R.anim.dock_bottom_exit;
2809 } else if (transit == TRANSIT_ENTER
2810 || transit == TRANSIT_SHOW) {
2811 return R.anim.dock_bottom_enter;
2813 } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
2814 if (transit == TRANSIT_EXIT
2815 || transit == TRANSIT_HIDE) {
2816 return R.anim.dock_right_exit;
2817 } else if (transit == TRANSIT_ENTER
2818 || transit == TRANSIT_SHOW) {
2819 return R.anim.dock_right_enter;
2821 } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
2822 if (transit == TRANSIT_EXIT
2823 || transit == TRANSIT_HIDE) {
2824 return R.anim.dock_left_exit;
2825 } else if (transit == TRANSIT_ENTER
2826 || transit == TRANSIT_SHOW) {
2827 return R.anim.dock_left_enter;
2830 } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) {
2831 return selectDockedDividerAnimationLw(win, transit);
2834 if (transit == TRANSIT_PREVIEW_DONE) {
2835 if (win.hasAppShownWindows()) {
2836 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
2837 return com.android.internal.R.anim.app_starting_exit;
2839 } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
2840 && transit == TRANSIT_ENTER) {
2841 // Special case: we are animating in a dream, while the keyguard
2842 // is shown. We don't want an animation on the dream, because
2843 // we need it shown immediately with the keyguard animating away
2851 private int selectDockedDividerAnimationLw(WindowState win, int transit) {
2852 int insets = mWindowManagerFuncs.getDockedDividerInsetsLw();
2854 // If the divider is behind the navigation bar, don't animate.
2855 final Rect frame = win.getFrameLw();
2856 final boolean behindNavBar = mNavigationBar != null
2857 && ((mNavigationBarPosition == NAV_BAR_BOTTOM
2858 && frame.top + insets >= mNavigationBar.getFrameLw().top)
2859 || (mNavigationBarPosition == NAV_BAR_RIGHT
2860 && frame.left + insets >= mNavigationBar.getFrameLw().left)
2861 || (mNavigationBarPosition == NAV_BAR_LEFT
2862 && frame.right - insets <= mNavigationBar.getFrameLw().right));
2863 final boolean landscape = frame.height() > frame.width();
2864 final boolean offscreenLandscape = landscape && (frame.right - insets <= 0
2865 || frame.left + insets >= win.getDisplayFrameLw().right);
2866 final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0
2867 || frame.bottom + insets >= win.getDisplayFrameLw().bottom);
2868 final boolean offscreen = offscreenLandscape || offscreenPortrait;
2869 if (behindNavBar || offscreen) {
2872 if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
2873 return R.anim.fade_in;
2874 } else if (transit == TRANSIT_EXIT) {
2875 return R.anim.fade_out;
2882 public void selectRotationAnimationLw(int anim[]) {
2883 if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
2884 + mTopFullscreenOpaqueWindowState + " rotationAnimation="
2885 + (mTopFullscreenOpaqueWindowState == null ?
2886 "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation));
2887 if (mTopFullscreenOpaqueWindowState != null) {
2888 int animationHint = mTopFullscreenOpaqueWindowState.getRotationAnimationHint();
2889 if (animationHint < 0 && mTopIsFullscreen) {
2890 animationHint = mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation;
2892 switch (animationHint) {
2893 case ROTATION_ANIMATION_CROSSFADE:
2894 case ROTATION_ANIMATION_SEAMLESS: // Crossfade is fallback for seamless.
2895 anim[0] = R.anim.rotation_animation_xfade_exit;
2896 anim[1] = R.anim.rotation_animation_enter;
2898 case ROTATION_ANIMATION_JUMPCUT:
2899 anim[0] = R.anim.rotation_animation_jump_exit;
2900 anim[1] = R.anim.rotation_animation_enter;
2902 case ROTATION_ANIMATION_ROTATE:
2904 anim[0] = anim[1] = 0;
2908 anim[0] = anim[1] = 0;
2913 public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId,
2914 boolean forceDefault) {
2915 switch (exitAnimId) {
2916 case R.anim.rotation_animation_xfade_exit:
2917 case R.anim.rotation_animation_jump_exit:
2918 // These are the only cases that matter.
2922 int anim[] = new int[2];
2923 selectRotationAnimationLw(anim);
2924 return (exitAnimId == anim[0] && enterAnimId == anim[1]);
2931 public Animation createForceHideEnterAnimation(boolean onWallpaper,
2932 boolean goingToNotificationShade) {
2933 if (goingToNotificationShade) {
2934 return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
2937 AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ?
2938 R.anim.lock_screen_behind_enter_wallpaper :
2939 R.anim.lock_screen_behind_enter);
2941 // TODO: Use XML interpolators when we have log interpolators available in XML.
2942 final List<Animation> animations = set.getAnimations();
2943 for (int i = animations.size() - 1; i >= 0; --i) {
2944 animations.get(i).setInterpolator(mLogDecelerateInterpolator);
2952 public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade) {
2953 if (goingToNotificationShade) {
2956 return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
2960 private static void awakenDreams() {
2961 IDreamManager dreamManager = getDreamManager();
2962 if (dreamManager != null) {
2964 dreamManager.awaken();
2965 } catch (RemoteException e) {
2966 // fine, stay asleep then
2971 static IDreamManager getDreamManager() {
2972 return IDreamManager.Stub.asInterface(
2973 ServiceManager.checkService(DreamService.DREAM_SERVICE));
2976 TelecomManager getTelecommService() {
2977 return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
2980 static IAudioService getAudioService() {
2981 IAudioService audioService = IAudioService.Stub.asInterface(
2982 ServiceManager.checkService(Context.AUDIO_SERVICE));
2983 if (audioService == null) {
2984 Log.w(TAG, "Unable to find IAudioService interface.");
2986 return audioService;
2989 boolean keyguardOn() {
2990 return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode();
2993 private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
2994 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
2995 WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
2998 /** {@inheritDoc} */
3000 public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
3001 final boolean keyguardOn = keyguardOn();
3002 final int keyCode = event.getKeyCode();
3003 final int repeatCount = event.getRepeatCount();
3004 final int metaState = event.getMetaState();
3005 final int flags = event.getFlags();
3006 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
3007 final boolean canceled = event.isCanceled();
3010 Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
3011 + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
3012 + " canceled=" + canceled);
3015 // If we think we might have a volume down & power key chord on the way
3016 // but we're not sure, then tell the dispatcher to wait a little while and
3017 // try again later before dispatching.
3018 if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
3019 if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
3020 final long now = SystemClock.uptimeMillis();
3021 final long timeoutTime = mScreenshotChordVolumeDownKeyTime
3022 + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
3023 if (now < timeoutTime) {
3024 return timeoutTime - now;
3027 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3028 && mScreenshotChordVolumeDownKeyConsumed) {
3030 mScreenshotChordVolumeDownKeyConsumed = false;
3036 // Cancel any pending meta actions if we see any other keys being pressed between the down
3037 // of the meta key and its corresponding up.
3038 if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
3039 mPendingMetaAction = false;
3041 // Any key that is not Alt or Meta cancels Caps Lock combo tracking.
3042 if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) {
3043 mPendingCapsLockToggle = false;
3046 // First we always handle the home key here, so applications
3047 // can never break it, although if keyguard is on, we do let
3048 // it handle it, because that gives us the correct 5 second
3050 if (keyCode == KeyEvent.KEYCODE_HOME) {
3052 // If we have released the home key, and didn't do anything else
3053 // while it was pressed, then it is time to go home!
3055 cancelPreloadRecentApps();
3057 mHomePressed = false;
3058 if (mHomeConsumed) {
3059 mHomeConsumed = false;
3064 Log.i(TAG, "Ignoring HOME; event canceled.");
3068 // Delay handling home if a double-tap is possible.
3069 if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
3070 mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
3071 mHomeDoubleTapPending = true;
3072 mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
3073 ViewConfiguration.getDoubleTapTimeout());
3077 handleShortPressOnHome();
3081 // If a system window has focus, then it doesn't make sense
3082 // right now to interact with applications.
3083 WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
3084 if (attrs != null) {
3085 final int type = attrs.type;
3086 if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM
3087 || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
3088 || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
3089 // the "app" is keyguard, so give it the key
3092 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
3093 for (int i=0; i<typeCount; i++) {
3094 if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
3095 // don't do anything, but also don't pass it to the app
3101 // Remember that home is pressed and handle special actions.
3102 if (repeatCount == 0) {
3103 mHomePressed = true;
3104 if (mHomeDoubleTapPending) {
3105 mHomeDoubleTapPending = false;
3106 mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
3107 handleDoubleTapOnHome();
3108 } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI
3109 || mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
3110 preloadRecentApps();
3112 } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
3114 handleLongPressOnHome(event.getDeviceId());
3118 } else if (keyCode == KeyEvent.KEYCODE_MENU) {
3119 // Hijack modified menu keys for debugging features
3120 final int chordBug = KeyEvent.META_SHIFT_ON;
3122 if (down && repeatCount == 0) {
3123 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
3124 Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
3125 mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
3126 null, null, null, 0, null, null);
3128 } else if (SHOW_PROCESSES_ON_ALT_MENU &&
3129 (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
3130 Intent service = new Intent();
3131 service.setClassName(mContext, "com.android.server.LoadAverageService");
3132 ContentResolver res = mContext.getContentResolver();
3133 boolean shown = Settings.Global.getInt(
3134 res, Settings.Global.SHOW_PROCESSES, 0) != 0;
3136 mContext.startService(service);
3138 mContext.stopService(service);
3140 Settings.Global.putInt(
3141 res, Settings.Global.SHOW_PROCESSES, shown ? 0 : 1);
3145 } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
3147 if (repeatCount == 0) {
3148 mSearchKeyShortcutPending = true;
3149 mConsumeSearchKeyUp = false;
3152 mSearchKeyShortcutPending = false;
3153 if (mConsumeSearchKeyUp) {
3154 mConsumeSearchKeyUp = false;
3159 } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
3161 if (down && repeatCount == 0) {
3162 preloadRecentApps();
3168 } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) {
3170 IStatusBarService service = getStatusBarService();
3171 if (service != null) {
3173 service.expandNotificationsPanel();
3174 } catch (RemoteException e) {
3179 } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed()
3180 && event.isCtrlPressed()) {
3181 if (down && repeatCount == 0) {
3182 int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION
3183 : TAKE_SCREENSHOT_FULLSCREEN;
3184 mScreenshotRunnable.setScreenshotType(type);
3185 mHandler.post(mScreenshotRunnable);
3188 } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
3189 if (down && repeatCount == 0 && !isKeyguardLocked()) {
3190 toggleKeyboardShortcutsMenu(event.getDeviceId());
3192 } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
3194 if (repeatCount == 0) {
3195 mAssistKeyLongPressed = false;
3196 } else if (repeatCount == 1) {
3197 mAssistKeyLongPressed = true;
3199 launchAssistLongPressAction();
3203 if (mAssistKeyLongPressed) {
3204 mAssistKeyLongPressed = false;
3207 launchAssistAction(null, event.getDeviceId());
3212 } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
3216 voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
3218 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
3219 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
3222 dic.exitIdle("voice-search");
3223 } catch (RemoteException e) {
3226 voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
3227 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
3229 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
3231 } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
3232 if (down && repeatCount == 0) {
3233 mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
3234 mHandler.post(mScreenshotRunnable);
3237 } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP
3238 || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) {
3240 int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
3242 // Disable autobrightness if it's on
3243 int auto = Settings.System.getIntForUser(
3244 mContext.getContentResolver(),
3245 Settings.System.SCREEN_BRIGHTNESS_MODE,
3246 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3247 UserHandle.USER_CURRENT_OR_SELF);
3249 Settings.System.putIntForUser(mContext.getContentResolver(),
3250 Settings.System.SCREEN_BRIGHTNESS_MODE,
3251 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3252 UserHandle.USER_CURRENT_OR_SELF);
3255 int min = mPowerManager.getMinimumScreenBrightnessSetting();
3256 int max = mPowerManager.getMaximumScreenBrightnessSetting();
3257 int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction;
3258 int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
3259 Settings.System.SCREEN_BRIGHTNESS,
3260 mPowerManager.getDefaultScreenBrightnessSetting(),
3261 UserHandle.USER_CURRENT_OR_SELF);
3263 // Make sure we don't go beyond the limits.
3264 brightness = Math.min(max, brightness);
3265 brightness = Math.max(min, brightness);
3267 Settings.System.putIntForUser(mContext.getContentResolver(),
3268 Settings.System.SCREEN_BRIGHTNESS, brightness,
3269 UserHandle.USER_CURRENT_OR_SELF);
3270 startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
3271 UserHandle.CURRENT_OR_SELF);
3274 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
3275 || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3276 || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
3277 if (mUseTvRouting) {
3278 // On TVs volume keys never go to the foreground app.
3279 dispatchDirectAudioEvent(event);
3284 // Toggle Caps Lock on META-ALT.
3285 boolean actionTriggered = false;
3286 if (KeyEvent.isModifierKey(keyCode)) {
3287 if (!mPendingCapsLockToggle) {
3288 // Start tracking meta state for combo.
3289 mInitialMetaState = mMetaState;
3290 mPendingCapsLockToggle = true;
3291 } else if (event.getAction() == KeyEvent.ACTION_UP) {
3292 int altOnMask = mMetaState & KeyEvent.META_ALT_MASK;
3293 int metaOnMask = mMetaState & KeyEvent.META_META_MASK;
3295 // Check for Caps Lock toggle
3296 if ((metaOnMask != 0) && (altOnMask != 0)) {
3297 // Check if nothing else is pressed
3298 if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) {
3299 // Handle Caps Lock Toggle
3300 mInputManagerInternal.toggleCapsLock(event.getDeviceId());
3301 actionTriggered = true;
3305 // Always stop tracking when key goes up.
3306 mPendingCapsLockToggle = false;
3309 // Store current meta state to be able to evaluate it later.
3310 mMetaState = metaState;
3312 if (actionTriggered) {
3316 if (KeyEvent.isMetaKey(keyCode)) {
3318 mPendingMetaAction = true;
3319 } else if (mPendingMetaAction) {
3320 launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId());
3325 // Shortcuts are invoked through Search+key, so intercept those here
3326 // Any printing key that is chorded with Search should be consumed
3327 // even if no shortcut was invoked. This prevents text from being
3328 // inadvertently inserted when using a keyboard that has built-in macro
3329 // shortcut keys (that emit Search+x) and some of them are not registered.
3330 if (mSearchKeyShortcutPending) {
3331 final KeyCharacterMap kcm = event.getKeyCharacterMap();
3332 if (kcm.isPrintingKey(keyCode)) {
3333 mConsumeSearchKeyUp = true;
3334 mSearchKeyShortcutPending = false;
3335 if (down && repeatCount == 0 && !keyguardOn) {
3336 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
3337 if (shortcutIntent != null) {
3338 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3340 startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3341 dismissKeyboardShortcutsMenu();
3342 } catch (ActivityNotFoundException ex) {
3343 Slog.w(TAG, "Dropping shortcut key combination because "
3344 + "the activity to which it is registered was not found: "
3345 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);
3348 Slog.i(TAG, "Dropping unregistered shortcut key combination: "
3349 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));
3356 // Invoke shortcuts using Meta.
3357 if (down && repeatCount == 0 && !keyguardOn
3358 && (metaState & KeyEvent.META_META_ON) != 0) {
3359 final KeyCharacterMap kcm = event.getKeyCharacterMap();
3360 if (kcm.isPrintingKey(keyCode)) {
3361 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
3362 metaState & ~(KeyEvent.META_META_ON
3363 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
3364 if (shortcutIntent != null) {
3365 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3367 startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3368 dismissKeyboardShortcutsMenu();
3369 } catch (ActivityNotFoundException ex) {
3370 Slog.w(TAG, "Dropping shortcut key combination because "
3371 + "the activity to which it is registered was not found: "
3372 + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
3379 // Handle application launch keys.
3380 if (down && repeatCount == 0 && !keyguardOn) {
3381 String category = sApplicationLaunchKeyCategories.get(keyCode);
3382 if (category != null) {
3383 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
3384 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3386 startActivityAsUser(intent, UserHandle.CURRENT);
3387 dismissKeyboardShortcutsMenu();
3388 } catch (ActivityNotFoundException ex) {
3389 Slog.w(TAG, "Dropping application launch key because "
3390 + "the activity to which it is registered was not found: "
3391 + "keyCode=" + keyCode + ", category=" + category, ex);
3397 // Display task switcher for ALT-TAB.
3398 if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
3399 if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
3400 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
3401 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
3402 mRecentAppsHeldModifiers = shiftlessModifiers;
3403 showRecentApps(true, false);
3407 } else if (!down && mRecentAppsHeldModifiers != 0
3408 && (metaState & mRecentAppsHeldModifiers) == 0) {
3409 mRecentAppsHeldModifiers = 0;
3410 hideRecentApps(true, false);
3413 // Handle input method switching.
3414 if (down && repeatCount == 0
3415 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3416 || (keyCode == KeyEvent.KEYCODE_SPACE
3417 && (metaState & KeyEvent.META_META_MASK) != 0))) {
3418 final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0;
3419 mWindowManagerFuncs.switchInputMethod(forwardDirection);
3422 if (mLanguageSwitchKeyPressed && !down
3423 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3424 || keyCode == KeyEvent.KEYCODE_SPACE)) {
3425 mLanguageSwitchKeyPressed = false;
3429 if (isValidGlobalKey(keyCode)
3430 && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
3435 long shortcutCode = keyCode;
3436 if (event.isCtrlPressed()) {
3437 shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
3440 if (event.isAltPressed()) {
3441 shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
3444 if (event.isShiftPressed()) {
3445 shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
3448 if (event.isMetaPressed()) {
3449 shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE;
3452 IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode);
3453 if (shortcutService != null) {
3455 if (isUserSetupComplete()) {
3456 shortcutService.notifyShortcutKeyPressed(shortcutCode);
3458 } catch (RemoteException e) {
3459 mShortcutKeyServices.delete(shortcutCode);
3465 // Reserve all the META modifier combos for system behavior
3466 if ((metaState & KeyEvent.META_META_ON) != 0) {
3470 // Let the application handle the key.
3474 /** {@inheritDoc} */
3476 public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
3477 // Note: This method is only called if the initial down was unhandled.
3479 Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
3480 + ", flags=" + event.getFlags()
3481 + ", keyCode=" + event.getKeyCode()
3482 + ", scanCode=" + event.getScanCode()
3483 + ", metaState=" + event.getMetaState()
3484 + ", repeatCount=" + event.getRepeatCount()
3485 + ", policyFlags=" + policyFlags);
3488 KeyEvent fallbackEvent = null;
3489 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3490 final KeyCharacterMap kcm = event.getKeyCharacterMap();
3491 final int keyCode = event.getKeyCode();
3492 final int metaState = event.getMetaState();
3493 final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
3494 && event.getRepeatCount() == 0;
3496 // Check for fallback actions specified by the key character map.
3497 final FallbackAction fallbackAction;
3499 fallbackAction = kcm.getFallbackAction(keyCode, metaState);
3501 fallbackAction = mFallbackActions.get(keyCode);
3504 if (fallbackAction != null) {
3506 Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode
3507 + " metaState=" + Integer.toHexString(fallbackAction.metaState));
3510 final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
3511 fallbackEvent = KeyEvent.obtain(
3512 event.getDownTime(), event.getEventTime(),
3513 event.getAction(), fallbackAction.keyCode,
3514 event.getRepeatCount(), fallbackAction.metaState,
3515 event.getDeviceId(), event.getScanCode(),
3516 flags, event.getSource(), null);
3518 if (!interceptFallback(win, fallbackEvent, policyFlags)) {
3519 fallbackEvent.recycle();
3520 fallbackEvent = null;
3524 mFallbackActions.put(keyCode, fallbackAction);
3525 } else if (event.getAction() == KeyEvent.ACTION_UP) {
3526 mFallbackActions.remove(keyCode);
3527 fallbackAction.recycle();
3533 if (fallbackEvent == null) {
3534 Slog.d(TAG, "No fallback.");
3536 Slog.d(TAG, "Performing fallback: " + fallbackEvent);
3539 return fallbackEvent;
3542 private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
3543 int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
3544 if ((actions & ACTION_PASS_TO_USER) != 0) {
3545 long delayMillis = interceptKeyBeforeDispatching(
3546 win, fallbackEvent, policyFlags);
3547 if (delayMillis == 0) {
3555 public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
3556 throws RemoteException {
3557 synchronized (mLock) {
3558 IShortcutService service = mShortcutKeyServices.get(shortcutCode);
3559 if (service != null && service.asBinder().pingBinder()) {
3560 throw new RemoteException("Key already exists.");
3563 mShortcutKeyServices.put(shortcutCode, shortcutService);
3568 public boolean canShowDismissingWindowWhileLockedLw() {
3569 // If the keyguard is trusted, it will unlock without a challange. Therefore, windows with
3570 // FLAG_DISMISS_KEYGUARD don't need to be force hidden, as they will unlock the phone right
3572 return mKeyguardDelegate != null && mKeyguardDelegate.isTrusted();
3575 private void launchAssistLongPressAction() {
3576 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
3577 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
3579 // launch the search activity
3580 Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
3581 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3583 // TODO: This only stops the factory-installed search manager.
3584 // Need to formalize an API to handle others
3585 SearchManager searchManager = getSearchManager();
3586 if (searchManager != null) {
3587 searchManager.stopSearch();
3589 startActivityAsUser(intent, UserHandle.CURRENT);
3590 } catch (ActivityNotFoundException e) {
3591 Slog.w(TAG, "No activity to handle assist long press action.", e);
3595 private void launchAssistAction(String hint, int deviceId) {
3596 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
3597 if (!isUserSetupComplete()) {
3598 // Disable opening assist window during setup
3602 if (deviceId > Integer.MIN_VALUE) {
3603 args = new Bundle();
3604 args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
3606 if ((mContext.getResources().getConfiguration().uiMode
3607 & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
3608 // On TV, use legacy handling until assistants are implemented in the proper way.
3609 ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
3610 .launchLegacyAssist(hint, UserHandle.myUserId(), args);
3614 args = new Bundle();
3616 args.putBoolean(hint, true);
3618 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3619 if (statusbar != null) {
3620 statusbar.startAssist(args);
3625 private void startActivityAsUser(Intent intent, UserHandle handle) {
3626 if (isUserSetupComplete()) {
3627 mContext.startActivityAsUser(intent, handle);
3629 Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent);
3633 private SearchManager getSearchManager() {
3634 if (mSearchManager == null) {
3635 mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
3637 return mSearchManager;
3640 private void preloadRecentApps() {
3641 mPreloadedRecentApps = true;
3642 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3643 if (statusbar != null) {
3644 statusbar.preloadRecentApps();
3648 private void cancelPreloadRecentApps() {
3649 if (mPreloadedRecentApps) {
3650 mPreloadedRecentApps = false;
3651 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3652 if (statusbar != null) {
3653 statusbar.cancelPreloadRecentApps();
3658 private void toggleRecentApps() {
3659 mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3660 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3661 if (statusbar != null) {
3662 statusbar.toggleRecentApps();
3667 public void showRecentApps(boolean fromHome) {
3668 mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
3669 mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget();
3672 private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
3673 mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3674 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3675 if (statusbar != null) {
3676 statusbar.showRecentApps(triggeredFromAltTab, fromHome);
3680 private void toggleKeyboardShortcutsMenu(int deviceId) {
3681 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3682 if (statusbar != null) {
3683 statusbar.toggleKeyboardShortcutsMenu(deviceId);
3687 private void dismissKeyboardShortcutsMenu() {
3688 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3689 if (statusbar != null) {
3690 statusbar.dismissKeyboardShortcutsMenu();
3694 private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
3695 mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3696 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3697 if (statusbar != null) {
3698 statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
3702 void launchHomeFromHotKey() {
3703 launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/);
3707 * A home key -> launch home action was detected. Take the appropriate action
3708 * given the situation with the keyguard.
3710 void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) {
3711 if (respectKeyguard) {
3712 if (isKeyguardShowingAndNotOccluded()) {
3713 // don't launch home if keyguard showing
3717 if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) {
3718 // when in keyguard restricted mode, must first verify unlock
3719 // before launching home
3720 mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
3722 public void onKeyguardExitResult(boolean success) {
3725 ActivityManagerNative.getDefault().stopAppSwitches();
3726 } catch (RemoteException e) {
3728 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
3729 startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
3737 // no keyguard stuff to worry about, just launch home!
3739 ActivityManagerNative.getDefault().stopAppSwitches();
3740 } catch (RemoteException e) {
3742 if (mRecentsVisible) {
3743 // Hide Recents and notify it to launch Home
3744 if (awakenFromDreams) {
3747 hideRecentApps(false, true);
3749 // Otherwise, just launch Home
3750 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
3751 startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
3755 private final Runnable mClearHideNavigationFlag = new Runnable() {
3758 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
3760 mForceClearedSystemUiFlags &=
3761 ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
3763 mWindowManagerFuncs.reevaluateStatusBarVisibility();
3768 * Input handler used while nav bar is hidden. Captures any touch on the screen,
3769 * to determine when the nav bar should be shown and prevent applications from
3770 * receiving those touches.
3772 final class HideNavInputEventReceiver extends InputEventReceiver {
3773 public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
3774 super(inputChannel, looper);
3778 public void onInputEvent(InputEvent event) {
3779 boolean handled = false;
3781 if (event instanceof MotionEvent
3782 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
3783 final MotionEvent motionEvent = (MotionEvent)event;
3784 if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
3785 // When the user taps down, we re-show the nav bar.
3786 boolean changed = false;
3787 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
3788 if (mInputConsumer == null) {
3791 // Any user activity always causes us to show the
3792 // navigation controls, if they had been hidden.
3793 // We also clear the low profile and only content
3794 // flags so that tapping on the screen will atomically
3795 // restore all currently hidden screen decorations.
3796 int newVal = mResettingSystemUiFlags |
3797 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
3798 View.SYSTEM_UI_FLAG_LOW_PROFILE |
3799 View.SYSTEM_UI_FLAG_FULLSCREEN;
3800 if (mResettingSystemUiFlags != newVal) {
3801 mResettingSystemUiFlags = newVal;
3804 // We don't allow the system's nav bar to be hidden
3805 // again for 1 second, to prevent applications from
3806 // spamming us and keeping it from being shown.
3807 newVal = mForceClearedSystemUiFlags |
3808 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
3809 if (mForceClearedSystemUiFlags != newVal) {
3810 mForceClearedSystemUiFlags = newVal;
3812 mHandler.postDelayed(mClearHideNavigationFlag, 1000);
3816 mWindowManagerFuncs.reevaluateStatusBarVisibility();
3821 finishInputEvent(event, handled);
3825 final InputEventReceiver.Factory mHideNavInputEventReceiverFactory =
3826 new InputEventReceiver.Factory() {
3828 public InputEventReceiver createInputEventReceiver(
3829 InputChannel inputChannel, Looper looper) {
3830 return new HideNavInputEventReceiver(inputChannel, looper);
3835 public int adjustSystemUiVisibilityLw(int visibility) {
3836 mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
3837 mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
3838 mRecentsVisible = (visibility & View.RECENT_APPS_VISIBLE) > 0;
3839 mTvPictureInPictureVisible = (visibility & View.TV_PICTURE_IN_PICTURE_VISIBLE) > 0;
3841 // Reset any bits in mForceClearingStatusBarVisibility that
3843 mResettingSystemUiFlags &= visibility;
3844 // Clear any bits in the new visibility that are currently being
3845 // force cleared, before reporting it.
3846 return visibility & ~mResettingSystemUiFlags
3847 & ~mForceClearedSystemUiFlags;
3851 public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
3852 int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets,
3853 Rect outStableInsets, Rect outOutsets) {
3854 final int fl = PolicyControl.getWindowFlags(null, attrs);
3855 final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
3856 final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
3858 final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
3860 int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
3862 if (displayRotation == Surface.ROTATION_0) {
3863 outOutsets.bottom += outset;
3864 } else if (displayRotation == Surface.ROTATION_90) {
3865 outOutsets.right += outset;
3866 } else if (displayRotation == Surface.ROTATION_180) {
3867 outOutsets.top += outset;
3868 } else if (displayRotation == Surface.ROTATION_270) {
3869 outOutsets.left += outset;
3874 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
3875 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
3876 int availRight, availBottom;
3877 if (canHideNavigationBar() &&
3878 (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
3879 availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
3880 availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
3882 availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
3883 availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
3885 if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
3886 if ((fl & FLAG_FULLSCREEN) != 0) {
3887 outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop,
3888 availRight - mStableFullscreenRight,
3889 availBottom - mStableFullscreenBottom);
3891 outContentInsets.set(mStableLeft, mStableTop,
3892 availRight - mStableRight, availBottom - mStableBottom);
3894 } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
3895 outContentInsets.setEmpty();
3896 } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
3897 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
3898 outContentInsets.set(mCurLeft, mCurTop,
3899 availRight - mCurRight, availBottom - mCurBottom);
3901 outContentInsets.set(mCurLeft, mCurTop,
3902 availRight - mCurRight, availBottom - mCurBottom);
3905 outStableInsets.set(mStableLeft, mStableTop,
3906 availRight - mStableRight, availBottom - mStableBottom);
3907 if (taskBounds != null) {
3908 calculateRelevantTaskInsets(taskBounds, outContentInsets,
3909 displayWidth, displayHeight);
3910 calculateRelevantTaskInsets(taskBounds, outStableInsets,
3911 displayWidth, displayHeight);
3913 return mForceShowSystemBars;
3915 outContentInsets.setEmpty();
3916 outStableInsets.setEmpty();
3917 return mForceShowSystemBars;
3921 * For any given task bounds, the insets relevant for these bounds given the insets relevant
3922 * for the entire display.
3924 private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth,
3925 int displayHeight) {
3926 mTmpRect.set(0, 0, displayWidth, displayHeight);
3927 mTmpRect.inset(inOutInsets);
3928 mTmpRect.intersect(taskBounds);
3929 int leftInset = mTmpRect.left - taskBounds.left;
3930 int topInset = mTmpRect.top - taskBounds.top;
3931 int rightInset = taskBounds.right - mTmpRect.right;
3932 int bottomInset = taskBounds.bottom - mTmpRect.bottom;
3933 inOutInsets.set(leftInset, topInset, rightInset, bottomInset);
3936 private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
3937 return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
3938 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
3941 /** {@inheritDoc} */
3943 public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
3944 int displayRotation, int uiMode) {
3945 mDisplayRotation = displayRotation;
3946 final int overscanLeft, overscanTop, overscanRight, overscanBottom;
3947 if (isDefaultDisplay) {
3948 switch (displayRotation) {
3949 case Surface.ROTATION_90:
3950 overscanLeft = mOverscanTop;
3951 overscanTop = mOverscanRight;
3952 overscanRight = mOverscanBottom;
3953 overscanBottom = mOverscanLeft;
3955 case Surface.ROTATION_180:
3956 overscanLeft = mOverscanRight;
3957 overscanTop = mOverscanBottom;
3958 overscanRight = mOverscanLeft;
3959 overscanBottom = mOverscanTop;
3961 case Surface.ROTATION_270:
3962 overscanLeft = mOverscanBottom;
3963 overscanTop = mOverscanLeft;
3964 overscanRight = mOverscanTop;
3965 overscanBottom = mOverscanRight;
3968 overscanLeft = mOverscanLeft;
3969 overscanTop = mOverscanTop;
3970 overscanRight = mOverscanRight;
3971 overscanBottom = mOverscanBottom;
3980 mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0;
3981 mOverscanScreenTop = mRestrictedOverscanScreenTop = 0;
3982 mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth;
3983 mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight;
3986 mSystemRight = displayWidth;
3987 mSystemBottom = displayHeight;
3988 mUnrestrictedScreenLeft = overscanLeft;
3989 mUnrestrictedScreenTop = overscanTop;
3990 mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight;
3991 mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom;
3992 mRestrictedScreenLeft = mUnrestrictedScreenLeft;
3993 mRestrictedScreenTop = mUnrestrictedScreenTop;
3994 mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth;
3995 mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight;
3996 mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft
3997 = mCurLeft = mUnrestrictedScreenLeft;
3998 mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop
3999 = mCurTop = mUnrestrictedScreenTop;
4000 mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight
4001 = mCurRight = displayWidth - overscanRight;
4002 mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom
4003 = mCurBottom = displayHeight - overscanBottom;
4004 mDockLayer = 0x10000000;
4005 mStatusBarLayer = -1;
4007 // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
4008 final Rect pf = mTmpParentFrame;
4009 final Rect df = mTmpDisplayFrame;
4010 final Rect of = mTmpOverscanFrame;
4011 final Rect vf = mTmpVisibleFrame;
4012 final Rect dcf = mTmpDecorFrame;
4013 pf.left = df.left = of.left = vf.left = mDockLeft;
4014 pf.top = df.top = of.top = vf.top = mDockTop;
4015 pf.right = df.right = of.right = vf.right = mDockRight;
4016 pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom;
4017 dcf.setEmpty(); // Decor frame N/A for system bars.
4019 if (isDefaultDisplay) {
4020 // For purposes of putting out fake window up to steal focus, we will
4021 // drive nav being hidden only by whether it is requested.
4022 final int sysui = mLastSystemUiFlags;
4023 boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
4024 boolean navTranslucent = (sysui
4025 & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
4026 boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
4027 boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
4028 boolean navAllowedHidden = immersive || immersiveSticky;
4029 navTranslucent &= !immersiveSticky; // transient trumps translucent
4030 boolean isKeyguardShowing = isStatusBarKeyguard() && !mHideLockScreen;
4031 if (!isKeyguardShowing) {
4032 navTranslucent &= areTranslucentBarsAllowed();
4034 boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null
4035 && mStatusBar.getAttrs().height == MATCH_PARENT
4036 && mStatusBar.getAttrs().width == MATCH_PARENT;
4038 // When the navigation bar isn't visible, we put up a fake
4039 // input window to catch all touch events. This way we can
4040 // detect when the user presses anywhere to bring back the nav
4041 // bar and ensure the application doesn't see the event.
4042 if (navVisible || navAllowedHidden) {
4043 if (mInputConsumer != null) {
4044 mHandler.sendMessage(
4045 mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
4046 mInputConsumer = null;
4048 } else if (mInputConsumer == null) {
4049 mInputConsumer = mWindowManagerFuncs.addInputConsumer(mHandler.getLooper(),
4050 mHideNavInputEventReceiverFactory);
4053 // For purposes of positioning and showing the nav bar, if we have
4054 // decided that it can't be hidden (because of the screen aspect ratio),
4055 // then take that into account.
4056 navVisible |= !canHideNavigationBar();
4058 boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight,
4059 displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom, dcf, navVisible, navTranslucent,
4060 navAllowedHidden, statusBarExpandedNotKeyguard);
4061 if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
4062 mDockLeft, mDockTop, mDockRight, mDockBottom));
4063 updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing);
4064 if (updateSysUiVisibility) {
4065 updateSystemUiVisibilityLw();
4070 private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui,
4071 boolean isKeyguardShowing) {
4072 // decide where the status bar goes ahead of time
4073 if (mStatusBar != null) {
4074 // apply any navigation bar insets
4075 pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4076 pf.top = df.top = of.top = mUnrestrictedScreenTop;
4077 pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4078 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
4079 + mUnrestrictedScreenTop;
4080 vf.left = mStableLeft;
4081 vf.top = mStableTop;
4082 vf.right = mStableRight;
4083 vf.bottom = mStableBottom;
4085 mStatusBarLayer = mStatusBar.getSurfaceLayer();
4087 // Let the status bar determine its size.
4088 mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
4089 vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
4090 dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */);
4092 // For layout, the status bar is always at the top with our fixed height.
4093 mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
4095 boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
4096 boolean statusBarTranslucent = (sysui
4097 & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
4098 if (!isKeyguardShowing) {
4099 statusBarTranslucent &= areTranslucentBarsAllowed();
4102 // If the status bar is hidden, we don't want to cause
4103 // windows behind it to scroll.
4104 if (mStatusBar.isVisibleLw() && !statusBarTransient) {
4105 // Status bar may go away, so the screen area it occupies
4106 // is available to apps but just covering them when the
4107 // status bar is visible.
4108 mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
4110 mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4111 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4112 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4113 mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4115 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " +
4117 "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
4118 mDockLeft, mDockTop, mDockRight, mDockBottom,
4119 mContentLeft, mContentTop, mContentRight, mContentBottom,
4120 mCurLeft, mCurTop, mCurRight, mCurBottom));
4122 if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
4123 && !statusBarTransient && !statusBarTranslucent
4124 && !mStatusBarController.wasRecentlyTranslucent()) {
4125 // If the opaque status bar is currently requested to be visible,
4126 // and not in the process of animating on or off, then
4127 // we can tell the app that it is covered by it.
4128 mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
4130 if (mStatusBarController.checkHiddenLw()) {
4137 private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation,
4138 int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf,
4139 boolean navVisible, boolean navTranslucent, boolean navAllowedHidden,
4140 boolean statusBarExpandedNotKeyguard) {
4141 if (mNavigationBar != null) {
4142 boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
4143 // Force the navigation bar to its appropriate place and
4144 // size. We need to do this directly, instead of relying on
4145 // it to bubble up from the nav bar, because this needs to
4146 // change atomically with screen rotations.
4147 mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight,
4149 if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
4150 // It's a system nav bar or a portrait screen; nav bar goes on bottom.
4151 int top = displayHeight - overscanBottom
4152 - getNavigationBarHeight(displayRotation, uiMode);
4153 mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
4154 mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
4155 if (transientNavBarShowing) {
4156 mNavigationBarController.setBarShowingLw(true);
4157 } else if (navVisible) {
4158 mNavigationBarController.setBarShowingLw(true);
4159 mDockBottom = mTmpNavigationFrame.top;
4160 mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
4161 mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
4163 // We currently want to hide the navigation UI - unless we expanded the status
4165 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4167 if (navVisible && !navTranslucent && !navAllowedHidden
4168 && !mNavigationBar.isAnimatingLw()
4169 && !mNavigationBarController.wasRecentlyTranslucent()) {
4170 // If the opaque nav bar is currently requested to be visible,
4171 // and not in the process of animating on or off, then
4172 // we can tell the app that it is covered by it.
4173 mSystemBottom = mTmpNavigationFrame.top;
4175 } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4176 // Landscape screen; nav bar goes to the right.
4177 int left = displayWidth - overscanRight
4178 - getNavigationBarWidth(displayRotation, uiMode);
4179 mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
4180 mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
4181 if (transientNavBarShowing) {
4182 mNavigationBarController.setBarShowingLw(true);
4183 } else if (navVisible) {
4184 mNavigationBarController.setBarShowingLw(true);
4185 mDockRight = mTmpNavigationFrame.left;
4186 mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4187 mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4189 // We currently want to hide the navigation UI - unless we expanded the status
4191 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4193 if (navVisible && !navTranslucent && !navAllowedHidden
4194 && !mNavigationBar.isAnimatingLw()
4195 && !mNavigationBarController.wasRecentlyTranslucent()) {
4196 // If the nav bar is currently requested to be visible,
4197 // and not in the process of animating on or off, then
4198 // we can tell the app that it is covered by it.
4199 mSystemRight = mTmpNavigationFrame.left;
4201 } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4202 // Seascape screen; nav bar goes to the left.
4203 int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode);
4204 mTmpNavigationFrame.set(overscanLeft, 0, right, displayHeight);
4205 mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right;
4206 if (transientNavBarShowing) {
4207 mNavigationBarController.setBarShowingLw(true);
4208 } else if (navVisible) {
4209 mNavigationBarController.setBarShowingLw(true);
4210 mDockLeft = mTmpNavigationFrame.right;
4211 // TODO: not so sure about those:
4212 mRestrictedScreenLeft = mRestrictedOverscanScreenLeft = mDockLeft;
4213 mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4214 mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4216 // We currently want to hide the navigation UI - unless we expanded the status
4218 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4220 if (navVisible && !navTranslucent && !navAllowedHidden
4221 && !mNavigationBar.isAnimatingLw()
4222 && !mNavigationBarController.wasRecentlyTranslucent()) {
4223 // If the nav bar is currently requested to be visible,
4224 // and not in the process of animating on or off, then
4225 // we can tell the app that it is covered by it.
4226 mSystemLeft = mTmpNavigationFrame.right;
4229 // Make sure the content and current rectangles are updated to
4230 // account for the restrictions from the navigation bar.
4231 mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4232 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4233 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4234 mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4235 mStatusBarLayer = mNavigationBar.getSurfaceLayer();
4236 // And compute the final frame.
4237 mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
4238 mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
4239 mTmpNavigationFrame, mTmpNavigationFrame);
4240 if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
4241 if (mNavigationBarController.checkHiddenLw()) {
4248 private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
4249 if (mNavigationBarCanMove && displayWidth > displayHeight) {
4250 if (displayRotation == Surface.ROTATION_270) {
4251 return NAV_BAR_LEFT;
4253 return NAV_BAR_RIGHT;
4256 return NAV_BAR_BOTTOM;
4259 /** {@inheritDoc} */
4261 public int getSystemDecorLayerLw() {
4262 if (mStatusBar != null && mStatusBar.isVisibleLw()) {
4263 return mStatusBar.getSurfaceLayer();
4266 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) {
4267 return mNavigationBar.getSurfaceLayer();
4274 public void getContentRectLw(Rect r) {
4275 r.set(mContentLeft, mContentTop, mContentRight, mContentBottom);
4278 void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
4279 boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
4280 if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
4281 // Here's a special case: if this attached window is a panel that is
4282 // above the dock window, and the window it is attached to is below
4283 // the dock window, then the frames we computed for the window it is
4284 // attached to can not be used because the dock is effectively part
4285 // of the underlying window and the attached window is floating on top
4286 // of the whole thing. So, we ignore the attached window and explicitly
4287 // compute the frames that would be appropriate without the dock.
4288 df.left = of.left = cf.left = vf.left = mDockLeft;
4289 df.top = of.top = cf.top = vf.top = mDockTop;
4290 df.right = of.right = cf.right = vf.right = mDockRight;
4291 df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom;
4293 // The effective display frame of the attached window depends on
4294 // whether it is taking care of insetting its content. If not,
4295 // we need to use the parent's content frame so that the entire
4296 // window is positioned within that content. Otherwise we can use
4297 // the overscan frame and let the attached window take care of
4298 // positioning its content appropriately.
4299 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4300 // Set the content frame of the attached window to the parent's decor frame
4301 // (same as content frame when IME isn't present) if specifically requested by
4302 // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
4303 // Otherwise, use the overscan frame.
4304 cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
4305 ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
4307 // If the window is resizing, then we want to base the content
4308 // frame on our attached content frame to resize... however,
4309 // things can be tricky if the attached window is NOT in resize
4310 // mode, in which case its content frame will be larger.
4311 // Ungh. So to deal with that, make sure the content frame
4312 // we end up using is not covering the IM dock.
4313 cf.set(attached.getContentFrameLw());
4314 if (attached.isVoiceInteraction()) {
4315 if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft;
4316 if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop;
4317 if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight;
4318 if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom;
4319 } else if (attached.getSurfaceLayer() < mDockLayer) {
4320 if (cf.left < mContentLeft) cf.left = mContentLeft;
4321 if (cf.top < mContentTop) cf.top = mContentTop;
4322 if (cf.right > mContentRight) cf.right = mContentRight;
4323 if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
4326 df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
4327 of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
4328 vf.set(attached.getVisibleFrameLw());
4330 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
4331 // window should be positioned relative to its parent or the entire
4333 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
4334 ? attached.getFrameLw() : df);
4337 private void applyStableConstraints(int sysui, int fl, Rect r) {
4338 if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4339 // If app is requesting a stable layout, don't let the
4340 // content insets go below the stable values.
4341 if ((fl & FLAG_FULLSCREEN) != 0) {
4342 if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft;
4343 if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop;
4344 if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight;
4345 if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom;
4347 if (r.left < mStableLeft) r.left = mStableLeft;
4348 if (r.top < mStableTop) r.top = mStableTop;
4349 if (r.right > mStableRight) r.right = mStableRight;
4350 if (r.bottom > mStableBottom) r.bottom = mStableBottom;
4355 private boolean canReceiveInput(WindowState win) {
4356 boolean notFocusable =
4357 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
4358 boolean altFocusableIm =
4359 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
4360 boolean notFocusableForIm = notFocusable ^ altFocusableIm;
4361 return !notFocusableForIm;
4364 /** {@inheritDoc} */
4366 public void layoutWindowLw(WindowState win, WindowState attached) {
4367 // We've already done the navigation bar and status bar. If the status bar can receive
4368 // input, we need to layout it again to accomodate for the IME window.
4369 if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) {
4372 final WindowManager.LayoutParams attrs = win.getAttrs();
4373 final boolean isDefaultDisplay = win.isDefaultDisplay();
4374 final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
4375 (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
4376 if (needsToOffsetInputMethodTarget) {
4377 if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
4378 offsetInputMethodWindowLw(mLastInputMethodWindow);
4381 final int fl = PolicyControl.getWindowFlags(win, attrs);
4382 final int pfl = attrs.privateFlags;
4383 final int sim = attrs.softInputMode;
4384 final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
4386 final Rect pf = mTmpParentFrame;
4387 final Rect df = mTmpDisplayFrame;
4388 final Rect of = mTmpOverscanFrame;
4389 final Rect cf = mTmpContentFrame;
4390 final Rect vf = mTmpVisibleFrame;
4391 final Rect dcf = mTmpDecorFrame;
4392 final Rect sf = mTmpStableFrame;
4396 final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
4397 && mNavigationBar != null && mNavigationBar.isVisibleLw());
4399 final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
4401 if (isDefaultDisplay) {
4402 sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom);
4404 sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom);
4407 if (!isDefaultDisplay) {
4408 if (attached != null) {
4409 // If this window is attached to another, our display
4410 // frame is the same as the one we are attached to.
4411 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4413 // Give the window full screen.
4414 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4415 pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4416 pf.right = df.right = of.right = cf.right
4417 = mOverscanScreenLeft + mOverscanScreenWidth;
4418 pf.bottom = df.bottom = of.bottom = cf.bottom
4419 = mOverscanScreenTop + mOverscanScreenHeight;
4421 } else if (attrs.type == TYPE_INPUT_METHOD) {
4422 pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
4423 pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
4424 pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
4425 // IM dock windows layout below the nav bar...
4426 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4427 // ...with content insets above the nav bar
4428 cf.bottom = vf.bottom = mStableBottom;
4429 if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
4430 // The status bar forces the navigation bar while it's visible. Make sure the IME
4431 // avoids the navigation bar in that case.
4432 if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4433 pf.right = df.right = of.right = cf.right = vf.right = mStableRight;
4434 } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4435 pf.left = df.left = of.left = cf.left = vf.left = mStableLeft;
4438 // IM dock windows always go to the bottom of the screen.
4439 attrs.gravity = Gravity.BOTTOM;
4440 mDockLayer = win.getSurfaceLayer();
4441 } else if (attrs.type == TYPE_VOICE_INTERACTION) {
4442 pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4443 pf.top = df.top = of.top = mUnrestrictedScreenTop;
4444 pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4445 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4446 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4447 cf.left = mDockLeft;
4449 cf.right = mDockRight;
4450 cf.bottom = mDockBottom;
4452 cf.left = mContentLeft;
4453 cf.top = mContentTop;
4454 cf.right = mContentRight;
4455 cf.bottom = mContentBottom;
4457 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4460 vf.right = mCurRight;
4461 vf.bottom = mCurBottom;
4465 } else if (attrs.type == TYPE_WALLPAPER) {
4466 layoutWallpaper(win, pf, df, of, cf);
4467 } else if (win == mStatusBar) {
4468 pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4469 pf.top = df.top = of.top = mUnrestrictedScreenTop;
4470 pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4471 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop;
4472 cf.left = vf.left = mStableLeft;
4473 cf.top = vf.top = mStableTop;
4474 cf.right = vf.right = mStableRight;
4475 vf.bottom = mStableBottom;
4477 if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
4478 cf.bottom = mContentBottom;
4480 cf.bottom = mDockBottom;
4481 vf.bottom = mContentBottom;
4485 // Default policy decor for the default display
4486 dcf.left = mSystemLeft;
4487 dcf.top = mSystemTop;
4488 dcf.right = mSystemRight;
4489 dcf.bottom = mSystemBottom;
4490 final boolean inheritTranslucentDecor = (attrs.privateFlags
4491 & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0;
4492 final boolean isAppWindow =
4493 attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW &&
4494 attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
4495 final boolean topAtRest =
4496 win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
4497 if (isAppWindow && !inheritTranslucentDecor && !topAtRest) {
4498 if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
4499 && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0
4500 && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
4501 && (fl & WindowManager.LayoutParams.
4502 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
4503 && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) {
4504 // Ensure policy decor includes status bar
4505 dcf.top = mStableTop;
4507 if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0
4508 && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
4509 && (fl & WindowManager.LayoutParams.
4510 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
4511 // Ensure policy decor includes navigation bar
4512 dcf.bottom = mStableBottom;
4513 dcf.right = mStableRight;
4517 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4518 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4519 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
4520 + "): IN_SCREEN, INSET_DECOR");
4521 // This is the case for a normal activity window: we want it
4522 // to cover all of the screen space, and it can take care of
4523 // moving its contents to account for screen decorations that
4524 // intrude into that space.
4525 if (attached != null) {
4526 // If this window is attached to another, our display
4527 // frame is the same as the one we are attached to.
4528 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4530 if (attrs.type == TYPE_STATUS_BAR_PANEL
4531 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
4532 // Status bar panels are the only windows who can go on top of
4533 // the status bar. They are protected by the STATUS_BAR_SERVICE
4534 // permission, so they have the same privileges as the status
4537 // However, they should still dodge the navigation bar if it exists.
4539 pf.left = df.left = of.left = hasNavBar
4540 ? mDockLeft : mUnrestrictedScreenLeft;
4541 pf.top = df.top = of.top = mUnrestrictedScreenTop;
4542 pf.right = df.right = of.right = hasNavBar
4543 ? mRestrictedScreenLeft+mRestrictedScreenWidth
4544 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4545 pf.bottom = df.bottom = of.bottom = hasNavBar
4546 ? mRestrictedScreenTop+mRestrictedScreenHeight
4547 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4549 if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4550 "Laying out status bar window: (%d,%d - %d,%d)",
4551 pf.left, pf.top, pf.right, pf.bottom));
4552 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4553 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4554 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4555 // Asking to layout into the overscan region, so give it that pure
4556 // unrestricted area.
4557 pf.left = df.left = of.left = mOverscanScreenLeft;
4558 pf.top = df.top = of.top = mOverscanScreenTop;
4559 pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth;
4560 pf.bottom = df.bottom = of.bottom = mOverscanScreenTop
4561 + mOverscanScreenHeight;
4562 } else if (canHideNavigationBar()
4563 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4564 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4565 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4566 // Asking for layout as if the nav bar is hidden, lets the
4567 // application extend into the unrestricted overscan screen area. We
4568 // only do this for application windows to ensure no window that
4569 // can be above the nav bar can do this.
4570 pf.left = df.left = mOverscanScreenLeft;
4571 pf.top = df.top = mOverscanScreenTop;
4572 pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
4573 pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
4574 // We need to tell the app about where the frame inside the overscan
4575 // is, so it can inset its content by that amount -- it didn't ask
4576 // to actually extend itself into the overscan region.
4577 of.left = mUnrestrictedScreenLeft;
4578 of.top = mUnrestrictedScreenTop;
4579 of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4580 of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4582 pf.left = df.left = mRestrictedOverscanScreenLeft;
4583 pf.top = df.top = mRestrictedOverscanScreenTop;
4584 pf.right = df.right = mRestrictedOverscanScreenLeft
4585 + mRestrictedOverscanScreenWidth;
4586 pf.bottom = df.bottom = mRestrictedOverscanScreenTop
4587 + mRestrictedOverscanScreenHeight;
4588 // We need to tell the app about where the frame inside the overscan
4589 // is, so it can inset its content by that amount -- it didn't ask
4590 // to actually extend itself into the overscan region.
4591 of.left = mUnrestrictedScreenLeft;
4592 of.top = mUnrestrictedScreenTop;
4593 of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4594 of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4597 if ((fl & FLAG_FULLSCREEN) == 0) {
4598 if (win.isVoiceInteraction()) {
4599 cf.left = mVoiceContentLeft;
4600 cf.top = mVoiceContentTop;
4601 cf.right = mVoiceContentRight;
4602 cf.bottom = mVoiceContentBottom;
4604 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4605 cf.left = mDockLeft;
4607 cf.right = mDockRight;
4608 cf.bottom = mDockBottom;
4610 cf.left = mContentLeft;
4611 cf.top = mContentTop;
4612 cf.right = mContentRight;
4613 cf.bottom = mContentBottom;
4617 // Full screen windows are always given a layout that is as if the
4618 // status bar and other transient decors are gone. This is to avoid
4619 // bad states when moving from a window that is not hding the
4620 // status bar to one that is.
4621 cf.left = mRestrictedScreenLeft;
4622 cf.top = mRestrictedScreenTop;
4623 cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
4624 cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4626 applyStableConstraints(sysUiFl, fl, cf);
4627 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4630 vf.right = mCurRight;
4631 vf.bottom = mCurBottom;
4636 } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
4637 & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
4638 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
4639 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4641 // A window that has requested to fill the entire screen just
4642 // gets everything, period.
4643 if (attrs.type == TYPE_STATUS_BAR_PANEL
4644 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL
4645 || attrs.type == TYPE_VOLUME_OVERLAY) {
4646 pf.left = df.left = of.left = cf.left = hasNavBar
4647 ? mDockLeft : mUnrestrictedScreenLeft;
4648 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
4649 pf.right = df.right = of.right = cf.right = hasNavBar
4650 ? mRestrictedScreenLeft+mRestrictedScreenWidth
4651 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4652 pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar
4653 ? mRestrictedScreenTop+mRestrictedScreenHeight
4654 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4655 if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4656 "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
4657 pf.left, pf.top, pf.right, pf.bottom));
4658 } else if (attrs.type == TYPE_NAVIGATION_BAR
4659 || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
4660 // The navigation bar has Real Ultimate Power.
4661 pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4662 pf.top = df.top = of.top = mUnrestrictedScreenTop;
4663 pf.right = df.right = of.right = mUnrestrictedScreenLeft
4664 + mUnrestrictedScreenWidth;
4665 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop
4666 + mUnrestrictedScreenHeight;
4667 if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4668 "Laying out navigation bar window: (%d,%d - %d,%d)",
4669 pf.left, pf.top, pf.right, pf.bottom));
4670 } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
4671 || attrs.type == TYPE_BOOT_PROGRESS
4672 || attrs.type == TYPE_SCREENSHOT)
4673 && ((fl & FLAG_FULLSCREEN) != 0)) {
4674 // Fullscreen secure system overlays get what they ask for. Screenshot region
4675 // selection overlay should also expand to full screen.
4676 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4677 pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4678 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
4679 + mOverscanScreenWidth;
4680 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
4681 + mOverscanScreenHeight;
4682 } else if (attrs.type == TYPE_BOOT_PROGRESS) {
4683 // Boot progress screen always covers entire display.
4684 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4685 pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4686 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
4687 + mOverscanScreenWidth;
4688 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
4689 + mOverscanScreenHeight;
4690 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4691 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4692 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4693 // Asking to layout into the overscan region, so give it that pure
4694 // unrestricted area.
4695 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4696 pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4697 pf.right = df.right = of.right = cf.right
4698 = mOverscanScreenLeft + mOverscanScreenWidth;
4699 pf.bottom = df.bottom = of.bottom = cf.bottom
4700 = mOverscanScreenTop + mOverscanScreenHeight;
4701 } else if (canHideNavigationBar()
4702 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4703 && (attrs.type == TYPE_STATUS_BAR
4704 || attrs.type == TYPE_TOAST
4705 || attrs.type == TYPE_DOCK_DIVIDER
4706 || attrs.type == TYPE_VOICE_INTERACTION_STARTING
4707 || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4708 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
4709 // Asking for layout as if the nav bar is hidden, lets the
4710 // application extend into the unrestricted screen area. We
4711 // only do this for application windows (or toasts) to ensure no window that
4712 // can be above the nav bar can do this.
4713 // XXX This assumes that an app asking for this will also
4714 // ask for layout in only content. We can't currently figure out
4715 // what the screen would be if only laying out to hide the nav bar.
4716 pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
4717 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
4718 pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft
4719 + mUnrestrictedScreenWidth;
4720 pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
4721 + mUnrestrictedScreenHeight;
4722 } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
4723 pf.left = df.left = of.left = mRestrictedScreenLeft;
4724 pf.top = df.top = of.top = mRestrictedScreenTop;
4725 pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
4726 pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop
4727 + mRestrictedScreenHeight;
4728 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4729 cf.left = mDockLeft;
4731 cf.right = mDockRight;
4732 cf.bottom = mDockBottom;
4734 cf.left = mContentLeft;
4735 cf.top = mContentTop;
4736 cf.right = mContentRight;
4737 cf.bottom = mContentBottom;
4740 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
4741 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
4742 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
4743 + mRestrictedScreenWidth;
4744 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
4745 + mRestrictedScreenHeight;
4748 applyStableConstraints(sysUiFl, fl, cf);
4750 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4753 vf.right = mCurRight;
4754 vf.bottom = mCurBottom;
4758 } else if (attached != null) {
4759 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4760 "): attached to " + attached);
4761 // A child window should be placed inside of the same visible
4762 // frame that its parent had.
4763 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf);
4765 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4766 "): normal window");
4767 // Otherwise, a normal window must be placed inside the content
4768 // of all screen decorations.
4769 if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) {
4770 // Status bar panels and the volume dialog are the only windows who can go on
4771 // top of the status bar. They are protected by the STATUS_BAR_SERVICE
4772 // permission, so they have the same privileges as the status
4774 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
4775 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
4776 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
4777 + mRestrictedScreenWidth;
4778 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
4779 + mRestrictedScreenHeight;
4780 } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) {
4781 // These dialogs are stable to interim decor changes.
4782 pf.left = df.left = of.left = cf.left = mStableLeft;
4783 pf.top = df.top = of.top = cf.top = mStableTop;
4784 pf.right = df.right = of.right = cf.right = mStableRight;
4785 pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom;
4787 pf.left = mContentLeft;
4788 pf.top = mContentTop;
4789 pf.right = mContentRight;
4790 pf.bottom = mContentBottom;
4791 if (win.isVoiceInteraction()) {
4792 df.left = of.left = cf.left = mVoiceContentLeft;
4793 df.top = of.top = cf.top = mVoiceContentTop;
4794 df.right = of.right = cf.right = mVoiceContentRight;
4795 df.bottom = of.bottom = cf.bottom = mVoiceContentBottom;
4796 } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4797 df.left = of.left = cf.left = mDockLeft;
4798 df.top = of.top = cf.top = mDockTop;
4799 df.right = of.right = cf.right = mDockRight;
4800 df.bottom = of.bottom = cf.bottom = mDockBottom;
4802 df.left = of.left = cf.left = mContentLeft;
4803 df.top = of.top = cf.top = mContentTop;
4804 df.right = of.right = cf.right = mContentRight;
4805 df.bottom = of.bottom = cf.bottom = mContentBottom;
4807 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4810 vf.right = mCurRight;
4811 vf.bottom = mCurBottom;
4819 // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
4820 // Also, we don't allow windows in multi-window mode to extend out of the screen.
4821 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR
4822 && !win.isInMultiWindowMode()) {
4823 df.left = df.top = -10000;
4824 df.right = df.bottom = 10000;
4825 if (attrs.type != TYPE_WALLPAPER) {
4826 of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
4827 of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
4831 // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we
4832 // need to provide information to the clients that want to pretend that you can draw there.
4833 // We only want to apply outsets to certain types of windows. For example, we never want to
4834 // apply the outsets to floating dialogs, because they wouldn't make sense there.
4835 final boolean useOutsets = shouldUseOutsets(attrs, fl);
4836 if (isDefaultDisplay && useOutsets) {
4837 osf = mTmpOutsetFrame;
4838 osf.set(cf.left, cf.top, cf.right, cf.bottom);
4839 int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
4841 int rotation = mDisplayRotation;
4842 if (rotation == Surface.ROTATION_0) {
4843 osf.bottom += outset;
4844 } else if (rotation == Surface.ROTATION_90) {
4845 osf.right += outset;
4846 } else if (rotation == Surface.ROTATION_180) {
4848 } else if (rotation == Surface.ROTATION_270) {
4851 if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset
4852 + " with rotation " + rotation + ", result: " + osf);
4856 if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
4857 + ": sim=#" + Integer.toHexString(sim)
4858 + " attach=" + attached + " type=" + attrs.type
4859 + String.format(" flags=0x%08x", fl)
4860 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
4861 + " of=" + of.toShortString()
4862 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
4863 + " dcf=" + dcf.toShortString()
4864 + " sf=" + sf.toShortString()
4865 + " osf=" + (osf == null ? "null" : osf.toShortString()));
4867 win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf);
4869 // Dock windows carve out the bottom of the screen, so normal windows
4870 // can't appear underneath them.
4871 if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleOrBehindKeyguardLw()
4872 && win.isDisplayedLw() && !win.getGivenInsetsPendingLw()) {
4873 setLastInputMethodWindowLw(null, null);
4874 offsetInputMethodWindowLw(win);
4876 if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleOrBehindKeyguardLw()
4877 && !win.getGivenInsetsPendingLw()) {
4878 offsetVoiceInputWindowLw(win);
4882 private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) {
4884 // The wallpaper also has Real Ultimate Power, but we want to tell
4885 // it about the overscan area.
4886 pf.left = df.left = mOverscanScreenLeft;
4887 pf.top = df.top = mOverscanScreenTop;
4888 pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
4889 pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
4890 of.left = cf.left = mUnrestrictedScreenLeft;
4891 of.top = cf.top = mUnrestrictedScreenTop;
4892 of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4893 of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4896 private void offsetInputMethodWindowLw(WindowState win) {
4897 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
4898 top += win.getGivenContentInsetsLw().top;
4899 if (mContentBottom > top) {
4900 mContentBottom = top;
4902 if (mVoiceContentBottom > top) {
4903 mVoiceContentBottom = top;
4905 top = win.getVisibleFrameLw().top;
4906 top += win.getGivenVisibleInsetsLw().top;
4907 if (mCurBottom > top) {
4910 if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
4911 + mDockBottom + " mContentBottom="
4912 + mContentBottom + " mCurBottom=" + mCurBottom);
4915 private void offsetVoiceInputWindowLw(WindowState win) {
4916 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
4917 top += win.getGivenContentInsetsLw().top;
4918 if (mVoiceContentBottom > top) {
4919 mVoiceContentBottom = top;
4923 /** {@inheritDoc} */
4925 public void finishLayoutLw() {
4929 /** {@inheritDoc} */
4931 public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
4932 mTopFullscreenOpaqueWindowState = null;
4933 mTopFullscreenOpaqueOrDimmingWindowState = null;
4934 mTopDockedOpaqueWindowState = null;
4935 mTopDockedOpaqueOrDimmingWindowState = null;
4936 mAppsToBeHidden.clear();
4937 mAppsThatDismissKeyguard.clear();
4938 mForceStatusBar = false;
4939 mForceStatusBarFromKeyguard = false;
4940 mForceStatusBarTransparent = false;
4941 mForcingShowNavBar = false;
4942 mForcingShowNavBarLayer = -1;
4944 mHideLockScreen = false;
4945 mAllowLockscreenWhenOn = false;
4946 mDismissKeyguard = DISMISS_KEYGUARD_NONE;
4947 mShowingLockscreen = false;
4948 mShowingDream = false;
4949 mWinShowWhenLocked = null;
4950 mKeyguardSecure = isKeyguardSecure(mCurrentUserId);
4951 mKeyguardSecureIncludingHidden = mKeyguardSecure
4952 && (mKeyguardDelegate != null && mKeyguardDelegate.isShowing());
4955 /** {@inheritDoc} */
4957 public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
4958 WindowState attached) {
4959 if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
4960 + win.isVisibleOrBehindKeyguardLw());
4961 final int fl = PolicyControl.getWindowFlags(win, attrs);
4962 if (mTopFullscreenOpaqueWindowState == null
4963 && win.isVisibleLw() && attrs.type == TYPE_INPUT_METHOD) {
4964 mForcingShowNavBar = true;
4965 mForcingShowNavBarLayer = win.getSurfaceLayer();
4967 if (attrs.type == TYPE_STATUS_BAR) {
4968 if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
4969 mForceStatusBarFromKeyguard = true;
4970 mShowingLockscreen = true;
4972 if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
4973 mForceStatusBarTransparent = true;
4977 boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
4978 && attrs.type < FIRST_SYSTEM_WINDOW;
4979 final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0;
4980 final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0;
4981 final int stackId = win.getStackId();
4982 if (mTopFullscreenOpaqueWindowState == null &&
4983 win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
4984 if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
4985 if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
4986 mForceStatusBarFromKeyguard = true;
4988 mForceStatusBar = true;
4991 if (attrs.type == TYPE_DREAM) {
4992 // If the lockscreen was showing when the dream started then wait
4993 // for the dream to draw before hiding the lockscreen.
4994 if (!mDreamingLockscreen
4995 || (win.isVisibleLw() && win.hasDrawnLw())) {
4996 mShowingDream = true;
5001 final IApplicationToken appToken = win.getAppToken();
5003 // For app windows that are not attached, we decide if all windows in the app they
5004 // represent should be hidden or if we should hide the lockscreen. For attached app
5005 // windows we defer the decision to the window it is attached to.
5006 if (appWindow && attached == null) {
5007 if (showWhenLocked) {
5008 // Remove any previous windows with the same appToken.
5009 mAppsToBeHidden.remove(appToken);
5010 mAppsThatDismissKeyguard.remove(appToken);
5011 if (mAppsToBeHidden.isEmpty()) {
5012 if (dismissKeyguard && !mKeyguardSecure) {
5013 mAppsThatDismissKeyguard.add(appToken);
5014 } else if (win.isDrawnLw() || win.hasAppShownWindows()) {
5015 mWinShowWhenLocked = win;
5016 mHideLockScreen = true;
5017 mForceStatusBarFromKeyguard = false;
5020 } else if (dismissKeyguard) {
5021 if (mKeyguardSecure) {
5022 mAppsToBeHidden.add(appToken);
5024 mAppsToBeHidden.remove(appToken);
5026 mAppsThatDismissKeyguard.add(appToken);
5028 mAppsToBeHidden.add(appToken);
5030 if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
5031 if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
5032 mTopFullscreenOpaqueWindowState = win;
5033 if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5034 mTopFullscreenOpaqueOrDimmingWindowState = win;
5036 if (!mAppsThatDismissKeyguard.isEmpty() &&
5037 mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
5038 if (DEBUG_LAYOUT) Slog.v(TAG,
5039 "Setting mDismissKeyguard true by win " + win);
5040 mDismissKeyguard = (mWinDismissingKeyguard == win
5041 && mSecureDismissingKeyguard == mKeyguardSecure)
5042 ? DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
5043 mWinDismissingKeyguard = win;
5044 mSecureDismissingKeyguard = mKeyguardSecure;
5045 mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure;
5046 } else if (mAppsToBeHidden.isEmpty() && showWhenLocked
5047 && (win.isDrawnLw() || win.hasAppShownWindows())) {
5048 if (DEBUG_LAYOUT) Slog.v(TAG,
5049 "Setting mHideLockScreen to true by win " + win);
5050 mHideLockScreen = true;
5051 mForceStatusBarFromKeyguard = false;
5053 if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
5054 mAllowLockscreenWhenOn = true;
5058 if (!mKeyguardHidden && mWinShowWhenLocked != null &&
5059 mWinShowWhenLocked.getAppToken() != win.getAppToken() &&
5060 (attrs.flags & FLAG_SHOW_WHEN_LOCKED) == 0) {
5064 } else if (mTopFullscreenOpaqueWindowState == null && mWinShowWhenLocked == null) {
5065 // No TopFullscreenOpaqueWindow is showing, but we found a SHOW_WHEN_LOCKED window
5066 // that is being hidden in an animation - keep the
5067 // keyguard hidden until the new window shows up and
5068 // we know whether to show the keyguard or not.
5069 if (win.isAnimatingLw() && appWindow && showWhenLocked && mKeyguardHidden) {
5070 mHideLockScreen = true;
5071 mWinShowWhenLocked = win;
5075 final boolean reallyVisible = win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw();
5077 // Voice interaction overrides both top fullscreen and top docked.
5078 if (reallyVisible && win.getAttrs().type == TYPE_VOICE_INTERACTION) {
5079 if (mTopFullscreenOpaqueWindowState == null) {
5080 mTopFullscreenOpaqueWindowState = win;
5081 if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5082 mTopFullscreenOpaqueOrDimmingWindowState = win;
5085 if (mTopDockedOpaqueWindowState == null) {
5086 mTopDockedOpaqueWindowState = win;
5087 if (mTopDockedOpaqueOrDimmingWindowState == null) {
5088 mTopDockedOpaqueOrDimmingWindowState = win;
5093 // Keep track of the window if it's dimming but not necessarily fullscreen.
5094 if (mTopFullscreenOpaqueOrDimmingWindowState == null && reallyVisible
5095 && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
5096 mTopFullscreenOpaqueOrDimmingWindowState = win;
5099 // We need to keep track of the top "fullscreen" opaque window for the docked stack
5100 // separately, because both the "real fullscreen" opaque window and the one for the docked
5101 // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
5102 if (mTopDockedOpaqueWindowState == null && reallyVisible && appWindow && attached == null
5103 && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
5104 mTopDockedOpaqueWindowState = win;
5105 if (mTopDockedOpaqueOrDimmingWindowState == null) {
5106 mTopDockedOpaqueOrDimmingWindowState = win;
5110 // Also keep track of any windows that are dimming but not necessarily fullscreen in the
5112 if (mTopDockedOpaqueOrDimmingWindowState == null && reallyVisible && win.isDimming()
5113 && stackId == DOCKED_STACK_ID) {
5114 mTopDockedOpaqueOrDimmingWindowState = win;
5118 private boolean isFullscreen(WindowManager.LayoutParams attrs) {
5119 return attrs.x == 0 && attrs.y == 0
5120 && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
5121 && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
5124 /** {@inheritDoc} */
5126 public int finishPostLayoutPolicyLw() {
5127 if (mWinShowWhenLocked != null && mTopFullscreenOpaqueWindowState != null &&
5128 mWinShowWhenLocked.getAppToken() != mTopFullscreenOpaqueWindowState.getAppToken()
5129 && isKeyguardLocked()) {
5130 // A dialog is dismissing the keyguard. Put the wallpaper behind it and hide the
5131 // fullscreen window.
5132 // TODO: Make sure FLAG_SHOW_WALLPAPER is restored when dialog is dismissed. Or not.
5133 mWinShowWhenLocked.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5134 mTopFullscreenOpaqueWindowState.hideLw(false);
5135 mTopFullscreenOpaqueWindowState = mWinShowWhenLocked;
5139 boolean topIsFullscreen = false;
5141 final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
5142 ? mTopFullscreenOpaqueWindowState.getAttrs()
5145 // If we are not currently showing a dream then remember the current
5146 // lockscreen state. We will use this to determine whether the dream
5147 // started while the lockscreen was showing and remember this state
5148 // while the dream is showing.
5149 if (!mShowingDream) {
5150 mDreamingLockscreen = mShowingLockscreen;
5151 if (mDreamingSleepTokenNeeded) {
5152 mDreamingSleepTokenNeeded = false;
5153 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
5156 if (!mDreamingSleepTokenNeeded) {
5157 mDreamingSleepTokenNeeded = true;
5158 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget();
5162 if (mStatusBar != null) {
5163 if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
5164 + " forcefkg=" + mForceStatusBarFromKeyguard
5165 + " top=" + mTopFullscreenOpaqueWindowState);
5166 boolean shouldBeTransparent = mForceStatusBarTransparent
5168 && !mForceStatusBarFromKeyguard;
5169 if (!shouldBeTransparent) {
5170 mStatusBarController.setShowTransparent(false /* transparent */);
5171 } else if (!mStatusBar.isVisibleLw()) {
5172 mStatusBarController.setShowTransparent(true /* transparent */);
5175 WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs();
5176 boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT
5177 && statusBarAttrs.width == MATCH_PARENT;
5178 if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
5179 || statusBarExpanded) {
5180 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
5181 if (mStatusBarController.setBarShowingLw(true)) {
5182 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5184 // Maintain fullscreen layout until incoming animation is complete.
5185 topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
5186 // Transient status bar on the lockscreen is not allowed
5187 if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) {
5188 mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
5189 mLastSystemUiFlags, mLastSystemUiFlags);
5191 if (statusBarExpanded && mNavigationBar != null) {
5192 if (mNavigationBarController.setBarShowingLw(true)) {
5193 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5196 } else if (mTopFullscreenOpaqueWindowState != null) {
5197 final int fl = PolicyControl.getWindowFlags(null, lp);
5199 Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
5200 + " shown position: "
5201 + mTopFullscreenOpaqueWindowState.getShownPositionLw());
5202 Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
5203 + " lp.flags=0x" + Integer.toHexString(fl));
5205 topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
5206 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
5207 // The subtle difference between the window for mTopFullscreenOpaqueWindowState
5208 // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
5209 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the
5211 if (mStatusBarController.isTransientShowing()) {
5212 if (mStatusBarController.setBarShowingLw(true)) {
5213 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5215 } else if (topIsFullscreen
5216 && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)
5217 && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) {
5218 if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
5219 if (mStatusBarController.setBarShowingLw(false)) {
5220 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5222 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
5225 if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
5226 if (mStatusBarController.setBarShowingLw(true)) {
5227 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5233 if (mTopIsFullscreen != topIsFullscreen) {
5234 if (!topIsFullscreen) {
5235 // Force another layout when status bar becomes fully shown.
5236 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5238 mTopIsFullscreen = topIsFullscreen;
5241 // Hide the key guard if a visible window explicitly specifies that it wants to be
5242 // displayed when the screen is locked.
5243 if (mKeyguardDelegate != null && mStatusBar != null) {
5244 if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
5246 if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardSecure) {
5247 mKeyguardHidden = true;
5248 if (setKeyguardOccludedLw(true)) {
5249 changes |= FINISH_LAYOUT_REDO_LAYOUT
5250 | FINISH_LAYOUT_REDO_CONFIG
5251 | FINISH_LAYOUT_REDO_WALLPAPER;
5253 if (mKeyguardDelegate.isShowing()) {
5254 mHandler.post(new Runnable() {
5257 mKeyguardDelegate.keyguardDone(false, false);
5261 } else if (mHideLockScreen) {
5262 mKeyguardHidden = true;
5263 mWinDismissingKeyguard = null;
5264 if (setKeyguardOccludedLw(true)) {
5265 changes |= FINISH_LAYOUT_REDO_LAYOUT
5266 | FINISH_LAYOUT_REDO_CONFIG
5267 | FINISH_LAYOUT_REDO_WALLPAPER;
5269 } else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) {
5270 mKeyguardHidden = false;
5271 final boolean trusted = mKeyguardDelegate.isTrusted();
5273 // No need to un-occlude keyguard - we'll dimiss it right away anyways.
5274 } else if (setKeyguardOccludedLw(false)) {
5275 changes |= FINISH_LAYOUT_REDO_LAYOUT
5276 | FINISH_LAYOUT_REDO_CONFIG
5277 | FINISH_LAYOUT_REDO_WALLPAPER;
5279 if (mDismissKeyguard == DISMISS_KEYGUARD_START) {
5280 // Only launch the next keyguard unlock window once per window.
5281 mHandler.post(new Runnable() {
5284 mKeyguardDelegate.dismiss(trusted /* allowWhileOccluded */);
5289 mWinDismissingKeyguard = null;
5290 mSecureDismissingKeyguard = false;
5291 mKeyguardHidden = false;
5292 if (setKeyguardOccludedLw(false)) {
5293 changes |= FINISH_LAYOUT_REDO_LAYOUT
5294 | FINISH_LAYOUT_REDO_CONFIG
5295 | FINISH_LAYOUT_REDO_WALLPAPER;
5300 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5301 // If the navigation bar has been hidden or shown, we need to do another
5302 // layout pass to update that window.
5303 changes |= FINISH_LAYOUT_REDO_LAYOUT;
5306 // update since mAllowLockscreenWhenOn might have changed
5307 updateLockScreenTimeout();
5312 * Updates the occluded state of the Keyguard.
5314 * @return Whether the flags have changed and we have to redo the layout.
5316 private boolean setKeyguardOccludedLw(boolean isOccluded) {
5317 boolean wasOccluded = mKeyguardOccluded;
5318 boolean showing = mKeyguardDelegate.isShowing();
5319 if (wasOccluded && !isOccluded && showing) {
5320 mKeyguardOccluded = false;
5321 mKeyguardDelegate.setOccluded(false);
5322 mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
5323 if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
5324 mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5327 } else if (!wasOccluded && isOccluded && showing) {
5328 mKeyguardOccluded = true;
5329 mKeyguardDelegate.setOccluded(true);
5330 mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
5331 mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
5338 private boolean isStatusBarKeyguard() {
5339 return mStatusBar != null
5340 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
5344 public boolean allowAppAnimationsLw() {
5345 if (isStatusBarKeyguard() || mShowingDream) {
5346 // If keyguard or dreams is currently visible, no reason to animate behind it.
5353 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
5354 mFocusedWindow = newFocus;
5355 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5356 // If the navigation bar has been hidden or shown, we need to do another
5357 // layout pass to update that window.
5358 return FINISH_LAYOUT_REDO_LAYOUT;
5363 /** {@inheritDoc} */
5365 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
5366 // lid changed state
5367 final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
5368 if (newLidState == mLidState) {
5372 mLidState = newLidState;
5373 applyLidSwitchState();
5374 updateRotation(true);
5377 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
5378 "android.policy:LID");
5379 } else if (!mLidControlsSleep) {
5380 mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
5385 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
5386 int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
5387 if (mCameraLensCoverState == lensCoverState) {
5390 if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
5391 lensCoverState == CAMERA_LENS_UNCOVERED) {
5393 final boolean keyguardActive = mKeyguardDelegate == null ? false :
5394 mKeyguardDelegate.isShowing();
5395 if (keyguardActive) {
5396 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
5398 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
5400 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
5401 "android.policy:CAMERA_COVER");
5402 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
5404 mCameraLensCoverState = lensCoverState;
5407 void setHdmiPlugged(boolean plugged) {
5408 if (mHdmiPlugged != plugged) {
5409 mHdmiPlugged = plugged;
5410 updateRotation(true, true);
5411 Intent intent = new Intent(ACTION_HDMI_PLUGGED);
5412 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
5413 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
5414 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
5418 void initializeHdmiState() {
5419 boolean plugged = false;
5420 // watch for HDMI plug messages if the hdmi switch exists
5421 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
5422 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
5424 final String filename = "/sys/class/switch/hdmi/state";
5425 FileReader reader = null;
5427 reader = new FileReader(filename);
5428 char[] buf = new char[15];
5429 int n = reader.read(buf);
5431 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
5433 } catch (IOException ex) {
5434 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5435 } catch (NumberFormatException ex) {
5436 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5438 if (reader != null) {
5441 } catch (IOException ex) {
5446 // This dance forces the code in setHdmiPlugged to run.
5447 // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
5448 mHdmiPlugged = !plugged;
5449 setHdmiPlugged(!mHdmiPlugged);
5452 final Object mScreenshotLock = new Object();
5453 ServiceConnection mScreenshotConnection = null;
5455 final Runnable mScreenshotTimeout = new Runnable() {
5456 @Override public void run() {
5457 synchronized (mScreenshotLock) {
5458 if (mScreenshotConnection != null) {
5459 mContext.unbindService(mScreenshotConnection);
5460 mScreenshotConnection = null;
5461 notifyScreenshotError();
5467 // Assume this is called from the Handler thread.
5468 private void takeScreenshot(final int screenshotType) {
5469 synchronized (mScreenshotLock) {
5470 if (mScreenshotConnection != null) {
5473 final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
5474 SYSUI_SCREENSHOT_SERVICE);
5475 final Intent serviceIntent = new Intent();
5476 serviceIntent.setComponent(serviceComponent);
5477 ServiceConnection conn = new ServiceConnection() {
5479 public void onServiceConnected(ComponentName name, IBinder service) {
5480 synchronized (mScreenshotLock) {
5481 if (mScreenshotConnection != this) {
5484 Messenger messenger = new Messenger(service);
5485 Message msg = Message.obtain(null, screenshotType);
5486 final ServiceConnection myConn = this;
5487 Handler h = new Handler(mHandler.getLooper()) {
5489 public void handleMessage(Message msg) {
5490 synchronized (mScreenshotLock) {
5491 if (mScreenshotConnection == myConn) {
5492 mContext.unbindService(mScreenshotConnection);
5493 mScreenshotConnection = null;
5494 mHandler.removeCallbacks(mScreenshotTimeout);
5499 msg.replyTo = new Messenger(h);
5500 msg.arg1 = msg.arg2 = 0;
5501 if (mStatusBar != null && mStatusBar.isVisibleLw())
5503 if (mNavigationBar != null && mNavigationBar.isVisibleLw())
5506 messenger.send(msg);
5507 } catch (RemoteException e) {
5513 public void onServiceDisconnected(ComponentName name) {
5514 notifyScreenshotError();
5517 if (mContext.bindServiceAsUser(serviceIntent, conn,
5518 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
5519 UserHandle.CURRENT)) {
5520 mScreenshotConnection = conn;
5521 mHandler.postDelayed(mScreenshotTimeout, 10000);
5527 * Notifies the screenshot service to show an error.
5529 private void notifyScreenshotError() {
5530 // If the service process is killed, then ask it to clean up after itself
5531 final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
5532 SYSUI_SCREENSHOT_ERROR_RECEIVER);
5533 Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
5534 errorIntent.setComponent(errorComponent);
5535 errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
5536 Intent.FLAG_RECEIVER_FOREGROUND);
5537 mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT);
5540 /** {@inheritDoc} */
5542 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
5543 if (!mSystemBooted) {
5544 // If we have not yet booted, don't let key events do anything.
5548 final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
5549 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
5550 final boolean canceled = event.isCanceled();
5551 final int keyCode = event.getKeyCode();
5553 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
5555 // If screen is off then we treat the case where the keyguard is open but hidden
5556 // the same as if it were open and in front.
5557 // This will prevent any keys other than the power button from waking the screen
5558 // when the keyguard is hidden by another activity.
5559 final boolean keyguardActive = (mKeyguardDelegate == null ? false :
5561 isKeyguardShowingAndNotOccluded() :
5562 mKeyguardDelegate.isShowing()));
5565 Log.d(TAG, "interceptKeyTq keycode=" + keyCode
5566 + " interactive=" + interactive + " keyguardActive=" + keyguardActive
5567 + " policyFlags=" + Integer.toHexString(policyFlags));
5570 // Basic policy based on interactive state.
5572 boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
5573 || event.isWakeKey();
5574 if (interactive || (isInjected && !isWakeKey)) {
5575 // When the device is interactive or the key is injected pass the
5576 // key to the application.
5577 result = ACTION_PASS_TO_USER;
5581 // If the screen is awake, but the button pressed was the one that woke the device
5582 // then don't pass it to the application
5583 if (keyCode == mPendingWakeKey && !down) {
5586 // Reset the pending key
5587 mPendingWakeKey = PENDING_KEY_NULL;
5589 } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
5590 // If we're currently dozing with the screen on and the keyguard showing, pass the key
5591 // to the application but preserve its wake key status to make sure we still move
5592 // from dozing to fully interactive if we would normally go from off to fully
5594 result = ACTION_PASS_TO_USER;
5595 // Since we're dispatching the input, reset the pending key
5596 mPendingWakeKey = PENDING_KEY_NULL;
5598 // When the screen is off and the key is not injected, determine whether
5599 // to wake the device but don't pass the key to the application.
5601 if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
5604 // Cache the wake key on down event so we can also avoid sending the up event to the app
5605 if (isWakeKey && down) {
5606 mPendingWakeKey = keyCode;
5610 // If the key would be handled globally, just return the result, don't worry about special
5612 if (isValidGlobalKey(keyCode)
5613 && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
5615 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5620 boolean useHapticFeedback = down
5621 && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
5622 && event.getRepeatCount() == 0;
5624 // Handle special keys.
5626 case KeyEvent.KEYCODE_BACK: {
5628 mBackKeyHandled = false;
5629 if (hasLongPressOnBackBehavior()) {
5630 Message msg = mHandler.obtainMessage(MSG_BACK_LONG_PRESS);
5631 msg.setAsynchronous(true);
5632 mHandler.sendMessageDelayed(msg,
5633 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
5636 boolean handled = mBackKeyHandled;
5638 // Reset back key state
5639 cancelPendingBackKeyAction();
5641 // Don't pass back press to app if we've already handled it
5643 result &= ~ACTION_PASS_TO_USER;
5649 case KeyEvent.KEYCODE_VOLUME_DOWN:
5650 case KeyEvent.KEYCODE_VOLUME_UP:
5651 case KeyEvent.KEYCODE_VOLUME_MUTE: {
5652 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
5654 if (interactive && !mScreenshotChordVolumeDownKeyTriggered
5655 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5656 mScreenshotChordVolumeDownKeyTriggered = true;
5657 mScreenshotChordVolumeDownKeyTime = event.getDownTime();
5658 mScreenshotChordVolumeDownKeyConsumed = false;
5659 cancelPendingPowerKeyAction();
5660 interceptScreenshotChord();
5663 mScreenshotChordVolumeDownKeyTriggered = false;
5664 cancelPendingScreenshotChordAction();
5666 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
5668 if (interactive && !mScreenshotChordVolumeUpKeyTriggered
5669 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5670 mScreenshotChordVolumeUpKeyTriggered = true;
5671 cancelPendingPowerKeyAction();
5672 cancelPendingScreenshotChordAction();
5675 mScreenshotChordVolumeUpKeyTriggered = false;
5676 cancelPendingScreenshotChordAction();
5680 TelecomManager telecomManager = getTelecommService();
5681 if (telecomManager != null) {
5682 if (telecomManager.isRinging()) {
5683 // If an incoming call is ringing, either VOLUME key means
5684 // "silence ringer". We handle these keys here, rather than
5685 // in the InCallScreen, to make sure we'll respond to them
5686 // even if the InCallScreen hasn't come to the foreground yet.
5687 // Look for the DOWN event here, to agree with the "fallback"
5688 // behavior in the InCallScreen.
5689 Log.i(TAG, "interceptKeyBeforeQueueing:"
5690 + " VOLUME key-down while ringing: Silence ringer!");
5692 // Silence the ringer. (It's safe to call this
5693 // even if the ringer has already been silenced.)
5694 telecomManager.silenceRinger();
5696 // And *don't* pass this key thru to the current activity
5697 // (which is probably the InCallScreen.)
5698 result &= ~ACTION_PASS_TO_USER;
5701 if (telecomManager.isInCall()
5702 && (result & ACTION_PASS_TO_USER) == 0) {
5703 // If we are in call but we decided not to pass the key to
5704 // the application, just pass it to the session service.
5706 MediaSessionLegacyHelper.getHelper(mContext)
5707 .sendVolumeKeyEvent(event, false);
5712 if (mUseTvRouting) {
5713 // On TVs, defer special key handlings to
5714 // {@link interceptKeyBeforeDispatching()}.
5715 result |= ACTION_PASS_TO_USER;
5716 } else if ((result & ACTION_PASS_TO_USER) == 0) {
5717 // If we aren't passing to the user and no one else
5718 // handled it send it to the session manager to
5720 MediaSessionLegacyHelper.getHelper(mContext)
5721 .sendVolumeKeyEvent(event, true);
5726 case KeyEvent.KEYCODE_ENDCALL: {
5727 result &= ~ACTION_PASS_TO_USER;
5729 TelecomManager telecomManager = getTelecommService();
5730 boolean hungUp = false;
5731 if (telecomManager != null) {
5732 hungUp = telecomManager.endCall();
5734 if (interactive && !hungUp) {
5735 mEndCallKeyHandled = false;
5736 mHandler.postDelayed(mEndCallLongPress,
5737 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
5739 mEndCallKeyHandled = true;
5742 if (!mEndCallKeyHandled) {
5743 mHandler.removeCallbacks(mEndCallLongPress);
5745 if ((mEndcallBehavior
5746 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
5751 if ((mEndcallBehavior
5752 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
5753 mPowerManager.goToSleep(event.getEventTime(),
5754 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
5763 case KeyEvent.KEYCODE_POWER: {
5764 result &= ~ACTION_PASS_TO_USER;
5765 isWakeKey = false; // wake-up will be handled separately
5767 interceptPowerKeyDown(event, interactive);
5769 interceptPowerKeyUp(event, interactive, canceled);
5774 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
5776 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
5778 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
5780 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
5781 result &= ~ACTION_PASS_TO_USER;
5782 interceptSystemNavigationKey(event);
5786 case KeyEvent.KEYCODE_SLEEP: {
5787 result &= ~ACTION_PASS_TO_USER;
5789 if (!mPowerManager.isInteractive()) {
5790 useHapticFeedback = false; // suppress feedback if already non-interactive
5793 sleepPress(event.getEventTime());
5795 sleepRelease(event.getEventTime());
5800 case KeyEvent.KEYCODE_SOFT_SLEEP: {
5801 result &= ~ACTION_PASS_TO_USER;
5804 mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
5809 case KeyEvent.KEYCODE_WAKEUP: {
5810 result &= ~ACTION_PASS_TO_USER;
5815 case KeyEvent.KEYCODE_MEDIA_PLAY:
5816 case KeyEvent.KEYCODE_MEDIA_PAUSE:
5817 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
5818 case KeyEvent.KEYCODE_HEADSETHOOK:
5819 case KeyEvent.KEYCODE_MUTE:
5820 case KeyEvent.KEYCODE_MEDIA_STOP:
5821 case KeyEvent.KEYCODE_MEDIA_NEXT:
5822 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
5823 case KeyEvent.KEYCODE_MEDIA_REWIND:
5824 case KeyEvent.KEYCODE_MEDIA_RECORD:
5825 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
5826 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
5827 if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
5828 // If the global session is active pass all media keys to it
5829 // instead of the active window.
5830 result &= ~ACTION_PASS_TO_USER;
5832 if ((result & ACTION_PASS_TO_USER) == 0) {
5833 // Only do this if we would otherwise not pass it to the user. In that
5834 // case, the PhoneWindow class will do the same thing, except it will
5835 // only do it if the showing app doesn't process the key on its own.
5836 // Note that we need to make a copy of the key event here because the
5837 // original key event will be recycled when we return.
5838 mBroadcastWakeLock.acquire();
5839 Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
5840 new KeyEvent(event));
5841 msg.setAsynchronous(true);
5847 case KeyEvent.KEYCODE_CALL: {
5849 TelecomManager telecomManager = getTelecommService();
5850 if (telecomManager != null) {
5851 if (telecomManager.isRinging()) {
5852 Log.i(TAG, "interceptKeyBeforeQueueing:"
5853 + " CALL key-down while ringing: Answer the call!");
5854 telecomManager.acceptRingingCall();
5856 // And *don't* pass this key thru to the current activity
5857 // (which is presumably the InCallScreen.)
5858 result &= ~ACTION_PASS_TO_USER;
5864 case KeyEvent.KEYCODE_VOICE_ASSIST: {
5865 // Only do this if we would otherwise not pass it to the user. In that case,
5866 // interceptKeyBeforeDispatching would apply a similar but different policy in
5867 // order to invoke voice assist actions. Note that we need to make a copy of the
5868 // key event here because the original key event will be recycled when we return.
5869 if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
5870 mBroadcastWakeLock.acquire();
5871 Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
5872 keyguardActive ? 1 : 0, 0);
5873 msg.setAsynchronous(true);
5878 case KeyEvent.KEYCODE_WINDOW: {
5879 if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
5880 if (mTvPictureInPictureVisible) {
5881 // Consumes the key only if picture-in-picture is visible
5882 // to show picture-in-picture control menu.
5883 // This gives a chance to the foreground activity
5884 // to customize PIP key behavior.
5886 showTvPictureInPictureMenu(event);
5888 result &= ~ACTION_PASS_TO_USER;
5895 if (useHapticFeedback) {
5896 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
5900 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5907 * Handle statusbar expansion events.
5910 private void interceptSystemNavigationKey(KeyEvent event) {
5911 if (event.getAction() == KeyEvent.ACTION_UP && areSystemNavigationKeysEnabled()) {
5912 IStatusBarService sbar = getStatusBarService();
5915 sbar.handleSystemNavigationKey(event.getKeyCode());
5916 } catch (RemoteException e1) {
5917 // oops, no statusbar. Ignore event.
5924 * Returns true if the key can have global actions attached to it.
5925 * We reserve all power management keys for the system since they require
5926 * very careful handling.
5928 private static boolean isValidGlobalKey(int keyCode) {
5930 case KeyEvent.KEYCODE_POWER:
5931 case KeyEvent.KEYCODE_WAKEUP:
5932 case KeyEvent.KEYCODE_SLEEP:
5940 * When the screen is off we ignore some keys that might otherwise typically
5941 * be considered wake keys. We filter them out here.
5943 * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
5944 * is always considered a wake key.
5946 private boolean isWakeKeyWhenScreenOff(int keyCode) {
5948 // ignore volume keys unless docked
5949 case KeyEvent.KEYCODE_VOLUME_UP:
5950 case KeyEvent.KEYCODE_VOLUME_DOWN:
5951 case KeyEvent.KEYCODE_VOLUME_MUTE:
5952 return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
5954 // ignore media and camera keys
5955 case KeyEvent.KEYCODE_MUTE:
5956 case KeyEvent.KEYCODE_HEADSETHOOK:
5957 case KeyEvent.KEYCODE_MEDIA_PLAY:
5958 case KeyEvent.KEYCODE_MEDIA_PAUSE:
5959 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
5960 case KeyEvent.KEYCODE_MEDIA_STOP:
5961 case KeyEvent.KEYCODE_MEDIA_NEXT:
5962 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
5963 case KeyEvent.KEYCODE_MEDIA_REWIND:
5964 case KeyEvent.KEYCODE_MEDIA_RECORD:
5965 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
5966 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
5967 case KeyEvent.KEYCODE_CAMERA:
5974 /** {@inheritDoc} */
5976 public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
5977 if ((policyFlags & FLAG_WAKE) != 0) {
5978 if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
5979 "android.policy:MOTION")) {
5984 if (shouldDispatchInputWhenNonInteractive(null)) {
5985 return ACTION_PASS_TO_USER;
5988 // If we have not passed the action up and we are in theater mode without dreaming,
5989 // there will be no dream to intercept the touch and wake into ambient. The device should
5990 // wake up in this case.
5991 if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
5992 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
5993 "android.policy:MOTION");
5999 private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
6000 final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
6002 if (displayOff && !mHasFeatureWatch) {
6006 // Send events to keyguard while the screen is on and it's showing.
6007 if (isKeyguardShowingAndNotOccluded() && !displayOff) {
6011 // Watches handle BACK specially
6012 if (mHasFeatureWatch
6014 && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
6015 || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
6019 // Send events to a dozing dream even if the screen is off since the dream
6020 // is in control of the state of the screen.
6021 IDreamManager dreamManager = getDreamManager();
6024 if (dreamManager != null && dreamManager.isDreaming()) {
6027 } catch (RemoteException e) {
6028 Slog.e(TAG, "RemoteException when checking if dreaming", e);
6031 // Otherwise, consume events since the user can't see what is being
6036 private void dispatchDirectAudioEvent(KeyEvent event) {
6037 if (event.getAction() != KeyEvent.ACTION_DOWN) {
6040 int keyCode = event.getKeyCode();
6041 int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
6042 | AudioManager.FLAG_FROM_KEY;
6043 String pkgName = mContext.getOpPackageName();
6045 case KeyEvent.KEYCODE_VOLUME_UP:
6047 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
6048 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6049 } catch (RemoteException e) {
6050 Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
6053 case KeyEvent.KEYCODE_VOLUME_DOWN:
6055 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
6056 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6057 } catch (RemoteException e) {
6058 Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
6061 case KeyEvent.KEYCODE_VOLUME_MUTE:
6063 if (event.getRepeatCount() == 0) {
6064 getAudioService().adjustSuggestedStreamVolume(
6065 AudioManager.ADJUST_TOGGLE_MUTE,
6066 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6068 } catch (RemoteException e) {
6069 Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
6075 void dispatchMediaKeyWithWakeLock(KeyEvent event) {
6077 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
6080 if (mHavePendingMediaKeyRepeatWithWakeLock) {
6082 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
6085 mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
6086 mHavePendingMediaKeyRepeatWithWakeLock = false;
6087 mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
6090 dispatchMediaKeyWithWakeLockToAudioService(event);
6092 if (event.getAction() == KeyEvent.ACTION_DOWN
6093 && event.getRepeatCount() == 0) {
6094 mHavePendingMediaKeyRepeatWithWakeLock = true;
6096 Message msg = mHandler.obtainMessage(
6097 MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
6098 msg.setAsynchronous(true);
6099 mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
6101 mBroadcastWakeLock.release();
6105 void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
6106 mHavePendingMediaKeyRepeatWithWakeLock = false;
6108 KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
6109 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6111 Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
6114 dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
6115 mBroadcastWakeLock.release();
6118 void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
6119 if (ActivityManagerNative.isSystemReady()) {
6120 MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
6124 void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
6125 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
6126 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
6129 dic.exitIdle("voice-search");
6130 } catch (RemoteException e) {
6133 Intent voiceIntent =
6134 new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
6135 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
6136 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
6137 mBroadcastWakeLock.release();
6140 BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
6142 public void onReceive(Context context, Intent intent) {
6143 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
6144 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6145 Intent.EXTRA_DOCK_STATE_UNDOCKED);
6148 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
6149 ServiceManager.getService(Context.UI_MODE_SERVICE));
6150 mUiMode = uiModeService.getCurrentModeType();
6151 } catch (RemoteException e) {
6154 updateRotation(true);
6155 synchronized (mLock) {
6156 updateOrientationListenerLp();
6161 BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
6163 public void onReceive(Context context, Intent intent) {
6164 if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
6165 if (mKeyguardDelegate != null) {
6166 mKeyguardDelegate.onDreamingStarted();
6168 } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
6169 if (mKeyguardDelegate != null) {
6170 mKeyguardDelegate.onDreamingStopped();
6176 BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
6178 public void onReceive(Context context, Intent intent) {
6179 if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
6180 // tickle the settings observer: this first ensures that we're
6181 // observing the relevant settings for the newly-active user,
6182 // and then updates our own bookkeeping based on the now-
6184 mSettingsObserver.onChange(false);
6186 // force a re-application of focused window sysui visibility.
6187 // the window may never have been shown for this user
6188 // e.g. the keyguard when going through the new-user setup flow
6189 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6190 mLastSystemUiFlags = 0;
6191 updateSystemUiVisibilityLw();
6197 private final Runnable mHiddenNavPanic = new Runnable() {
6200 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6201 if (!isUserSetupComplete()) {
6202 // Swipe-up for navigation bar is disabled during setup
6205 mPendingPanicGestureUptime = SystemClock.uptimeMillis();
6206 if (!isNavBarEmpty(mLastSystemUiFlags)) {
6207 mNavigationBarController.showTransient();
6213 private void requestTransientBars(WindowState swipeTarget) {
6214 synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6215 if (!isUserSetupComplete()) {
6216 // Swipe-up for navigation bar is disabled during setup
6219 boolean sb = mStatusBarController.checkShowTransientBarLw();
6220 boolean nb = mNavigationBarController.checkShowTransientBarLw()
6221 && !isNavBarEmpty(mLastSystemUiFlags);
6223 // Don't show status bar when swiping on already visible navigation bar
6224 if (!nb && swipeTarget == mNavigationBar) {
6225 if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
6228 if (sb) mStatusBarController.showTransient();
6229 if (nb) mNavigationBarController.showTransient();
6230 mImmersiveModeConfirmation.confirmCurrentPrompt();
6231 updateSystemUiVisibilityLw();
6236 // Called on the PowerManager's Notifier thread.
6238 public void startedGoingToSleep(int why) {
6239 if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
6240 mCameraGestureTriggeredDuringGoingToSleep = false;
6241 mGoingToSleep = true;
6242 if (mKeyguardDelegate != null) {
6243 mKeyguardDelegate.onStartedGoingToSleep(why);
6247 // Called on the PowerManager's Notifier thread.
6249 public void finishedGoingToSleep(int why) {
6250 EventLog.writeEvent(70000, 0);
6251 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
6252 MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
6254 mGoingToSleep = false;
6256 // We must get this work done here because the power manager will drop
6257 // the wake lock and let the system suspend once this function returns.
6258 synchronized (mLock) {
6260 updateWakeGestureListenerLp();
6261 updateOrientationListenerLp();
6262 updateLockScreenTimeout();
6264 if (mKeyguardDelegate != null) {
6265 mKeyguardDelegate.onFinishedGoingToSleep(why,
6266 mCameraGestureTriggeredDuringGoingToSleep);
6268 mCameraGestureTriggeredDuringGoingToSleep = false;
6271 // Called on the PowerManager's Notifier thread.
6273 public void startedWakingUp() {
6274 EventLog.writeEvent(70000, 1);
6275 if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
6277 // Since goToSleep performs these functions synchronously, we must
6278 // do the same here. We cannot post this work to a handler because
6279 // that might cause it to become reordered with respect to what
6280 // may happen in a future call to goToSleep.
6281 synchronized (mLock) {
6284 updateWakeGestureListenerLp();
6285 updateOrientationListenerLp();
6286 updateLockScreenTimeout();
6289 if (mKeyguardDelegate != null) {
6290 mKeyguardDelegate.onStartedWakingUp();
6294 // Called on the PowerManager's Notifier thread.
6296 public void finishedWakingUp() {
6297 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
6300 private void wakeUpFromPowerKey(long eventTime) {
6301 wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
6304 private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
6305 final boolean theaterModeEnabled = isTheaterModeEnabled();
6306 if (!wakeInTheaterMode && theaterModeEnabled) {
6310 if (theaterModeEnabled) {
6311 Settings.Global.putInt(mContext.getContentResolver(),
6312 Settings.Global.THEATER_MODE_ON, 0);
6315 mPowerManager.wakeUp(wakeTime, reason);
6319 private void finishKeyguardDrawn() {
6320 synchronized (mLock) {
6321 if (!mScreenOnEarly || mKeyguardDrawComplete) {
6322 return; // We are not awake yet or we have already informed of this event.
6325 mKeyguardDrawComplete = true;
6326 if (mKeyguardDelegate != null) {
6327 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6329 mWindowManagerDrawComplete = false;
6332 // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
6333 // as well as enabling the orientation change logic/sensor.
6334 mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
6335 WAITING_FOR_DRAWN_TIMEOUT);
6338 // Called on the DisplayManager's DisplayPowerController thread.
6340 public void screenTurnedOff() {
6341 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
6343 updateScreenOffSleepToken(true);
6344 synchronized (mLock) {
6345 mScreenOnEarly = false;
6346 mScreenOnFully = false;
6347 mKeyguardDrawComplete = false;
6348 mWindowManagerDrawComplete = false;
6349 mScreenOnListener = null;
6350 updateOrientationListenerLp();
6352 if (mKeyguardDelegate != null) {
6353 mKeyguardDelegate.onScreenTurnedOff();
6358 // Called on the DisplayManager's DisplayPowerController thread.
6360 public void screenTurningOn(final ScreenOnListener screenOnListener) {
6361 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
6363 updateScreenOffSleepToken(false);
6364 synchronized (mLock) {
6365 mScreenOnEarly = true;
6366 mScreenOnFully = false;
6367 mKeyguardDrawComplete = false;
6368 mWindowManagerDrawComplete = false;
6369 mScreenOnListener = screenOnListener;
6371 if (mKeyguardDelegate != null) {
6372 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6373 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
6374 mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
6376 if (DEBUG_WAKEUP) Slog.d(TAG,
6377 "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
6378 finishKeyguardDrawn();
6383 // Called on the DisplayManager's DisplayPowerController thread.
6385 public void screenTurnedOn() {
6386 synchronized (mLock) {
6387 if (mKeyguardDelegate != null) {
6388 mKeyguardDelegate.onScreenTurnedOn();
6393 private void finishWindowsDrawn() {
6394 synchronized (mLock) {
6395 if (!mScreenOnEarly || mWindowManagerDrawComplete) {
6396 return; // Screen is not turned on or we did already handle this case earlier.
6399 mWindowManagerDrawComplete = true;
6402 finishScreenTurningOn();
6405 private void finishScreenTurningOn() {
6406 synchronized (mLock) {
6407 // We have just finished drawing screen content. Since the orientation listener
6408 // gets only installed when all windows are drawn, we try to install it again.
6409 updateOrientationListenerLp();
6411 final ScreenOnListener listener;
6412 final boolean enableScreen;
6413 synchronized (mLock) {
6414 if (DEBUG_WAKEUP) Slog.d(TAG,
6415 "finishScreenTurningOn: mAwake=" + mAwake
6416 + ", mScreenOnEarly=" + mScreenOnEarly
6417 + ", mScreenOnFully=" + mScreenOnFully
6418 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
6419 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
6421 if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
6422 || (mAwake && !mKeyguardDrawComplete)) {
6423 return; // spurious or not ready yet
6426 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
6427 listener = mScreenOnListener;
6428 mScreenOnListener = null;
6429 mScreenOnFully = true;
6431 // Remember the first time we draw the keyguard so we know when we're done with
6432 // the main part of booting and can enable the screen and hide boot messages.
6433 if (!mKeyguardDrawnOnce && mAwake) {
6434 mKeyguardDrawnOnce = true;
6435 enableScreen = true;
6436 if (mBootMessageNeedsHiding) {
6437 mBootMessageNeedsHiding = false;
6441 enableScreen = false;
6445 if (listener != null) {
6446 listener.onScreenOn();
6451 mWindowManager.enableScreenIfNeeded();
6452 } catch (RemoteException unhandled) {
6457 private void handleHideBootMessage() {
6458 synchronized (mLock) {
6459 if (!mKeyguardDrawnOnce) {
6460 mBootMessageNeedsHiding = true;
6461 return; // keyguard hasn't drawn the first time yet, not done booting
6465 if (mBootMsgDialog != null) {
6466 if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
6467 mBootMsgDialog.dismiss();
6468 mBootMsgDialog = null;
6473 public boolean isScreenOn() {
6474 return mScreenOnFully;
6477 /** {@inheritDoc} */
6479 public void enableKeyguard(boolean enabled) {
6480 if (mKeyguardDelegate != null) {
6481 mKeyguardDelegate.setKeyguardEnabled(enabled);
6485 /** {@inheritDoc} */
6487 public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
6488 if (mKeyguardDelegate != null) {
6489 mKeyguardDelegate.verifyUnlock(callback);
6493 private boolean isKeyguardShowingAndNotOccluded() {
6494 if (mKeyguardDelegate == null) return false;
6495 return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
6498 /** {@inheritDoc} */
6500 public boolean isKeyguardLocked() {
6501 return keyguardOn();
6504 /** {@inheritDoc} */
6506 public boolean isKeyguardSecure(int userId) {
6507 if (mKeyguardDelegate == null) return false;
6508 return mKeyguardDelegate.isSecure(userId);
6511 /** {@inheritDoc} */
6513 public boolean isKeyguardShowingOrOccluded() {
6514 return mKeyguardDelegate == null ? false : mKeyguardDelegate.isShowing();
6517 /** {@inheritDoc} */
6519 public boolean inKeyguardRestrictedKeyInputMode() {
6520 if (mKeyguardDelegate == null) return false;
6521 return mKeyguardDelegate.isInputRestricted();
6525 public void dismissKeyguardLw() {
6526 if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
6527 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
6528 mHandler.post(new Runnable() {
6531 // ask the keyguard to prompt the user to authenticate if necessary
6532 mKeyguardDelegate.dismiss(false /* allowWhileOccluded */);
6539 public void notifyActivityDrawnForKeyguardLw() {
6540 if (mKeyguardDelegate != null) {
6541 mHandler.post(new Runnable() {
6544 mKeyguardDelegate.onActivityDrawn();
6551 public boolean isKeyguardDrawnLw() {
6552 synchronized (mLock) {
6553 return mKeyguardDrawnOnce;
6558 public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
6559 if (mKeyguardDelegate != null) {
6560 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
6561 mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
6566 public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6568 outInsets.setEmpty();
6570 // Navigation bar and status bar.
6571 getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
6572 if (mStatusBar != null) {
6573 outInsets.top = mStatusBarHeight;
6578 public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6580 outInsets.setEmpty();
6582 // Only navigation bar
6583 if (mNavigationBar != null) {
6584 int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
6585 if (position == NAV_BAR_BOTTOM) {
6586 outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
6587 } else if (position == NAV_BAR_RIGHT) {
6588 outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
6589 } else if (position == NAV_BAR_LEFT) {
6590 outInsets.left = getNavigationBarWidth(displayRotation, mUiMode);
6596 public boolean isNavBarForcedShownLw(WindowState windowState) {
6597 return mForceShowSystemBars;
6601 public boolean isDockSideAllowed(int dockSide) {
6603 // We do not allow all dock sides at which the navigation bar touches the docked stack.
6604 if (!mNavigationBarCanMove) {
6605 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT;
6607 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT;
6611 void sendCloseSystemWindows() {
6612 PhoneWindow.sendCloseSystemWindows(mContext, null);
6615 void sendCloseSystemWindows(String reason) {
6616 PhoneWindow.sendCloseSystemWindows(mContext, reason);
6620 public int rotationForOrientationLw(int orientation, int lastRotation) {
6622 Slog.v(TAG, "rotationForOrientationLw(orient="
6623 + orientation + ", last=" + lastRotation
6624 + "); user=" + mUserRotation + " "
6625 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
6626 ? "USER_ROTATION_LOCKED" : "")
6630 if (mForceDefaultOrientation) {
6631 return Surface.ROTATION_0;
6634 synchronized (mLock) {
6635 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
6636 if (sensorRotation < 0) {
6637 sensorRotation = lastRotation;
6640 final int preferredRotation;
6641 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
6642 // Ignore sensor when lid switch is open and rotation is forced.
6643 preferredRotation = mLidOpenRotation;
6644 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
6645 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
6646 // Ignore sensor when in car dock unless explicitly enabled.
6647 // This case can override the behavior of NOSENSOR, and can also
6648 // enable 180 degree rotation while docked.
6649 preferredRotation = mCarDockEnablesAccelerometer
6650 ? sensorRotation : mCarDockRotation;
6651 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
6652 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
6653 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
6654 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
6655 // Ignore sensor when in desk dock unless explicitly enabled.
6656 // This case can override the behavior of NOSENSOR, and can also
6657 // enable 180 degree rotation while docked.
6658 preferredRotation = mDeskDockEnablesAccelerometer
6659 ? sensorRotation : mDeskDockRotation;
6660 } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
6661 // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
6662 // Note that the dock orientation overrides the HDMI orientation.
6663 preferredRotation = mDemoHdmiRotation;
6664 } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
6665 && mUndockedHdmiRotation >= 0) {
6666 // Ignore sensor when plugged into HDMI and an undocked orientation has
6667 // been specified in the configuration (only for legacy devices without
6668 // full multi-display support).
6669 // Note that the dock orientation overrides the HDMI orientation.
6670 preferredRotation = mUndockedHdmiRotation;
6671 } else if (mDemoRotationLock) {
6672 // Ignore sensor when demo rotation lock is enabled.
6673 // Note that the dock orientation and HDMI rotation lock override this.
6674 preferredRotation = mDemoRotation;
6675 } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
6676 // Application just wants to remain locked in the last rotation.
6677 preferredRotation = lastRotation;
6678 } else if (!mSupportAutoRotation) {
6679 // If we don't support auto-rotation then bail out here and ignore
6680 // the sensor and any rotation lock settings.
6681 preferredRotation = -1;
6682 } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
6683 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
6684 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
6685 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
6686 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
6687 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
6688 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
6689 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6690 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
6691 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
6692 // Otherwise, use sensor only if requested by the application or enabled
6693 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR.
6694 if (mAllowAllRotations < 0) {
6695 // Can't read this during init() because the context doesn't
6696 // have display metrics at that time so we cannot determine
6697 // tablet vs. phone then.
6698 mAllowAllRotations = mContext.getResources().getBoolean(
6699 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
6701 if (sensorRotation != Surface.ROTATION_180
6702 || mAllowAllRotations == 1
6703 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6704 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
6705 preferredRotation = sensorRotation;
6707 preferredRotation = lastRotation;
6709 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
6710 && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
6711 // Apply rotation lock. Does not apply to NOSENSOR.
6712 // The idea is that the user rotation expresses a weak preference for the direction
6713 // of gravity and as NOSENSOR is never affected by gravity, then neither should
6714 // NOSENSOR be affected by rotation lock (although it will be affected by docks).
6715 preferredRotation = mUserRotation;
6717 // No overriding preference.
6718 // We will do exactly what the application asked us to do.
6719 preferredRotation = -1;
6722 switch (orientation) {
6723 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6724 // Return portrait unless overridden.
6725 if (isAnyPortrait(preferredRotation)) {
6726 return preferredRotation;
6728 return mPortraitRotation;
6730 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6731 // Return landscape unless overridden.
6732 if (isLandscapeOrSeascape(preferredRotation)) {
6733 return preferredRotation;
6735 return mLandscapeRotation;
6737 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6738 // Return reverse portrait unless overridden.
6739 if (isAnyPortrait(preferredRotation)) {
6740 return preferredRotation;
6742 return mUpsideDownRotation;
6744 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6745 // Return seascape unless overridden.
6746 if (isLandscapeOrSeascape(preferredRotation)) {
6747 return preferredRotation;
6749 return mSeascapeRotation;
6751 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6752 case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
6753 // Return either landscape rotation.
6754 if (isLandscapeOrSeascape(preferredRotation)) {
6755 return preferredRotation;
6757 if (isLandscapeOrSeascape(lastRotation)) {
6758 return lastRotation;
6760 return mLandscapeRotation;
6762 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6763 case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
6764 // Return either portrait rotation.
6765 if (isAnyPortrait(preferredRotation)) {
6766 return preferredRotation;
6768 if (isAnyPortrait(lastRotation)) {
6769 return lastRotation;
6771 return mPortraitRotation;
6774 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
6775 // just return the preferred orientation we already calculated.
6776 if (preferredRotation >= 0) {
6777 return preferredRotation;
6779 return Surface.ROTATION_0;
6785 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
6786 switch (orientation) {
6787 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6788 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6789 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6790 return isAnyPortrait(rotation);
6792 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6793 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6794 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6795 return isLandscapeOrSeascape(rotation);
6803 public void setRotationLw(int rotation) {
6804 mOrientationListener.setCurrentRotation(rotation);
6807 private boolean isLandscapeOrSeascape(int rotation) {
6808 return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
6811 private boolean isAnyPortrait(int rotation) {
6812 return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
6816 public int getUserRotationMode() {
6817 return Settings.System.getIntForUser(mContext.getContentResolver(),
6818 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
6819 WindowManagerPolicy.USER_ROTATION_FREE :
6820 WindowManagerPolicy.USER_ROTATION_LOCKED;
6823 // User rotation: to be used when all else fails in assigning an orientation to the device
6825 public void setUserRotationMode(int mode, int rot) {
6826 ContentResolver res = mContext.getContentResolver();
6828 // mUserRotationMode and mUserRotation will be assigned by the content observer
6829 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
6830 Settings.System.putIntForUser(res,
6831 Settings.System.USER_ROTATION,
6833 UserHandle.USER_CURRENT);
6834 Settings.System.putIntForUser(res,
6835 Settings.System.ACCELEROMETER_ROTATION,
6837 UserHandle.USER_CURRENT);
6839 Settings.System.putIntForUser(res,
6840 Settings.System.ACCELEROMETER_ROTATION,
6842 UserHandle.USER_CURRENT);
6847 public void setSafeMode(boolean safeMode) {
6848 mSafeMode = safeMode;
6849 performHapticFeedbackLw(null, safeMode
6850 ? HapticFeedbackConstants.SAFE_MODE_ENABLED
6851 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
6854 static long[] getLongIntArray(Resources r, int resid) {
6855 int[] ar = r.getIntArray(resid);
6859 long[] out = new long[ar.length];
6860 for (int i=0; i<ar.length; i++) {
6866 /** {@inheritDoc} */
6868 public void systemReady() {
6869 mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
6870 mKeyguardDelegate.onSystemReady();
6872 readCameraLensCoverState();
6874 boolean bindKeyguardNow;
6875 synchronized (mLock) {
6876 updateOrientationListenerLp();
6877 mSystemReady = true;
6878 mHandler.post(new Runnable() {
6885 bindKeyguardNow = mDeferBindKeyguard;
6886 if (bindKeyguardNow) {
6887 // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now.
6888 mDeferBindKeyguard = false;
6892 if (bindKeyguardNow) {
6893 mKeyguardDelegate.bindService(mContext);
6894 mKeyguardDelegate.onBootCompleted();
6896 mSystemGestures.systemReady();
6897 mImmersiveModeConfirmation.systemReady();
6900 /** {@inheritDoc} */
6902 public void systemBooted() {
6903 boolean bindKeyguardNow = false;
6904 synchronized (mLock) {
6905 // Time to bind Keyguard; take care to only bind it once, either here if ready or
6906 // in systemReady if not.
6907 if (mKeyguardDelegate != null) {
6908 bindKeyguardNow = true;
6910 // Because mKeyguardDelegate is null, we know that the synchronized block in
6911 // systemReady didn't run yet and setting this will actually have an effect.
6912 mDeferBindKeyguard = true;
6915 if (bindKeyguardNow) {
6916 mKeyguardDelegate.bindService(mContext);
6917 mKeyguardDelegate.onBootCompleted();
6919 synchronized (mLock) {
6920 mSystemBooted = true;
6923 screenTurningOn(null);
6927 ProgressDialog mBootMsgDialog = null;
6929 /** {@inheritDoc} */
6931 public void showBootMessage(final CharSequence msg, final boolean always) {
6932 mHandler.post(new Runnable() {
6933 @Override public void run() {
6934 if (mBootMsgDialog == null) {
6936 if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) {
6937 theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
6942 mBootMsgDialog = new ProgressDialog(mContext, theme) {
6943 // This dialog will consume all events coming in to
6944 // it, to avoid it trying to do things too early in boot.
6945 @Override public boolean dispatchKeyEvent(KeyEvent event) {
6948 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
6951 @Override public boolean dispatchTouchEvent(MotionEvent ev) {
6954 @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
6957 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
6960 @Override public boolean dispatchPopulateAccessibilityEvent(
6961 AccessibilityEvent event) {
6965 if (mContext.getPackageManager().isUpgrade()) {
6966 mBootMsgDialog.setTitle(R.string.android_upgrading_title);
6968 mBootMsgDialog.setTitle(R.string.android_start_title);
6970 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
6971 mBootMsgDialog.setIndeterminate(true);
6972 mBootMsgDialog.getWindow().setType(
6973 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
6974 mBootMsgDialog.getWindow().addFlags(
6975 WindowManager.LayoutParams.FLAG_DIM_BEHIND
6976 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
6977 mBootMsgDialog.getWindow().setDimAmount(1);
6978 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
6979 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
6980 mBootMsgDialog.getWindow().setAttributes(lp);
6981 mBootMsgDialog.setCancelable(false);
6982 mBootMsgDialog.show();
6984 mBootMsgDialog.setMessage(msg);
6989 /** {@inheritDoc} */
6991 public void hideBootMessages() {
6992 mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
6995 /** {@inheritDoc} */
6997 public void userActivity() {
6998 // ***************************************
6999 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
7000 // ***************************************
7001 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
7002 // WITH ITS LOCKS HELD.
7004 // This code must be VERY careful about the locks
7006 // In fact, the current code acquires way too many,
7007 // and probably has lurking deadlocks.
7009 synchronized (mScreenLockTimeout) {
7010 if (mLockScreenTimerActive) {
7012 mHandler.removeCallbacks(mScreenLockTimeout);
7013 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7018 class ScreenLockTimeout implements Runnable {
7023 synchronized (this) {
7024 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
7025 if (mKeyguardDelegate != null) {
7026 mKeyguardDelegate.doKeyguardTimeout(options);
7028 mLockScreenTimerActive = false;
7033 public void setLockOptions(Bundle options) {
7034 this.options = options;
7038 ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
7041 public void lockNow(Bundle options) {
7042 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
7043 mHandler.removeCallbacks(mScreenLockTimeout);
7044 if (options != null) {
7045 // In case multiple calls are made to lockNow, we don't wipe out the options
7046 // until the runnable actually executes.
7047 mScreenLockTimeout.setLockOptions(options);
7049 mHandler.post(mScreenLockTimeout);
7052 private void updateLockScreenTimeout() {
7053 synchronized (mScreenLockTimeout) {
7054 boolean enable = (mAllowLockscreenWhenOn && mAwake &&
7055 mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
7056 if (mLockScreenTimerActive != enable) {
7058 if (localLOGV) Log.v(TAG, "setting lockscreen timer");
7059 mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
7060 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7062 if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
7063 mHandler.removeCallbacks(mScreenLockTimeout);
7065 mLockScreenTimerActive = enable;
7070 private void updateDreamingSleepToken(boolean acquire) {
7072 if (mDreamingSleepToken == null) {
7073 mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream");
7076 if (mDreamingSleepToken != null) {
7077 mDreamingSleepToken.release();
7078 mDreamingSleepToken = null;
7083 private void updateScreenOffSleepToken(boolean acquire) {
7085 if (mScreenOffSleepToken == null) {
7086 mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff");
7089 if (mScreenOffSleepToken != null) {
7090 mScreenOffSleepToken.release();
7091 mScreenOffSleepToken = null;
7096 /** {@inheritDoc} */
7098 public void enableScreenAfterBoot() {
7100 applyLidSwitchState();
7101 updateRotation(true);
7104 private void applyLidSwitchState() {
7105 if (mLidState == LID_CLOSED && mLidControlsSleep) {
7106 mPowerManager.goToSleep(SystemClock.uptimeMillis(),
7107 PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
7108 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
7109 } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
7110 mWindowManagerFuncs.lockDeviceNow();
7113 synchronized (mLock) {
7114 updateWakeGestureListenerLp();
7118 void updateUiMode() {
7119 if (mUiModeManager == null) {
7120 mUiModeManager = IUiModeManager.Stub.asInterface(
7121 ServiceManager.getService(Context.UI_MODE_SERVICE));
7124 mUiMode = mUiModeManager.getCurrentModeType();
7125 } catch (RemoteException e) {
7129 void updateRotation(boolean alwaysSendConfiguration) {
7131 //set orientation on WindowManager
7132 mWindowManager.updateRotation(alwaysSendConfiguration, false);
7133 } catch (RemoteException e) {
7138 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
7140 //set orientation on WindowManager
7141 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
7142 } catch (RemoteException e) {
7148 * Return an Intent to launch the currently active dock app as home. Returns
7149 * null if the standard home should be launched, which is the case if any of the following is
7152 * <li>The device is not in either car mode or desk mode
7153 * <li>The device is in car mode but mEnableCarDockHomeCapture is false
7154 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
7155 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
7156 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
7158 * @return A dock intent.
7160 Intent createHomeDockIntent() {
7161 Intent intent = null;
7163 // What home does is based on the mode, not the dock state. That
7164 // is, when in car mode you should be taken to car home regardless
7165 // of whether we are actually in a car dock.
7166 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
7167 if (mEnableCarDockHomeCapture) {
7168 intent = mCarDockIntent;
7170 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
7171 if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
7172 intent = mDeskDockIntent;
7174 } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
7175 && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7176 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
7177 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
7178 // Always launch dock home from home when watch is docked, if it exists.
7179 intent = mDeskDockIntent;
7182 if (intent == null) {
7186 ActivityInfo ai = null;
7187 ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
7189 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
7192 ai = info.activityInfo;
7195 && ai.metaData != null
7196 && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
7197 intent = new Intent(intent);
7198 intent.setClassName(ai.packageName, ai.name);
7205 void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
7206 if (awakenFromDreams) {
7210 Intent dock = createHomeDockIntent();
7214 dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7216 startActivityAsUser(dock, UserHandle.CURRENT);
7218 } catch (ActivityNotFoundException e) {
7225 intent = new Intent(mHomeIntent);
7226 intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7228 intent = mHomeIntent;
7231 startActivityAsUser(intent, UserHandle.CURRENT);
7235 * goes to the home screen
7236 * @return whether it did anything
7239 if (!isUserSetupComplete()) {
7240 Slog.i(TAG, "Not going home because user setup is in progress.");
7244 // This code always brings home to the front.
7246 ActivityManagerNative.getDefault().stopAppSwitches();
7247 } catch (RemoteException e) {
7249 sendCloseSystemWindows();
7250 startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
7252 // This code brings home to the front or, if it is already
7253 // at the front, puts the device to sleep.
7255 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
7256 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
7257 Log.d(TAG, "UTS-TEST-MODE");
7259 ActivityManagerNative.getDefault().stopAppSwitches();
7260 sendCloseSystemWindows();
7261 Intent dock = createHomeDockIntent();
7263 int result = ActivityManagerNative.getDefault()
7264 .startActivityAsUser(null, null, dock,
7265 dock.resolveTypeIfNeeded(mContext.getContentResolver()),
7267 ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7268 null, null, UserHandle.USER_CURRENT);
7269 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7274 int result = ActivityManagerNative.getDefault()
7275 .startActivityAsUser(null, null, mHomeIntent,
7276 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
7278 ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7279 null, null, UserHandle.USER_CURRENT);
7280 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7283 } catch (RemoteException ex) {
7284 // bummer, the activity manager, which is in this process, is dead
7291 public void setCurrentOrientationLw(int newOrientation) {
7292 synchronized (mLock) {
7293 if (newOrientation != mCurrentAppOrientation) {
7294 mCurrentAppOrientation = newOrientation;
7295 updateOrientationListenerLp();
7300 private void performAuditoryFeedbackForAccessibilityIfNeed() {
7301 if (!isGlobalAccessibilityGestureEnabled()) {
7304 AudioManager audioManager = (AudioManager) mContext.getSystemService(
7305 Context.AUDIO_SERVICE);
7306 if (audioManager.isSilentMode()) {
7309 Ringtone ringTone = RingtoneManager.getRingtone(mContext,
7310 Settings.System.DEFAULT_NOTIFICATION_URI);
7311 ringTone.setStreamType(AudioManager.STREAM_MUSIC);
7315 private boolean isTheaterModeEnabled() {
7316 return Settings.Global.getInt(mContext.getContentResolver(),
7317 Settings.Global.THEATER_MODE_ON, 0) == 1;
7320 private boolean isGlobalAccessibilityGestureEnabled() {
7321 return Settings.Global.getInt(mContext.getContentResolver(),
7322 Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1;
7325 private boolean areSystemNavigationKeysEnabled() {
7326 return Settings.Secure.getIntForUser(mContext.getContentResolver(),
7327 Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
7331 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
7332 if (!mVibrator.hasVibrator()) {
7335 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
7336 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
7337 if (hapticsDisabled && !always) {
7340 long[] pattern = null;
7342 case HapticFeedbackConstants.LONG_PRESS:
7343 pattern = mLongPressVibePattern;
7345 case HapticFeedbackConstants.VIRTUAL_KEY:
7346 pattern = mVirtualKeyVibePattern;
7348 case HapticFeedbackConstants.KEYBOARD_TAP:
7349 pattern = mKeyboardTapVibePattern;
7351 case HapticFeedbackConstants.CLOCK_TICK:
7352 pattern = mClockTickVibePattern;
7354 case HapticFeedbackConstants.CALENDAR_DATE:
7355 pattern = mCalendarDateVibePattern;
7357 case HapticFeedbackConstants.SAFE_MODE_DISABLED:
7358 pattern = mSafeModeDisabledVibePattern;
7360 case HapticFeedbackConstants.SAFE_MODE_ENABLED:
7361 pattern = mSafeModeEnabledVibePattern;
7363 case HapticFeedbackConstants.CONTEXT_CLICK:
7364 pattern = mContextClickVibePattern;
7370 String owningPackage;
7372 owningUid = win.getOwningUid();
7373 owningPackage = win.getOwningPackage();
7375 owningUid = android.os.Process.myUid();
7376 owningPackage = mContext.getOpPackageName();
7378 if (pattern.length == 1) {
7379 // One-shot vibration
7380 mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES);
7382 // Pattern vibration
7383 mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES);
7389 public void keepScreenOnStartedLw() {
7393 public void keepScreenOnStoppedLw() {
7394 if (isKeyguardShowingAndNotOccluded()) {
7395 mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
7399 private int updateSystemUiVisibilityLw() {
7400 // If there is no window focused, there will be nobody to handle the events
7401 // anyway, so just hang on in whatever state we're in until things settle down.
7402 final WindowState win = mFocusedWindow != null ? mFocusedWindow
7403 : mTopFullscreenOpaqueWindowState;
7407 if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) {
7408 // We are updating at a point where the keyguard has gotten
7409 // focus, but we were last in a state where the top window is
7410 // hiding it. This is probably because the keyguard as been
7411 // shown while the top window was displayed, so we want to ignore
7412 // it here because this is just a very transient change and it
7413 // will quickly lose focus once it correctly gets hidden.
7417 int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
7418 & ~mResettingSystemUiFlags
7419 & ~mForceClearedSystemUiFlags;
7420 if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
7421 tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
7424 final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
7425 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
7426 final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
7427 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
7428 mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);
7429 mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);
7430 final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
7431 final int diff = visibility ^ mLastSystemUiFlags;
7432 final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
7433 final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
7434 final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
7435 if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
7436 && mFocusedApp == win.getAppToken()
7437 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
7438 && mLastDockedStackBounds.equals(mDockedStackBounds)) {
7441 mLastSystemUiFlags = visibility;
7442 mLastFullscreenStackSysUiFlags = fullscreenVisibility;
7443 mLastDockedStackSysUiFlags = dockedVisibility;
7444 mLastFocusNeedsMenu = needsMenu;
7445 mFocusedApp = win.getAppToken();
7446 final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
7447 final Rect dockedStackBounds = new Rect(mDockedStackBounds);
7448 mHandler.post(new Runnable() {
7451 StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
7452 if (statusbar != null) {
7453 statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
7454 dockedVisibility, 0xffffffff, fullscreenStackBounds,
7455 dockedStackBounds, win.toString());
7456 statusbar.topAppWindowChanged(needsMenu);
7463 private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
7464 WindowState statusColorWin = isStatusBarKeyguard() && !mHideLockScreen
7468 if (statusColorWin != null) {
7469 if (statusColorWin == opaque) {
7470 // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7472 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7473 vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
7474 & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7475 } else if (statusColorWin != null && statusColorWin.isDimming()) {
7476 // Otherwise if it's dimming, clear the light flag.
7477 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7483 private boolean drawsSystemBarBackground(WindowState win) {
7484 return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
7487 private boolean forcesDrawStatusBarBackground(WindowState win) {
7488 return win == null || (win.getAttrs().privateFlags
7489 & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
7492 private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
7493 final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
7494 final boolean freeformStackVisible =
7495 mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
7496 final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
7498 // We need to force system bars when the docked stack is visible, when the freeform stack
7499 // is visible but also when we are resizing for the transitions when docked stack
7500 // visibility changes.
7501 mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
7502 final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
7504 // apply translucent bar vis flags
7505 WindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen
7507 : mTopFullscreenOpaqueWindowState;
7508 vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7509 vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7510 final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
7511 mTopDockedOpaqueWindowState, 0, 0);
7513 final boolean fullscreenDrawsStatusBarBackground =
7514 (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
7515 && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
7516 || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
7517 final boolean dockedDrawsStatusBarBackground =
7518 (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
7519 && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
7520 || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
7522 // prevent status bar interaction from clearing certain flags
7523 int type = win.getAttrs().type;
7524 boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
7525 if (statusBarHasFocus && !isStatusBarKeyguard()) {
7526 int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
7527 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
7528 | View.SYSTEM_UI_FLAG_IMMERSIVE
7529 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
7530 | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7531 if (mHideLockScreen) {
7532 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
7534 vis = (vis & ~flags) | (oldVis & flags);
7537 if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
7538 vis |= View.STATUS_BAR_TRANSPARENT;
7539 vis &= ~View.STATUS_BAR_TRANSLUCENT;
7540 } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
7541 || forceOpaqueStatusBar) {
7542 vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
7545 vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
7547 // update status bar
7548 boolean immersiveSticky =
7549 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7550 final boolean hideStatusBarWM =
7551 mTopFullscreenOpaqueWindowState != null
7552 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
7553 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
7554 final boolean hideStatusBarSysui =
7555 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
7556 final boolean hideNavBarSysui =
7557 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
7559 final boolean transientStatusBarAllowed = mStatusBar != null
7560 && (statusBarHasFocus || (!mForceShowSystemBars
7561 && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
7563 final boolean transientNavBarAllowed = mNavigationBar != null
7564 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
7566 final long now = SystemClock.uptimeMillis();
7567 final boolean pendingPanic = mPendingPanicGestureUptime != 0
7568 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
7569 if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
7570 // The user performed the panic gesture recently, we're about to hide the bars,
7571 // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
7572 mPendingPanicGestureUptime = 0;
7573 mStatusBarController.showTransient();
7574 if (!isNavBarEmpty(vis)) {
7575 mNavigationBarController.showTransient();
7579 final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
7580 && !transientStatusBarAllowed && hideStatusBarSysui;
7581 final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
7582 && !transientNavBarAllowed;
7583 if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
7584 // clear the clearable flags instead
7585 clearClearableFlagsLw();
7586 vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
7589 final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
7590 immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7591 final boolean navAllowedHidden = immersive || immersiveSticky;
7593 if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType())
7594 > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) {
7595 // We can't hide the navbar from this window otherwise the input consumer would not get
7596 // the input events.
7597 vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
7600 vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
7602 // update navigation bar
7603 boolean oldImmersiveMode = isImmersiveMode(oldVis);
7604 boolean newImmersiveMode = isImmersiveMode(vis);
7605 if (win != null && oldImmersiveMode != newImmersiveMode) {
7606 final String pkg = win.getOwningPackage();
7607 mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
7608 isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility()));
7611 vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
7617 * @return the current visibility flags with the nav-bar opacity related flags toggled based
7618 * on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
7620 private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
7621 boolean freeformStackVisible, boolean isDockedDividerResizing) {
7622 if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
7623 if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
7624 visibility = setNavBarOpaqueFlag(visibility);
7626 } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
7627 if (isDockedDividerResizing) {
7628 visibility = setNavBarOpaqueFlag(visibility);
7629 } else if (freeformStackVisible) {
7630 visibility = setNavBarTranslucentFlag(visibility);
7632 visibility = setNavBarOpaqueFlag(visibility);
7636 if (!areTranslucentBarsAllowed()) {
7637 visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
7642 private int setNavBarOpaqueFlag(int visibility) {
7643 return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
7646 private int setNavBarTranslucentFlag(int visibility) {
7647 visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
7648 return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
7651 private void clearClearableFlagsLw() {
7652 int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
7653 if (newVal != mResettingSystemUiFlags) {
7654 mResettingSystemUiFlags = newVal;
7655 mWindowManagerFuncs.reevaluateStatusBarVisibility();
7659 private boolean isImmersiveMode(int vis) {
7660 final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
7661 return mNavigationBar != null
7662 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
7663 && (vis & flags) != 0
7664 && canHideNavigationBar();
7667 private static boolean isNavBarEmpty(int systemUiFlags) {
7668 final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
7669 | View.STATUS_BAR_DISABLE_BACK
7670 | View.STATUS_BAR_DISABLE_RECENT);
7672 return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
7676 * @return whether the navigation or status bar can be made translucent
7678 * This should return true unless touch exploration is not enabled or
7679 * R.boolean.config_enableTranslucentDecor is false.
7681 private boolean areTranslucentBarsAllowed() {
7682 return mTranslucentDecorEnabled;
7685 // Use this instead of checking config_showNavigationBar so that it can be consistently
7686 // overridden by qemu.hw.mainkeys in the emulator.
7688 public boolean hasNavigationBar() {
7689 return mHasNavigationBar;
7693 public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
7694 mLastInputMethodWindow = ime;
7695 mLastInputMethodTargetWindow = target;
7699 public int getInputMethodWindowVisibleHeightLw() {
7700 return mDockBottom - mCurBottom;
7704 public void setCurrentUserLw(int newUserId) {
7705 mCurrentUserId = newUserId;
7706 if (mKeyguardDelegate != null) {
7707 mKeyguardDelegate.setCurrentUser(newUserId);
7709 StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
7710 if (statusBar != null) {
7711 statusBar.setCurrentUser(newUserId);
7713 setLastInputMethodWindowLw(null, null);
7717 public boolean canMagnifyWindow(int windowType) {
7718 switch (windowType) {
7719 case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
7720 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
7721 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
7722 case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
7730 public boolean isTopLevelWindow(int windowType) {
7731 if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
7732 && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
7733 return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
7739 public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
7740 // For the upside down rotation we don't rotate seamlessly as the navigation
7741 // bar moves position.
7742 // Note most apps (using orientation:sensor or user as opposed to fullSensor)
7743 // will not enter the reverse portrait orientation, so actually the
7744 // orientation won't change at all.
7745 if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
7748 int delta = newRotation - oldRotation;
7749 if (delta < 0) delta += 4;
7750 // Likewise we don't rotate seamlessly for 180 degree rotations
7751 // in this case the surfaces never resize, and our logic to
7752 // revert the transformations on size change will fail. We could
7753 // fix this in the future with the "tagged" frames idea.
7754 if (delta == Surface.ROTATION_180) {
7758 final WindowState w = mTopFullscreenOpaqueWindowState;
7759 if (w != mFocusedWindow) {
7763 // We only enable seamless rotation if the top window has requested
7764 // it and is in the fullscreen opaque state. Seamless rotation
7765 // requires freezing various Surface states and won't work well
7766 // with animations, so we disable it in the animation case for now.
7767 if (w != null && !w.isAnimatingLw() &&
7768 ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) ||
7769 (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) {
7776 public void dump(String prefix, PrintWriter pw, String[] args) {
7777 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
7778 pw.print(" mSystemReady="); pw.print(mSystemReady);
7779 pw.print(" mSystemBooted="); pw.println(mSystemBooted);
7780 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
7781 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
7782 pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
7783 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
7784 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
7785 || mForceClearedSystemUiFlags != 0) {
7786 pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
7787 pw.print(Integer.toHexString(mLastSystemUiFlags));
7788 pw.print(" mResettingSystemUiFlags=0x");
7789 pw.print(Integer.toHexString(mResettingSystemUiFlags));
7790 pw.print(" mForceClearedSystemUiFlags=0x");
7791 pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
7793 if (mLastFocusNeedsMenu) {
7794 pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
7795 pw.println(mLastFocusNeedsMenu);
7797 pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
7798 pw.println(mWakeGestureEnabledSetting);
7800 pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
7801 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
7802 pw.print(" mDockMode="); pw.print(mDockMode);
7803 pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
7804 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
7805 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
7806 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
7807 pw.print(" mUserRotation="); pw.print(mUserRotation);
7808 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
7809 pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
7810 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
7811 pw.print(mCarDockEnablesAccelerometer);
7812 pw.print(" mDeskDockEnablesAccelerometer=");
7813 pw.println(mDeskDockEnablesAccelerometer);
7814 pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
7815 pw.print(mLidKeyboardAccessibility);
7816 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
7817 pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
7818 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
7820 pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
7822 pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
7823 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
7825 pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
7826 pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
7827 pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
7828 pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
7829 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
7830 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
7831 pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
7832 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
7833 pw.print(prefix); pw.print("mOrientationSensorEnabled=");
7834 pw.println(mOrientationSensorEnabled);
7835 pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
7836 pw.print(","); pw.print(mOverscanScreenTop);
7837 pw.print(") "); pw.print(mOverscanScreenWidth);
7838 pw.print("x"); pw.println(mOverscanScreenHeight);
7839 if (mOverscanLeft != 0 || mOverscanTop != 0
7840 || mOverscanRight != 0 || mOverscanBottom != 0) {
7841 pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
7842 pw.print(" top="); pw.print(mOverscanTop);
7843 pw.print(" right="); pw.print(mOverscanRight);
7844 pw.print(" bottom="); pw.println(mOverscanBottom);
7846 pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
7847 pw.print(mRestrictedOverscanScreenLeft);
7848 pw.print(","); pw.print(mRestrictedOverscanScreenTop);
7849 pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
7850 pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
7851 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
7852 pw.print(","); pw.print(mUnrestrictedScreenTop);
7853 pw.print(") "); pw.print(mUnrestrictedScreenWidth);
7854 pw.print("x"); pw.println(mUnrestrictedScreenHeight);
7855 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
7856 pw.print(","); pw.print(mRestrictedScreenTop);
7857 pw.print(") "); pw.print(mRestrictedScreenWidth);
7858 pw.print("x"); pw.println(mRestrictedScreenHeight);
7859 pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
7860 pw.print(","); pw.print(mStableFullscreenTop);
7861 pw.print(")-("); pw.print(mStableFullscreenRight);
7862 pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
7863 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
7864 pw.print(","); pw.print(mStableTop);
7865 pw.print(")-("); pw.print(mStableRight);
7866 pw.print(","); pw.print(mStableBottom); pw.println(")");
7867 pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
7868 pw.print(","); pw.print(mSystemTop);
7869 pw.print(")-("); pw.print(mSystemRight);
7870 pw.print(","); pw.print(mSystemBottom); pw.println(")");
7871 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
7872 pw.print(","); pw.print(mCurTop);
7873 pw.print(")-("); pw.print(mCurRight);
7874 pw.print(","); pw.print(mCurBottom); pw.println(")");
7875 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
7876 pw.print(","); pw.print(mContentTop);
7877 pw.print(")-("); pw.print(mContentRight);
7878 pw.print(","); pw.print(mContentBottom); pw.println(")");
7879 pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft);
7880 pw.print(","); pw.print(mVoiceContentTop);
7881 pw.print(")-("); pw.print(mVoiceContentRight);
7882 pw.print(","); pw.print(mVoiceContentBottom); pw.println(")");
7883 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
7884 pw.print(","); pw.print(mDockTop);
7885 pw.print(")-("); pw.print(mDockRight);
7886 pw.print(","); pw.print(mDockBottom); pw.println(")");
7887 pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
7888 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
7889 pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen);
7890 pw.print(" mShowingDream="); pw.print(mShowingDream);
7891 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
7892 pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
7893 if (mLastInputMethodWindow != null) {
7894 pw.print(prefix); pw.print("mLastInputMethodWindow=");
7895 pw.println(mLastInputMethodWindow);
7897 if (mLastInputMethodTargetWindow != null) {
7898 pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
7899 pw.println(mLastInputMethodTargetWindow);
7901 if (mStatusBar != null) {
7902 pw.print(prefix); pw.print("mStatusBar=");
7903 pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
7904 pw.println(isStatusBarKeyguard());
7906 if (mNavigationBar != null) {
7907 pw.print(prefix); pw.print("mNavigationBar=");
7908 pw.println(mNavigationBar);
7910 if (mFocusedWindow != null) {
7911 pw.print(prefix); pw.print("mFocusedWindow=");
7912 pw.println(mFocusedWindow);
7914 if (mFocusedApp != null) {
7915 pw.print(prefix); pw.print("mFocusedApp=");
7916 pw.println(mFocusedApp);
7918 if (mWinDismissingKeyguard != null) {
7919 pw.print(prefix); pw.print("mWinDismissingKeyguard=");
7920 pw.println(mWinDismissingKeyguard);
7922 if (mTopFullscreenOpaqueWindowState != null) {
7923 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
7924 pw.println(mTopFullscreenOpaqueWindowState);
7926 if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
7927 pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
7928 pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
7930 if (mForcingShowNavBar) {
7931 pw.print(prefix); pw.print("mForcingShowNavBar=");
7932 pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
7933 pw.println(mForcingShowNavBarLayer);
7935 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
7936 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
7937 pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
7938 pw.print(" mForceStatusBarFromKeyguard=");
7939 pw.println(mForceStatusBarFromKeyguard);
7940 pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
7941 pw.print(" mWinDismissingKeyguard="); pw.print(mWinDismissingKeyguard);
7942 pw.print(" mHomePressed="); pw.println(mHomePressed);
7943 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
7944 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
7945 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
7946 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
7947 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
7948 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
7949 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
7950 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
7951 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
7952 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
7953 pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
7954 pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
7955 pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
7957 mGlobalKeyManager.dump(prefix, pw);
7958 mStatusBarController.dump(pw, prefix);
7959 mNavigationBarController.dump(pw, prefix);
7960 PolicyControl.dump(prefix, pw);
7962 if (mWakeGestureListener != null) {
7963 mWakeGestureListener.dump(pw, prefix);
7965 if (mOrientationListener != null) {
7966 mOrientationListener.dump(pw, prefix);
7968 if (mBurnInProtectionHelper != null) {
7969 mBurnInProtectionHelper.dump(prefix, pw);
7971 if (mKeyguardDelegate != null) {
7972 mKeyguardDelegate.dump(prefix, pw);