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