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