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