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