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