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